diff --git a/.github/workflows/ebpf_kvm_watcher.yml b/.github/workflows/ebpf_kvm_watcher.yml index dc79c8d50..e90c618d5 100644 --- a/.github/workflows/ebpf_kvm_watcher.yml +++ b/.github/workflows/ebpf_kvm_watcher.yml @@ -19,10 +19,12 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - - - name: Test program execution + - name: Install dependencies run: | cd eBPF_Supermarket/kvm_watcher/ make deps - make - + - name: Test program execution + continue-on-error: true + run: | + cd eBPF_Supermarket/kvm_watcher/ + make \ No newline at end of file diff --git a/.github/workflows/ebpf_net_watcher.yml b/.github/workflows/ebpf_net_watcher.yml index ec987c429..025578510 100644 --- a/.github/workflows/ebpf_net_watcher.yml +++ b/.github/workflows/ebpf_net_watcher.yml @@ -45,4 +45,5 @@ jobs: sudo timeout -s SIGINT 5 ./netwatcher -k || if [[ $? != 124 && $? != 0 ]];then exit $?;fi sudo timeout -s SIGINT 5 ./netwatcher -k -T || if [[ $? != 124 && $? != 0 ]];then exit $?;fi sudo timeout -s SIGINT 5 ./netwatcher -I || if [[ $? != 124 && $? != 0 ]];then exit $?;fi + sudo timeout -s SIGINT 5 ./netwatcher -S || if [[ $? != 124 && $? != 0 ]];then exit $?;fi timeout-minutes: 5 diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index b29742b99..80522307c 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -30,8 +30,10 @@ jobs: run: | cd eBPF_Supermarket/Stack_Analyser make + sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 + gcc -o ./testdir/usdt_pthread ./testdir/usdt_pthread.c - sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -t 5 + sudo ./stack_analyzer probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -d 5 magic-eyes-build-and-test: runs-on: ubuntu-22.04 @@ -49,4 +51,5 @@ jobs: cd MagicEyes/build cmake -DBUILD_STACK_ANALYZER=ON .. make - sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe u:pthread:pthread_create -c "../../eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread" -t 5 \ No newline at end of file + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe u:pthread:pthread_create -c "../../eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread" -d 5 diff --git a/MagicEyes/CMakeLists.txt b/MagicEyes/CMakeLists.txt index 682302408..549a17dfa 100644 --- a/MagicEyes/CMakeLists.txt +++ b/MagicEyes/CMakeLists.txt @@ -12,8 +12,8 @@ # ----------------------------------------------------------------------------------------- cmake_minimum_required(VERSION 3.10) -set(CMAKE_C_COMPILER clang) -set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) set(PROJECT_NAME MagicEyes) project(${PROJECT_NAME}) @@ -45,6 +45,20 @@ elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "riscv64") elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") set(ARCH "loongarch") endif() + +#lht增加:不同编译环境下,构建libbpf和bpftool的编译选项 +set(CROSS_COMPILE "") +set(CC ${CMAKE_C_COMPILER}) + +#lht增加:cmake -Dcross_compilation_arm64=ON .. 来配置交叉编译arm64的环境 +if(DEFINED TARCH AND TARCH STREQUAL arm64 OR TARCH STREQUAL aarch64) + message(STATUS "Cross-compilation for arm64 is enabled.") + set(ARCH "arm64") + include(${PROJECT_SOURCE_DIR}/platforms/aarch64/arm64_linux_setup.cmake) +else() +endif() + + # 判断CPU架构 # if (NOT DEFINED OS_ARCH) # string(TOLOWER ${CMAKE_HOST_SYSTEM_PROCESSOR} OS_ARCH) @@ -89,13 +103,15 @@ ExternalProject_Add(libbpf SOURCE_DIR ${CMAKE_SOURCE_DIR}/libbpf/src CONFIGURE_COMMAND "" BUILD_COMMAND make - BUILD_STATIC_ONLY=1 - OBJDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf - DESTDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf - INCLUDEDIR= - LIBDIR= - UAPIDIR= - install install_uapi_headers + ARCH=${ARCH} + CC=${CC} + BUILD_STATIC_ONLY=1 + OBJDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf + DESTDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf + INCLUDEDIR= + LIBDIR= + UAPIDIR= + install install_uapi_headers BUILD_IN_SOURCE TRUE INSTALL_COMMAND "" STEP_TARGETS build @@ -105,8 +121,11 @@ ExternalProject_Add(bpftool PREFIX bpftool SOURCE_DIR ${CMAKE_SOURCE_DIR}/bpftool/src CONFIGURE_COMMAND "" - BUILD_COMMAND make bootstrap - OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/bpftool/ + BUILD_COMMAND make + ARCH=${ARCH} + CROSS_COMPILE=${CROSS_COMPILE} + bootstrap + OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/bpftool/ BUILD_IN_SOURCE TRUE INSTALL_COMMAND "" STEP_TARGETS build diff --git a/MagicEyes/README.md b/MagicEyes/README.md index e2f5a016d..ab037d676 100644 --- a/MagicEyes/README.md +++ b/MagicEyes/README.md @@ -1,33 +1,50 @@ # MagicEyes + ## 1. 简介 + 一款用于Linux内核的可观测性定制工具,覆盖CPU、内存、网络、文件、虚拟化等子系统。 母项目直达:[lmp](https://github.com/linuxkerneltravel/lmp) + ## 2. 架构 + ![basic_arch](./docs/introduction/images_dir/basic_arch.png) + ## 3. 目前已有的工具 + - 文件系统部分 -- [x] fs_watcher + - [x] fs_watcher + - 内存部分 -- [x] mem_watcher + - [x] mem_watcher + - 网络部分 -- [x] net_watcher + - [x] net_watcher + - CPU部分 -- [x] cpu_watcher -- [x] proc_image + - [x] cpu_watcher + - [x] proc_image + - 虚拟化部分 -- [x] kvm_watcher + - [x] kvm_watcher + - 系统诊断与调优 -- [x] stack_analyzer + - [x] stack_analyzer + ## 4. 编译安装 + ```bash -git clone git clone --recurse-submodules +git clone --recurse-submodules mkdir build && cd build -# 编译所有工具 -cmake -DBUILD_ALL=ON -D -DCMAKE_INSTALL_PREFIX= .. -# 编译单独某个工具,如 fs_watcher +# ------------------------------------------------------- +# 若想要编译所有工具 +cmake -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX= .. +# 若想要编译单独某个工具,如 fs_watcher cmake -DBUILD_FS_WATCHER=ON .. +# 若想在x64平台交叉编译出arm64平台的程序(TARCH 即 target arch) +cmake -DBUILD_ALL=ON -DTARCH=arm64 .. +# ------------------------------------------------------- make make install ``` diff --git a/MagicEyes/platforms/aarch64/README.md b/MagicEyes/platforms/aarch64/README.md index 3446f83a0..7ec8326f5 100644 --- a/MagicEyes/platforms/aarch64/README.md +++ b/MagicEyes/platforms/aarch64/README.md @@ -1 +1,31 @@ -ARM64平台交叉编译工具链 \ No newline at end of file +# ARM64平台交叉编译工具链 + +## How to install aarch64-linux-gnu- compilation tools for cross-compilation? + +1. install the Ubuntu toolchain gcc-aarch64-linux-gnu GNU C compiler for the arm64 architecture + +``` sudo apt-get install gcc-aarch64-linux-gnu ``` + + + +2. export the environment variable ARCH and CROSS_COMPILE + +``` export ARCH=arm64 && export CROSS_COMPILE=/usr/bin/aarch64-linux-gnu- ``` + + + +3. After done before installation, cmake will automatically detect the cross-compilation tools. + + + + +## What is the arm64_linux_setup.cmake? + +This file is a cmake module used to set the arm64 cross-compilation environment in the cmake project. + + + + +## What is the dependency directory? + +The dependency directory is used to store the dependent libraries for arm64 cross-compilation. diff --git a/MagicEyes/platforms/aarch64/arm64_linux_setup.cmake b/MagicEyes/platforms/aarch64/arm64_linux_setup.cmake new file mode 100644 index 000000000..65e044d55 --- /dev/null +++ b/MagicEyes/platforms/aarch64/arm64_linux_setup.cmake @@ -0,0 +1,33 @@ +set(CMAKE_SYSTEM_NAME Linux) #设置目标系统名字 +set(CMAKE_SYSTEM_PROCESSOR arm64) #设置目标处理器架构 + +#设置libbpf和bpftool的make编译选项 +set(CROSS_COMPILE "aarch64-linux-gnu-") + +#检查交叉编译链是否存在于系统环境变量中,不存在报错结束 +find_program(CMAKE_C_COMPILE_PATH NAMES ${CMAKE_C_COMPILER} PATHS $ENV{PATH}) +find_program(CMAKE_CXX_COMPILE_PATH NAMES ${CMAKE_CXX_COMPILER} PATHS $ENV{PATH}) +if(NOT CMAKE_C_COMPILE_PATH OR NOT CMAKE_CXX_COMPILE_PATH) + message(FATAL_ERROR "Can't find aarch64 compiler, please add it to system environment variable!") +endif() + +# 指定交叉编译链 +set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) +message(STATUS "The C compiler identification is ${CMAKE_C_COMPILER} now") +message(STATUS "The CXX compiler identification is ${CMAKE_CXX_COMPILER} now") + +set(CC ${CMAKE_C_COMPILER}) + + +#引入libbpf的依赖库zlib, elf +set(ZLIB_ARM64_DIR "${PROJECT_SOURCE_DIR}/platforms/aarch64/dependency/zlib-1.3.1/lib") +set(ELF_ARM64_DIR "${PROJECT_SOURCE_DIR}/platforms/aarch64/dependency/elfutils-0.189/lib") +set(ZLIB_SOURCE_DIR ${PROJECT_SOURCE_DIR}/platforms/aarch64/dependency/zlib-1.3.1/) +set(ELF_SOURCE_DIR ${PROJECT_SOURCE_DIR}/platforms/aarch64/dependency/elfutils-0.189/) +include_directories( + ${ZLIB_SOURCE_DIR}/include + ${ELF_SOURCE_DIR}/include) + +message(STATUS "Arm64 cross-compilation set-up run successfully") +#bpf.c 使用clang编译,.c使用gcc编译 \ No newline at end of file diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-addr2line b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-addr2line new file mode 100755 index 000000000..f3aff95f6 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-addr2line differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ar b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ar new file mode 100755 index 000000000..59b706f65 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ar differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfclassify b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfclassify new file mode 100755 index 000000000..dc950ef2b Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfclassify differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcmp b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcmp new file mode 100755 index 000000000..1fe8c609f Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcmp differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcompress b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcompress new file mode 100755 index 000000000..b1c75e6bd Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elfcompress differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elflint b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elflint new file mode 100755 index 000000000..f50640097 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-elflint differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-findtextrel b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-findtextrel new file mode 100755 index 000000000..2b949ba2b Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-findtextrel differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-make-debug-archive b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-make-debug-archive new file mode 100755 index 000000000..1d6b986b6 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-make-debug-archive @@ -0,0 +1,132 @@ +#!/bin/sh +# +# Script to make an offline archive for debugging with libdwfl-based tools. +# +# make-debug-archive ARCHIVE {options} +# make-debug-archive --kernel [--force] [RELEASE] +# +# Valid options are those listed under 'Input selection options' +# by running /home/jerry/Downloads/toolchain/elfutils-0.189/_install/bin/eu-unstrip --help. +# +# The archive installed by --kernel be used automatically by -K. +# An offline archive can be used via -e in any tool that accepts those options. +# + +UNSTRIP=${UNSTRIP:-/home/jerry/Downloads/toolchain/elfutils-0.189/_install/bin/eu-unstrip} +AR=${AR:-/home/jerry/Downloads/toolchain/elfutils-0.189/_install/bin/eu-ar} +SUDO=${SUDO:-/usr/bin/sudo} + +LS=/bin/ls +RM=/bin/rm +MV=/bin/mv +MKDIR=/bin/mkdir +XARGS=/usr/bin/xargs + +outdir=${TMPDIR:-/tmp}/debugar$$ + +usage() +{ + echo "Usage: $0 ARCHIVE {options}" + echo " or: $0 --kernel [--sudo] [--force] [RELEASE]" + echo + echo "Valid options are listed under 'Input selection options'" + echo "when running: $UNSTRIP --help" + echo + echo "The --kernel form updates the file used by -K if the" + echo "kernel installation has changed, or always with --force." + echo "With --sudo, touches the installed file via $SUDO." +} + +fatal_usage() +{ + usage >&2 + exit 2 +} + +script_version() +{ + echo "`basename $0` (elfutils) 0.189" + echo "Copyright (C) 2007 Red Hat, Inc." + echo "This is free software; see the source for copying conditions." + echo "There is NO warranty; not even for MERCHANTABILITY or" + echo "FITNESS FOR A PARTICULAR PURPOSE." + echo "Written by Roland McGrath." +} + +sudo= +kernel=no +force_kernel=no +while [ $# -gt 0 ]; do + case "x$1" in + x--help) usage; exit 0 ;; + x--version) script_version; exit 0 ;; + x--kernel) kernel=yes ;; + x--force) force_kernel=yes ;; + x--sudo) sudo=$SUDO ;; + *) break ;; + esac + shift +done + +if [ $kernel = no ] && [ $force_kernel = yes -o -n "$sudo" ]; then + usage +fi + +if [ $kernel = yes ]; then + if [ $# -eq 0 ]; then + release=`uname -r` + elif [ $# -eq 1 ]; then + release=$1 + else + fatal_usage + fi + + dir=/usr/lib/debug/lib/modules/$release + archive=$dir/debug.a + dep=/lib/modules/$release/modules.dep + + if [ ! -d $dir ]; then + echo >&2 "$0: $dir not installed" + exit 1 + fi + + # Without --force, bail if the kernel installation is not newer. + # This file is normally touched by installing new kernels or modules. + if [ $force_kernel = no -a "$archive" -nt "$dep" ]; then + exit 0 + fi + + # We have to kill the old one first, because our own -K would use it. + [ ! -e "$archive" ] || $sudo $RM -f "$archive" || exit + + set "$archive" "-K$release" +fi + +if [ $# -lt 2 ]; then + fatal_usage +fi + +archive="$1" +shift + +case "$archive" in +/*) ;; +*) archive="`/bin/pwd`/$archive" ;; +esac + +if [ -z "$sudo" ]; then + new_archive="$archive.new" +else + new_archive="$outdir.a" +fi + +$RM -f "$new_archive" || exit + +trap '$RM -rf "$outdir" "$new_archive"' 0 1 2 15 + +$MKDIR "$outdir" && +$UNSTRIP -d "$outdir" -m -a -R "$@" && +(cd "$outdir" && $LS | $XARGS $AR cq "$new_archive") && +$sudo $MV -f "$new_archive" "$archive" + +exit diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-nm b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-nm new file mode 100755 index 000000000..a6ca3d323 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-nm differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-objdump b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-objdump new file mode 100755 index 000000000..f9e0750bd Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-objdump differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ranlib b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ranlib new file mode 100755 index 000000000..087671850 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-ranlib differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-readelf b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-readelf new file mode 100755 index 000000000..4b3c801ea Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-readelf differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-size b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-size new file mode 100755 index 000000000..5aa767e4b Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-size differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-stack b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-stack new file mode 100755 index 000000000..7c8c94588 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-stack differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strings b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strings new file mode 100755 index 000000000..69f5ca778 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strings differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strip b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strip new file mode 100755 index 000000000..3a8e7f6a4 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-strip differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-unstrip b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-unstrip new file mode 100755 index 000000000..6aa28d39b Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/bin/eu-unstrip differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/dwarf.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/dwarf.h new file mode 100644 index 000000000..b2e49db2c --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/dwarf.h @@ -0,0 +1,1050 @@ +/* This file defines standard DWARF types, structures, and macros. + Copyright (C) 2000-2011, 2014, 2016, 2017, 2018 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _DWARF_H +#define _DWARF_H 1 + +/* DWARF Unit Header Types. */ +enum + { + DW_UT_compile = 0x01, + DW_UT_type = 0x02, + DW_UT_partial = 0x03, + DW_UT_skeleton = 0x04, + DW_UT_split_compile = 0x05, + DW_UT_split_type = 0x06, + + DW_UT_lo_user = 0x80, + DW_UT_hi_user = 0xff + }; + +/* DWARF tags. */ +enum + { + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + /* 0x06 reserved. */ + /* 0x07 reserved. */ + DW_TAG_imported_declaration = 0x08, + /* 0x09 reserved. */ + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + /* 0x0c reserved. */ + DW_TAG_member = 0x0d, + /* 0x0e reserved. */ + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + /* 0x14 reserved. */ + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + /* 0x3e reserved. Was DW_TAG_mutable_type. */ + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_type_unit = 0x41, + DW_TAG_rvalue_reference_type = 0x42, + DW_TAG_template_alias = 0x43, + DW_TAG_coarray_type = 0x44, + DW_TAG_generic_subrange = 0x45, + DW_TAG_dynamic_type = 0x46, + DW_TAG_atomic_type = 0x47, + DW_TAG_call_site = 0x48, + DW_TAG_call_site_parameter = 0x49, + DW_TAG_skeleton_unit = 0x4a, + DW_TAG_immutable_type = 0x4b, + + DW_TAG_lo_user = 0x4080, + + DW_TAG_MIPS_loop = 0x4081, + DW_TAG_format_label = 0x4101, + DW_TAG_function_template = 0x4102, + DW_TAG_class_template = 0x4103, + + DW_TAG_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105, + + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, + DW_TAG_GNU_call_site = 0x4109, + DW_TAG_GNU_call_site_parameter = 0x410a, + + DW_TAG_hi_user = 0xffff + }; + + +/* Children determination encodings. */ +enum + { + DW_CHILDREN_no = 0, + DW_CHILDREN_yes = 1 + }; + + +/* DWARF attributes encodings. */ +enum + { + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + /* 0x04 reserved. */ + /* 0x05 reserved. */ + /* 0x06 reserved. */ + /* 0x07 reserved. */ + /* 0x08 reserved. */ + DW_AT_ordering = 0x09, + /* 0x0a reserved. */ + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, /* Deprecated in DWARF4. */ + DW_AT_bit_size = 0x0d, + /* 0x0e reserved. */ + /* 0x0f reserved. */ + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + /* 0x14 reserved. */ + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + /* 0x1f reserved. */ + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + /* 0x23 reserved. */ + /* 0x24 reserved. */ + DW_AT_producer = 0x25, + /* 0x26 reserved. */ + DW_AT_prototyped = 0x27, + /* 0x28 reserved. */ + /* 0x29 reserved. */ + DW_AT_return_addr = 0x2a, + /* 0x2b reserved. */ + DW_AT_start_scope = 0x2c, + /* 0x2d reserved. */ + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + /* 0x30 reserved. */ + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, /* Deprecated in DWARF5. */ + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_rnglists_base = 0x74, + /* 0x75 reserved. */ + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_macros = 0x79, + DW_AT_call_all_calls = 0x7a, + DW_AT_call_all_source_calls = 0x7b, + DW_AT_call_all_tail_calls = 0x7c, + DW_AT_call_return_pc = 0x7d, + DW_AT_call_value = 0x7e, + DW_AT_call_origin = 0x7f, + DW_AT_call_parameter = 0x80, + DW_AT_call_pc = 0x81, + DW_AT_call_tail_call = 0x82, + DW_AT_call_target = 0x83, + DW_AT_call_target_clobbered = 0x84, + DW_AT_call_data_location = 0x85, + DW_AT_call_data_value = 0x86, + DW_AT_noreturn = 0x87, + DW_AT_alignment = 0x88, + DW_AT_export_symbols = 0x89, + DW_AT_deleted = 0x8a, + DW_AT_defaulted = 0x8b, + DW_AT_loclists_base = 0x8c, + + DW_AT_lo_user = 0x2000, + + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + DW_AT_MIPS_stride_byte = 0x200c, + DW_AT_MIPS_stride_elem = 0x200d, + DW_AT_MIPS_ptr_dopetype = 0x200e, + DW_AT_MIPS_allocatable_dopetype = 0x200f, + DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + DW_AT_MIPS_assumed_size = 0x2011, + + /* GNU extensions. */ + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_guarded_by = 0x2108, + DW_AT_GNU_pt_guarded_by = 0x2109, + DW_AT_GNU_guarded = 0x210a, + DW_AT_GNU_pt_guarded = 0x210b, + DW_AT_GNU_locks_excluded = 0x210c, + DW_AT_GNU_exclusive_locks_required = 0x210d, + DW_AT_GNU_shared_locks_required = 0x210e, + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_call_site_value = 0x2111, + DW_AT_GNU_call_site_data_value = 0x2112, + DW_AT_GNU_call_site_target = 0x2113, + DW_AT_GNU_call_site_target_clobbered = 0x2114, + DW_AT_GNU_tail_call = 0x2115, + DW_AT_GNU_all_tail_call_sites = 0x2116, + DW_AT_GNU_all_call_sites = 0x2117, + DW_AT_GNU_all_source_call_sites = 0x2118, + DW_AT_GNU_locviews = 0x2137, + DW_AT_GNU_entry_view = 0x2138, + DW_AT_GNU_macros = 0x2119, + DW_AT_GNU_deleted = 0x211a, + /* GNU Debug Fission extensions. */ + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, + + /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator */ + DW_AT_GNU_numerator = 0x2303, + DW_AT_GNU_denominator = 0x2304, + /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias */ + DW_AT_GNU_bias = 0x2305, + + DW_AT_hi_user = 0x3fff + }; + +/* Old unofficially attribute names. Should not be used. + Will not appear in known-dwarf.h */ + +/* DWARF1 array subscripts and element data types. */ +#define DW_AT_subscr_data 0x0a +/* DWARF1 enumeration literals. */ +#define DW_AT_element_list 0x0f +/* DWARF1 reference for variable to member structure, class or union. */ +#define DW_AT_member 0x14 + +/* DWARF form encodings. */ +enum + { + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_strx = 0x1a, + DW_FORM_addrx = 0x1b, + DW_FORM_ref_sup4 = 0x1c, + DW_FORM_strp_sup = 0x1d, + DW_FORM_data16 = 0x1e, + DW_FORM_line_strp = 0x1f, + DW_FORM_ref_sig8 = 0x20, + DW_FORM_implicit_const = 0x21, + DW_FORM_loclistx = 0x22, + DW_FORM_rnglistx = 0x23, + DW_FORM_ref_sup8 = 0x24, + DW_FORM_strx1 = 0x25, + DW_FORM_strx2 = 0x26, + DW_FORM_strx3 = 0x27, + DW_FORM_strx4 = 0x28, + DW_FORM_addrx1 = 0x29, + DW_FORM_addrx2 = 0x2a, + DW_FORM_addrx3 = 0x2b, + DW_FORM_addrx4 = 0x2c, + + /* GNU Debug Fission extensions. */ + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + + DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */ + DW_FORM_GNU_strp_alt = 0x1f21 /* offset in alternate .debug_str. */ + }; + + +/* DWARF location operation encodings. */ +enum + { + DW_OP_addr = 0x03, /* Constant address. */ + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, /* Unsigned 1-byte constant. */ + DW_OP_const1s = 0x09, /* Signed 1-byte constant. */ + DW_OP_const2u = 0x0a, /* Unsigned 2-byte constant. */ + DW_OP_const2s = 0x0b, /* Signed 2-byte constant. */ + DW_OP_const4u = 0x0c, /* Unsigned 4-byte constant. */ + DW_OP_const4s = 0x0d, /* Signed 4-byte constant. */ + DW_OP_const8u = 0x0e, /* Unsigned 8-byte constant. */ + DW_OP_const8s = 0x0f, /* Signed 8-byte constant. */ + DW_OP_constu = 0x10, /* Unsigned LEB128 constant. */ + DW_OP_consts = 0x11, /* Signed LEB128 constant. */ + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, /* 1-byte stack index. */ + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, /* Unsigned LEB128 addend. */ + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_bra = 0x28, /* Signed 2-byte constant. */ + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_skip = 0x2f, /* Signed 2-byte constant. */ + DW_OP_lit0 = 0x30, /* Literal 0. */ + DW_OP_lit1 = 0x31, /* Literal 1. */ + DW_OP_lit2 = 0x32, /* Literal 2. */ + DW_OP_lit3 = 0x33, /* Literal 3. */ + DW_OP_lit4 = 0x34, /* Literal 4. */ + DW_OP_lit5 = 0x35, /* Literal 5. */ + DW_OP_lit6 = 0x36, /* Literal 6. */ + DW_OP_lit7 = 0x37, /* Literal 7. */ + DW_OP_lit8 = 0x38, /* Literal 8. */ + DW_OP_lit9 = 0x39, /* Literal 9. */ + DW_OP_lit10 = 0x3a, /* Literal 10. */ + DW_OP_lit11 = 0x3b, /* Literal 11. */ + DW_OP_lit12 = 0x3c, /* Literal 12. */ + DW_OP_lit13 = 0x3d, /* Literal 13. */ + DW_OP_lit14 = 0x3e, /* Literal 14. */ + DW_OP_lit15 = 0x3f, /* Literal 15. */ + DW_OP_lit16 = 0x40, /* Literal 16. */ + DW_OP_lit17 = 0x41, /* Literal 17. */ + DW_OP_lit18 = 0x42, /* Literal 18. */ + DW_OP_lit19 = 0x43, /* Literal 19. */ + DW_OP_lit20 = 0x44, /* Literal 20. */ + DW_OP_lit21 = 0x45, /* Literal 21. */ + DW_OP_lit22 = 0x46, /* Literal 22. */ + DW_OP_lit23 = 0x47, /* Literal 23. */ + DW_OP_lit24 = 0x48, /* Literal 24. */ + DW_OP_lit25 = 0x49, /* Literal 25. */ + DW_OP_lit26 = 0x4a, /* Literal 26. */ + DW_OP_lit27 = 0x4b, /* Literal 27. */ + DW_OP_lit28 = 0x4c, /* Literal 28. */ + DW_OP_lit29 = 0x4d, /* Literal 29. */ + DW_OP_lit30 = 0x4e, /* Literal 30. */ + DW_OP_lit31 = 0x4f, /* Literal 31. */ + DW_OP_reg0 = 0x50, /* Register 0. */ + DW_OP_reg1 = 0x51, /* Register 1. */ + DW_OP_reg2 = 0x52, /* Register 2. */ + DW_OP_reg3 = 0x53, /* Register 3. */ + DW_OP_reg4 = 0x54, /* Register 4. */ + DW_OP_reg5 = 0x55, /* Register 5. */ + DW_OP_reg6 = 0x56, /* Register 6. */ + DW_OP_reg7 = 0x57, /* Register 7. */ + DW_OP_reg8 = 0x58, /* Register 8. */ + DW_OP_reg9 = 0x59, /* Register 9. */ + DW_OP_reg10 = 0x5a, /* Register 10. */ + DW_OP_reg11 = 0x5b, /* Register 11. */ + DW_OP_reg12 = 0x5c, /* Register 12. */ + DW_OP_reg13 = 0x5d, /* Register 13. */ + DW_OP_reg14 = 0x5e, /* Register 14. */ + DW_OP_reg15 = 0x5f, /* Register 15. */ + DW_OP_reg16 = 0x60, /* Register 16. */ + DW_OP_reg17 = 0x61, /* Register 17. */ + DW_OP_reg18 = 0x62, /* Register 18. */ + DW_OP_reg19 = 0x63, /* Register 19. */ + DW_OP_reg20 = 0x64, /* Register 20. */ + DW_OP_reg21 = 0x65, /* Register 21. */ + DW_OP_reg22 = 0x66, /* Register 22. */ + DW_OP_reg23 = 0x67, /* Register 24. */ + DW_OP_reg24 = 0x68, /* Register 24. */ + DW_OP_reg25 = 0x69, /* Register 25. */ + DW_OP_reg26 = 0x6a, /* Register 26. */ + DW_OP_reg27 = 0x6b, /* Register 27. */ + DW_OP_reg28 = 0x6c, /* Register 28. */ + DW_OP_reg29 = 0x6d, /* Register 29. */ + DW_OP_reg30 = 0x6e, /* Register 30. */ + DW_OP_reg31 = 0x6f, /* Register 31. */ + DW_OP_breg0 = 0x70, /* Base register 0. */ + DW_OP_breg1 = 0x71, /* Base register 1. */ + DW_OP_breg2 = 0x72, /* Base register 2. */ + DW_OP_breg3 = 0x73, /* Base register 3. */ + DW_OP_breg4 = 0x74, /* Base register 4. */ + DW_OP_breg5 = 0x75, /* Base register 5. */ + DW_OP_breg6 = 0x76, /* Base register 6. */ + DW_OP_breg7 = 0x77, /* Base register 7. */ + DW_OP_breg8 = 0x78, /* Base register 8. */ + DW_OP_breg9 = 0x79, /* Base register 9. */ + DW_OP_breg10 = 0x7a, /* Base register 10. */ + DW_OP_breg11 = 0x7b, /* Base register 11. */ + DW_OP_breg12 = 0x7c, /* Base register 12. */ + DW_OP_breg13 = 0x7d, /* Base register 13. */ + DW_OP_breg14 = 0x7e, /* Base register 14. */ + DW_OP_breg15 = 0x7f, /* Base register 15. */ + DW_OP_breg16 = 0x80, /* Base register 16. */ + DW_OP_breg17 = 0x81, /* Base register 17. */ + DW_OP_breg18 = 0x82, /* Base register 18. */ + DW_OP_breg19 = 0x83, /* Base register 19. */ + DW_OP_breg20 = 0x84, /* Base register 20. */ + DW_OP_breg21 = 0x85, /* Base register 21. */ + DW_OP_breg22 = 0x86, /* Base register 22. */ + DW_OP_breg23 = 0x87, /* Base register 23. */ + DW_OP_breg24 = 0x88, /* Base register 24. */ + DW_OP_breg25 = 0x89, /* Base register 25. */ + DW_OP_breg26 = 0x8a, /* Base register 26. */ + DW_OP_breg27 = 0x8b, /* Base register 27. */ + DW_OP_breg28 = 0x8c, /* Base register 28. */ + DW_OP_breg29 = 0x8d, /* Base register 29. */ + DW_OP_breg30 = 0x8e, /* Base register 30. */ + DW_OP_breg31 = 0x8f, /* Base register 31. */ + DW_OP_regx = 0x90, /* Unsigned LEB128 register. */ + DW_OP_fbreg = 0x91, /* Signed LEB128 offset. */ + DW_OP_bregx = 0x92, /* ULEB128 register followed by SLEB128 off. */ + DW_OP_piece = 0x93, /* ULEB128 size of piece addressed. */ + DW_OP_deref_size = 0x94, /* 1-byte size of data retrieved. */ + DW_OP_xderef_size = 0x95, /* 1-byte size of data retrieved. */ + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b,/* TLS offset to address in current thread */ + DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI. */ + DW_OP_bit_piece = 0x9d, /* ULEB128 size and ULEB128 offset in bits. */ + DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode. */ + DW_OP_stack_value = 0x9f, /* No operands, special like DW_OP_piece. */ + + DW_OP_implicit_pointer = 0xa0, + DW_OP_addrx = 0xa1, + DW_OP_constx = 0xa2, + DW_OP_entry_value = 0xa3, + DW_OP_const_type = 0xa4, + DW_OP_regval_type = 0xa5, + DW_OP_deref_type = 0xa6, + DW_OP_xderef_type = 0xa7, + DW_OP_convert = 0xa8, + DW_OP_reinterpret = 0xa9, + + /* GNU extensions. */ + DW_OP_GNU_push_tls_address = 0xe0, + DW_OP_GNU_uninit = 0xf0, + DW_OP_GNU_encoded_addr = 0xf1, + DW_OP_GNU_implicit_pointer = 0xf2, + DW_OP_GNU_entry_value = 0xf3, + DW_OP_GNU_const_type = 0xf4, + DW_OP_GNU_regval_type = 0xf5, + DW_OP_GNU_deref_type = 0xf6, + DW_OP_GNU_convert = 0xf7, + DW_OP_GNU_reinterpret = 0xf9, + DW_OP_GNU_parameter_ref = 0xfa, + + /* GNU Debug Fission extensions. */ + DW_OP_GNU_addr_index = 0xfb, + DW_OP_GNU_const_index = 0xfc, + + DW_OP_GNU_variable_value = 0xfd, + + DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */ + DW_OP_hi_user = 0xff /* Implementation-defined range end. */ + }; + + +/* DWARF base type encodings. */ +enum + { + DW_ATE_void = 0x0, + DW_ATE_address = 0x1, + DW_ATE_boolean = 0x2, + DW_ATE_complex_float = 0x3, + DW_ATE_float = 0x4, + DW_ATE_signed = 0x5, + DW_ATE_signed_char = 0x6, + DW_ATE_unsigned = 0x7, + DW_ATE_unsigned_char = 0x8, + DW_ATE_imaginary_float = 0x9, + DW_ATE_packed_decimal = 0xa, + DW_ATE_numeric_string = 0xb, + DW_ATE_edited = 0xc, + DW_ATE_signed_fixed = 0xd, + DW_ATE_unsigned_fixed = 0xe, + DW_ATE_decimal_float = 0xf, + DW_ATE_UTF = 0x10, + DW_ATE_UCS = 0x11, + DW_ATE_ASCII = 0x12, + + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff + }; + + +/* DWARF decimal sign encodings. */ +enum + { + DW_DS_unsigned = 1, + DW_DS_leading_overpunch = 2, + DW_DS_trailing_overpunch = 3, + DW_DS_leading_separate = 4, + DW_DS_trailing_separate = 5, + }; + + +/* DWARF endianity encodings. */ +enum + { + DW_END_default = 0, + DW_END_big = 1, + DW_END_little = 2, + + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff + }; + + +/* DWARF accessibility encodings. */ +enum + { + DW_ACCESS_public = 1, + DW_ACCESS_protected = 2, + DW_ACCESS_private = 3 + }; + + +/* DWARF visibility encodings. */ +enum + { + DW_VIS_local = 1, + DW_VIS_exported = 2, + DW_VIS_qualified = 3 + }; + + +/* DWARF virtuality encodings. */ +enum + { + DW_VIRTUALITY_none = 0, + DW_VIRTUALITY_virtual = 1, + DW_VIRTUALITY_pure_virtual = 2 + }; + + +/* DWARF language encodings. */ +enum + { + DW_LANG_C89 = 0x0001, /* ISO C:1989 */ + DW_LANG_C = 0x0002, /* C */ + DW_LANG_Ada83 = 0x0003, /* ISO Ada:1983 */ + DW_LANG_C_plus_plus = 0x0004, /* ISO C++:1998 */ + DW_LANG_Cobol74 = 0x0005, /* ISO Cobol:1974 */ + DW_LANG_Cobol85 = 0x0006, /* ISO Cobol:1985 */ + DW_LANG_Fortran77 = 0x0007, /* ISO FORTRAN 77 */ + DW_LANG_Fortran90 = 0x0008, /* ISO Fortran 90 */ + DW_LANG_Pascal83 = 0x0009, /* ISO Pascal:1983 */ + DW_LANG_Modula2 = 0x000a, /* ISO Modula-2:1996 */ + DW_LANG_Java = 0x000b, /* Java */ + DW_LANG_C99 = 0x000c, /* ISO C:1999 */ + DW_LANG_Ada95 = 0x000d, /* ISO Ada:1995 */ + DW_LANG_Fortran95 = 0x000e, /* ISO Fortran 95 */ + DW_LANG_PLI = 0x000f, /* ISO PL/1:1976 */ + DW_LANG_ObjC = 0x0010, /* Objective-C */ + DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */ + DW_LANG_UPC = 0x0012, /* Unified Parallel C */ + DW_LANG_D = 0x0013, /* D */ + DW_LANG_Python = 0x0014, /* Python */ + DW_LANG_OpenCL = 0x0015, /* OpenCL */ + DW_LANG_Go = 0x0016, /* Go */ + DW_LANG_Modula3 = 0x0017, /* Modula-3 */ + DW_LANG_Haskell = 0x0018, /* Haskell */ + DW_LANG_C_plus_plus_03 = 0x0019, /* ISO C++:2003 */ + DW_LANG_C_plus_plus_11 = 0x001a, /* ISO C++:2011 */ + DW_LANG_OCaml = 0x001b, /* OCaml */ + DW_LANG_Rust = 0x001c, /* Rust */ + DW_LANG_C11 = 0x001d, /* ISO C:2011 */ + DW_LANG_Swift = 0x001e, /* Swift */ + DW_LANG_Julia = 0x001f, /* Julia */ + DW_LANG_Dylan = 0x0020, /* Dylan */ + DW_LANG_C_plus_plus_14 = 0x0021, /* ISO C++:2014 */ + DW_LANG_Fortran03 = 0x0022, /* ISO/IEC 1539-1:2004 */ + DW_LANG_Fortran08 = 0x0023, /* ISO/IEC 1539-1:2010 */ + DW_LANG_RenderScript = 0x0024, /* RenderScript Kernal Language */ + DW_LANG_BLISS = 0x0025, /* BLISS */ + + DW_LANG_lo_user = 0x8000, + DW_LANG_Mips_Assembler = 0x8001, /* Assembler */ + DW_LANG_hi_user = 0xffff + }; + +/* Old (typo) '1' != 'I'. */ +#define DW_LANG_PL1 DW_LANG_PLI + +/* DWARF identifier case encodings. */ +enum + { + DW_ID_case_sensitive = 0, + DW_ID_up_case = 1, + DW_ID_down_case = 2, + DW_ID_case_insensitive = 3 + }; + + +/* DWARF calling conventions encodings. + Used as values of DW_AT_calling_convention for subroutines + (normal, program or nocall) or structures, unions and class types + (normal, reference or value). */ +enum + { + DW_CC_normal = 0x1, + DW_CC_program = 0x2, + DW_CC_nocall = 0x3, + DW_CC_pass_by_reference = 0x4, + DW_CC_pass_by_value = 0x5, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff + }; + + +/* DWARF inline encodings. */ +enum + { + DW_INL_not_inlined = 0, + DW_INL_inlined = 1, + DW_INL_declared_not_inlined = 2, + DW_INL_declared_inlined = 3 + }; + + +/* DWARF ordering encodings. */ +enum + { + DW_ORD_row_major = 0, + DW_ORD_col_major = 1 + }; + + +/* DWARF discriminant descriptor encodings. */ +enum + { + DW_DSC_label = 0, + DW_DSC_range = 1 + }; + +/* DWARF defaulted member function encodings. */ +enum + { + DW_DEFAULTED_no = 0, + DW_DEFAULTED_in_class = 1, + DW_DEFAULTED_out_of_class = 2 + }; + +/* DWARF line content descriptions. */ +enum + { + DW_LNCT_path = 0x1, + DW_LNCT_directory_index = 0x2, + DW_LNCT_timestamp = 0x3, + DW_LNCT_size = 0x4, + DW_LNCT_MD5 = 0x5, + DW_LNCT_lo_user = 0x2000, + DW_LNCT_hi_user = 0x3fff + }; + +/* DWARF standard opcode encodings. */ +enum + { + DW_LNS_copy = 1, + DW_LNS_advance_pc = 2, + DW_LNS_advance_line = 3, + DW_LNS_set_file = 4, + DW_LNS_set_column = 5, + DW_LNS_negate_stmt = 6, + DW_LNS_set_basic_block = 7, + DW_LNS_const_add_pc = 8, + DW_LNS_fixed_advance_pc = 9, + DW_LNS_set_prologue_end = 10, + DW_LNS_set_epilogue_begin = 11, + DW_LNS_set_isa = 12 + }; + + +/* DWARF extended opcode encodings. */ +enum + { + DW_LNE_end_sequence = 1, + DW_LNE_set_address = 2, + DW_LNE_define_file = 3, + DW_LNE_set_discriminator = 4, + + DW_LNE_lo_user = 128, + + DW_LNE_NVIDIA_inlined_call = 144, + DW_LNE_NVIDIA_set_function_name = 145, + + DW_LNE_hi_user = 255 + }; + + +/* DWARF macinfo type encodings. */ +enum + { + DW_MACINFO_define = 1, + DW_MACINFO_undef = 2, + DW_MACINFO_start_file = 3, + DW_MACINFO_end_file = 4, + DW_MACINFO_vendor_ext = 255 + }; + + +/* DWARF debug_macro type encodings. */ +enum + { + DW_MACRO_define = 0x01, + DW_MACRO_undef = 0x02, + DW_MACRO_start_file = 0x03, + DW_MACRO_end_file = 0x04, + DW_MACRO_define_strp = 0x05, + DW_MACRO_undef_strp = 0x06, + DW_MACRO_import = 0x07, + DW_MACRO_define_sup = 0x08, + DW_MACRO_undef_sup = 0x09, + DW_MACRO_import_sup = 0x0a, + DW_MACRO_define_strx = 0x0b, + DW_MACRO_undef_strx = 0x0c, + DW_MACRO_lo_user = 0xe0, + DW_MACRO_hi_user = 0xff + }; + +/* Old GNU extension names for DWARF5 debug_macro type encodings. + There are no equivalents for the supplementary object file (sup) + and indirect string references (strx). */ +#define DW_MACRO_GNU_define DW_MACRO_define +#define DW_MACRO_GNU_undef DW_MACRO_undef +#define DW_MACRO_GNU_start_file DW_MACRO_start_file +#define DW_MACRO_GNU_end_file DW_MACRO_end_file +#define DW_MACRO_GNU_define_indirect DW_MACRO_define_strp +#define DW_MACRO_GNU_undef_indirect DW_MACRO_undef_strp +#define DW_MACRO_GNU_transparent_include DW_MACRO_import +#define DW_MACRO_GNU_lo_user DW_MACRO_lo_user +#define DW_MACRO_GNU_hi_user DW_MACRO_hi_user + + +/* Range list entry encoding. */ +enum + { + DW_RLE_end_of_list = 0x0, + DW_RLE_base_addressx = 0x1, + DW_RLE_startx_endx = 0x2, + DW_RLE_startx_length = 0x3, + DW_RLE_offset_pair = 0x4, + DW_RLE_base_address = 0x5, + DW_RLE_start_end = 0x6, + DW_RLE_start_length = 0x7 + }; + + +/* Location list entry encoding. */ +enum + { + DW_LLE_end_of_list = 0x0, + DW_LLE_base_addressx = 0x1, + DW_LLE_startx_endx = 0x2, + DW_LLE_startx_length = 0x3, + DW_LLE_offset_pair = 0x4, + DW_LLE_default_location = 0x5, + DW_LLE_base_address = 0x6, + DW_LLE_start_end = 0x7, + DW_LLE_start_length = 0x8 + }; + + +/* GNU DebugFission list entry encodings (.debug_loc.dwo). */ +enum + { + DW_LLE_GNU_end_of_list_entry = 0x0, + DW_LLE_GNU_base_address_selection_entry = 0x1, + DW_LLE_GNU_start_end_entry = 0x2, + DW_LLE_GNU_start_length_entry = 0x3, + + // http://www.fsfla.org/~lxoliva/papers/sfn/dwarf6-sfn-lvu.txt + // https://dwarfstd.org/ShowIssue.php?issue=170427.1 + DW_LLE_GNU_view_pair = 0x9 + }; + +/* DWARF5 package file section identifiers. */ +enum + { + DW_SECT_INFO = 1, + /* Reserved = 2, */ + DW_SECT_ABBREV = 3, + DW_SECT_LINE = 4, + DW_SECT_LOCLISTS = 5, + DW_SECT_STR_OFFSETS = 6, + DW_SECT_MACRO = 7, + DW_SECT_RNGLISTS = 8, + }; + + +/* DWARF call frame instruction encodings. */ +enum + { + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_extended = 0, + + DW_CFA_nop = 0x00, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + + DW_CFA_low_user = 0x1c, + DW_CFA_MIPS_advance_loc8 = 0x1d, + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_AARCH64_negate_ra_state = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f, + DW_CFA_high_user = 0x3f + }; + +/* ID indicating CIE as opposed to FDE in .debug_frame. */ +enum + { + DW_CIE_ID_32 = 0xffffffffU, /* In 32-bit format CIE header. */ + DW_CIE_ID_64 = 0xffffffffffffffffULL /* In 64-bit format CIE header. */ + }; + + +/* Information for GNU unwind information. */ +enum + { + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + + /* FDE data encoding. */ + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0a, + DW_EH_PE_sdata4 = 0x0b, + DW_EH_PE_sdata8 = 0x0c, + DW_EH_PE_signed = 0x08, + + /* FDE flags. */ + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + + DW_EH_PE_indirect = 0x80 + }; + + +/* DWARF XXX. */ +#define DW_ADDR_none 0 + +/* Section 7.2.2 of the DWARF3 specification defines a range of escape + codes that can appear in the length field of certain DWARF structures. + + These defines enumerate the minimum and maximum values of this range. + Currently only the maximum value is used (to indicate that 64-bit + values are going to be used in the dwarf data that accompanies the + structure). The other values are reserved. + + Note: There is a typo in DWARF3 spec (published Dec 20, 2005). In + sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to + as 0xffffff00 whereas in fact it should be 0xfffffff0. */ +#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u +#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu +#define DWARF3_LENGTH_64_BIT DWARF3_LENGTH_MAX_ESCAPE_CODE + +#endif /* dwarf.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/elf-knowledge.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/elf-knowledge.h new file mode 100644 index 000000000..6e005fa59 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/elf-knowledge.h @@ -0,0 +1,101 @@ +/* Accumulation of various pieces of knowledge about ELF. + Copyright (C) 2000-2012, 2014, 2016 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2000. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _ELF_KNOWLEDGE_H +#define _ELF_KNOWLEDGE_H 1 + +#include + + +/* Test whether a section can be stripped or not. */ +#define SECTION_STRIP_P(shdr, name, remove_comment) \ + /* Sections which are allocated are not removed. */ \ + (((shdr)->sh_flags & SHF_ALLOC) == 0 \ + /* We never remove .note sections. */ \ + && (shdr)->sh_type != SHT_NOTE \ + && (((shdr)->sh_type) != SHT_PROGBITS \ + /* Never remove .gnu.warning.* sections. */ \ + || (name != NULL \ + && strncmp (name, ".gnu.warning.", sizeof ".gnu.warning." - 1) != 0\ + /* We remove .comment sections only if explicitly told to do so. */\ + && (remove_comment \ + || strcmp (name, ".comment") != 0)))) + + +/* Test whether `sh_info' field in section header contains a section + index. There are two kinds of sections doing this: + + - the sections containing relocation information reference in this + field the section to which the relocations apply; + + - section with the SHF_INFO_LINK flag set to signal that `sh_info' + references a section. This allows correct handling of unknown + sections. */ +#define SH_INFO_LINK_P(Shdr) \ + ((Shdr)->sh_type == SHT_REL || (Shdr)->sh_type == SHT_RELA \ + || ((Shdr)->sh_flags & SHF_INFO_LINK) != 0) + + +/* Size of an entry in the hash table. The ELF specification says all + entries are regardless of platform 32-bits in size. Early 64-bit + ports (namely Alpha for Linux) got this wrong. The wording was not + clear. + + Several years later the ABI for the 64-bit S390s was developed. + Many things were copied from the IA-64 ABI (which uses the correct + 32-bit entry size) but it does get the SHT_HASH entry size wrong by + using a 64-bit entry size. So now we need this macro to special + case both the alpha and s390x ABIs. */ +#define SH_ENTSIZE_HASH(Ehdr) \ + ((Ehdr)->e_machine == EM_ALPHA \ + || ((Ehdr)->e_machine == EM_S390 \ + && (Ehdr)->e_ident[EI_CLASS] == ELFCLASS64) ? 8 : 4) + +/* GNU Annobin notes are not fully standardized and abuses the owner name. */ + +#define ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX "GA" + +#define NT_GNU_BUILD_ATTRIBUTE_OPEN 0x100 +#define NT_GNU_BUILD_ATTRIBUTE_FUNC 0x101 + +#define GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC '*' +#define GNU_BUILD_ATTRIBUTE_TYPE_STRING '$' +#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE '+' +#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE '!' + +#define GNU_BUILD_ATTRIBUTE_VERSION 1 +#define GNU_BUILD_ATTRIBUTE_STACK_PROT 2 +#define GNU_BUILD_ATTRIBUTE_RELRO 3 +#define GNU_BUILD_ATTRIBUTE_STACK_SIZE 4 +#define GNU_BUILD_ATTRIBUTE_TOOL 5 +#define GNU_BUILD_ATTRIBUTE_ABI 6 +#define GNU_BUILD_ATTRIBUTE_PIC 7 +#define GNU_BUILD_ATTRIBUTE_SHORT_ENUM 8 + +#endif /* elf-knowledge.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/known-dwarf.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/known-dwarf.h new file mode 100644 index 000000000..24dce447d --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/known-dwarf.h @@ -0,0 +1,795 @@ +/* Generated by config/known-dwarf.awk from libdw/dwarf.h contents. */ + +#define DWARF_ALL_KNOWN_DW_ACCESS \ + DWARF_ONE_KNOWN_DW_ACCESS (private, DW_ACCESS_private) \ + DWARF_ONE_KNOWN_DW_ACCESS (protected, DW_ACCESS_protected) \ + DWARF_ONE_KNOWN_DW_ACCESS (public, DW_ACCESS_public) \ + /* End of DW_ACCESS_*. */ + +#define DWARF_ALL_KNOWN_DW_AT \ + DWARF_ONE_KNOWN_DW_AT (GNU_addr_base, DW_AT_GNU_addr_base) \ + DWARF_ONE_KNOWN_DW_AT (GNU_all_call_sites, DW_AT_GNU_all_call_sites) \ + DWARF_ONE_KNOWN_DW_AT (GNU_all_source_call_sites, DW_AT_GNU_all_source_call_sites) \ + DWARF_ONE_KNOWN_DW_AT (GNU_all_tail_call_sites, DW_AT_GNU_all_tail_call_sites) \ + DWARF_ONE_KNOWN_DW_AT (GNU_bias, DW_AT_GNU_bias) \ + DWARF_ONE_KNOWN_DW_AT (GNU_call_site_data_value, DW_AT_GNU_call_site_data_value) \ + DWARF_ONE_KNOWN_DW_AT (GNU_call_site_target, DW_AT_GNU_call_site_target) \ + DWARF_ONE_KNOWN_DW_AT (GNU_call_site_target_clobbered, DW_AT_GNU_call_site_target_clobbered) \ + DWARF_ONE_KNOWN_DW_AT (GNU_call_site_value, DW_AT_GNU_call_site_value) \ + DWARF_ONE_KNOWN_DW_AT (GNU_deleted, DW_AT_GNU_deleted) \ + DWARF_ONE_KNOWN_DW_AT (GNU_denominator, DW_AT_GNU_denominator) \ + DWARF_ONE_KNOWN_DW_AT (GNU_dwo_id, DW_AT_GNU_dwo_id) \ + DWARF_ONE_KNOWN_DW_AT (GNU_dwo_name, DW_AT_GNU_dwo_name) \ + DWARF_ONE_KNOWN_DW_AT (GNU_entry_view, DW_AT_GNU_entry_view) \ + DWARF_ONE_KNOWN_DW_AT (GNU_exclusive_locks_required, DW_AT_GNU_exclusive_locks_required) \ + DWARF_ONE_KNOWN_DW_AT (GNU_guarded, DW_AT_GNU_guarded) \ + DWARF_ONE_KNOWN_DW_AT (GNU_guarded_by, DW_AT_GNU_guarded_by) \ + DWARF_ONE_KNOWN_DW_AT (GNU_locks_excluded, DW_AT_GNU_locks_excluded) \ + DWARF_ONE_KNOWN_DW_AT (GNU_locviews, DW_AT_GNU_locviews) \ + DWARF_ONE_KNOWN_DW_AT (GNU_macros, DW_AT_GNU_macros) \ + DWARF_ONE_KNOWN_DW_AT (GNU_numerator, DW_AT_GNU_numerator) \ + DWARF_ONE_KNOWN_DW_AT (GNU_odr_signature, DW_AT_GNU_odr_signature) \ + DWARF_ONE_KNOWN_DW_AT (GNU_pt_guarded, DW_AT_GNU_pt_guarded) \ + DWARF_ONE_KNOWN_DW_AT (GNU_pt_guarded_by, DW_AT_GNU_pt_guarded_by) \ + DWARF_ONE_KNOWN_DW_AT (GNU_pubnames, DW_AT_GNU_pubnames) \ + DWARF_ONE_KNOWN_DW_AT (GNU_pubtypes, DW_AT_GNU_pubtypes) \ + DWARF_ONE_KNOWN_DW_AT (GNU_ranges_base, DW_AT_GNU_ranges_base) \ + DWARF_ONE_KNOWN_DW_AT (GNU_shared_locks_required, DW_AT_GNU_shared_locks_required) \ + DWARF_ONE_KNOWN_DW_AT (GNU_tail_call, DW_AT_GNU_tail_call) \ + DWARF_ONE_KNOWN_DW_AT (GNU_template_name, DW_AT_GNU_template_name) \ + DWARF_ONE_KNOWN_DW_AT (GNU_vector, DW_AT_GNU_vector) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_abstract_name, DW_AT_MIPS_abstract_name) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_allocatable_dopetype, DW_AT_MIPS_allocatable_dopetype) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_assumed_shape_dopetype, DW_AT_MIPS_assumed_shape_dopetype) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_assumed_size, DW_AT_MIPS_assumed_size) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_clone_origin, DW_AT_MIPS_clone_origin) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_epilog_begin, DW_AT_MIPS_epilog_begin) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_fde, DW_AT_MIPS_fde) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_has_inlines, DW_AT_MIPS_has_inlines) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_linkage_name, DW_AT_MIPS_linkage_name) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_loop_begin, DW_AT_MIPS_loop_begin) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_loop_unroll_factor, DW_AT_MIPS_loop_unroll_factor) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_ptr_dopetype, DW_AT_MIPS_ptr_dopetype) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_software_pipeline_depth, DW_AT_MIPS_software_pipeline_depth) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_stride, DW_AT_MIPS_stride) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_stride_byte, DW_AT_MIPS_stride_byte) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_stride_elem, DW_AT_MIPS_stride_elem) \ + DWARF_ONE_KNOWN_DW_AT (MIPS_tail_loop_begin, DW_AT_MIPS_tail_loop_begin) \ + DWARF_ONE_KNOWN_DW_AT (abstract_origin, DW_AT_abstract_origin) \ + DWARF_ONE_KNOWN_DW_AT (accessibility, DW_AT_accessibility) \ + DWARF_ONE_KNOWN_DW_AT (addr_base, DW_AT_addr_base) \ + DWARF_ONE_KNOWN_DW_AT (address_class, DW_AT_address_class) \ + DWARF_ONE_KNOWN_DW_AT (alignment, DW_AT_alignment) \ + DWARF_ONE_KNOWN_DW_AT (allocated, DW_AT_allocated) \ + DWARF_ONE_KNOWN_DW_AT (artificial, DW_AT_artificial) \ + DWARF_ONE_KNOWN_DW_AT (associated, DW_AT_associated) \ + DWARF_ONE_KNOWN_DW_AT (base_types, DW_AT_base_types) \ + DWARF_ONE_KNOWN_DW_AT (binary_scale, DW_AT_binary_scale) \ + DWARF_ONE_KNOWN_DW_AT (bit_offset, DW_AT_bit_offset) \ + DWARF_ONE_KNOWN_DW_AT (bit_size, DW_AT_bit_size) \ + DWARF_ONE_KNOWN_DW_AT (bit_stride, DW_AT_bit_stride) \ + DWARF_ONE_KNOWN_DW_AT (body_begin, DW_AT_body_begin) \ + DWARF_ONE_KNOWN_DW_AT (body_end, DW_AT_body_end) \ + DWARF_ONE_KNOWN_DW_AT (byte_size, DW_AT_byte_size) \ + DWARF_ONE_KNOWN_DW_AT (byte_stride, DW_AT_byte_stride) \ + DWARF_ONE_KNOWN_DW_AT (call_all_calls, DW_AT_call_all_calls) \ + DWARF_ONE_KNOWN_DW_AT (call_all_source_calls, DW_AT_call_all_source_calls) \ + DWARF_ONE_KNOWN_DW_AT (call_all_tail_calls, DW_AT_call_all_tail_calls) \ + DWARF_ONE_KNOWN_DW_AT (call_column, DW_AT_call_column) \ + DWARF_ONE_KNOWN_DW_AT (call_data_location, DW_AT_call_data_location) \ + DWARF_ONE_KNOWN_DW_AT (call_data_value, DW_AT_call_data_value) \ + DWARF_ONE_KNOWN_DW_AT (call_file, DW_AT_call_file) \ + DWARF_ONE_KNOWN_DW_AT (call_line, DW_AT_call_line) \ + DWARF_ONE_KNOWN_DW_AT (call_origin, DW_AT_call_origin) \ + DWARF_ONE_KNOWN_DW_AT (call_parameter, DW_AT_call_parameter) \ + DWARF_ONE_KNOWN_DW_AT (call_pc, DW_AT_call_pc) \ + DWARF_ONE_KNOWN_DW_AT (call_return_pc, DW_AT_call_return_pc) \ + DWARF_ONE_KNOWN_DW_AT (call_tail_call, DW_AT_call_tail_call) \ + DWARF_ONE_KNOWN_DW_AT (call_target, DW_AT_call_target) \ + DWARF_ONE_KNOWN_DW_AT (call_target_clobbered, DW_AT_call_target_clobbered) \ + DWARF_ONE_KNOWN_DW_AT (call_value, DW_AT_call_value) \ + DWARF_ONE_KNOWN_DW_AT (calling_convention, DW_AT_calling_convention) \ + DWARF_ONE_KNOWN_DW_AT (common_reference, DW_AT_common_reference) \ + DWARF_ONE_KNOWN_DW_AT (comp_dir, DW_AT_comp_dir) \ + DWARF_ONE_KNOWN_DW_AT (const_expr, DW_AT_const_expr) \ + DWARF_ONE_KNOWN_DW_AT (const_value, DW_AT_const_value) \ + DWARF_ONE_KNOWN_DW_AT (containing_type, DW_AT_containing_type) \ + DWARF_ONE_KNOWN_DW_AT (count, DW_AT_count) \ + DWARF_ONE_KNOWN_DW_AT (data_bit_offset, DW_AT_data_bit_offset) \ + DWARF_ONE_KNOWN_DW_AT (data_location, DW_AT_data_location) \ + DWARF_ONE_KNOWN_DW_AT (data_member_location, DW_AT_data_member_location) \ + DWARF_ONE_KNOWN_DW_AT (decimal_scale, DW_AT_decimal_scale) \ + DWARF_ONE_KNOWN_DW_AT (decimal_sign, DW_AT_decimal_sign) \ + DWARF_ONE_KNOWN_DW_AT (decl_column, DW_AT_decl_column) \ + DWARF_ONE_KNOWN_DW_AT (decl_file, DW_AT_decl_file) \ + DWARF_ONE_KNOWN_DW_AT (decl_line, DW_AT_decl_line) \ + DWARF_ONE_KNOWN_DW_AT (declaration, DW_AT_declaration) \ + DWARF_ONE_KNOWN_DW_AT (default_value, DW_AT_default_value) \ + DWARF_ONE_KNOWN_DW_AT (defaulted, DW_AT_defaulted) \ + DWARF_ONE_KNOWN_DW_AT (deleted, DW_AT_deleted) \ + DWARF_ONE_KNOWN_DW_AT (description, DW_AT_description) \ + DWARF_ONE_KNOWN_DW_AT (digit_count, DW_AT_digit_count) \ + DWARF_ONE_KNOWN_DW_AT (discr, DW_AT_discr) \ + DWARF_ONE_KNOWN_DW_AT (discr_list, DW_AT_discr_list) \ + DWARF_ONE_KNOWN_DW_AT (discr_value, DW_AT_discr_value) \ + DWARF_ONE_KNOWN_DW_AT (dwo_name, DW_AT_dwo_name) \ + DWARF_ONE_KNOWN_DW_AT (elemental, DW_AT_elemental) \ + DWARF_ONE_KNOWN_DW_AT (encoding, DW_AT_encoding) \ + DWARF_ONE_KNOWN_DW_AT (endianity, DW_AT_endianity) \ + DWARF_ONE_KNOWN_DW_AT (entry_pc, DW_AT_entry_pc) \ + DWARF_ONE_KNOWN_DW_AT (enum_class, DW_AT_enum_class) \ + DWARF_ONE_KNOWN_DW_AT (explicit, DW_AT_explicit) \ + DWARF_ONE_KNOWN_DW_AT (export_symbols, DW_AT_export_symbols) \ + DWARF_ONE_KNOWN_DW_AT (extension, DW_AT_extension) \ + DWARF_ONE_KNOWN_DW_AT (external, DW_AT_external) \ + DWARF_ONE_KNOWN_DW_AT (frame_base, DW_AT_frame_base) \ + DWARF_ONE_KNOWN_DW_AT (friend, DW_AT_friend) \ + DWARF_ONE_KNOWN_DW_AT (high_pc, DW_AT_high_pc) \ + DWARF_ONE_KNOWN_DW_AT (identifier_case, DW_AT_identifier_case) \ + DWARF_ONE_KNOWN_DW_AT (import, DW_AT_import) \ + DWARF_ONE_KNOWN_DW_AT (inline, DW_AT_inline) \ + DWARF_ONE_KNOWN_DW_AT (is_optional, DW_AT_is_optional) \ + DWARF_ONE_KNOWN_DW_AT (language, DW_AT_language) \ + DWARF_ONE_KNOWN_DW_AT (linkage_name, DW_AT_linkage_name) \ + DWARF_ONE_KNOWN_DW_AT (location, DW_AT_location) \ + DWARF_ONE_KNOWN_DW_AT (loclists_base, DW_AT_loclists_base) \ + DWARF_ONE_KNOWN_DW_AT (low_pc, DW_AT_low_pc) \ + DWARF_ONE_KNOWN_DW_AT (lower_bound, DW_AT_lower_bound) \ + DWARF_ONE_KNOWN_DW_AT (mac_info, DW_AT_mac_info) \ + DWARF_ONE_KNOWN_DW_AT (macro_info, DW_AT_macro_info) \ + DWARF_ONE_KNOWN_DW_AT (macros, DW_AT_macros) \ + DWARF_ONE_KNOWN_DW_AT (main_subprogram, DW_AT_main_subprogram) \ + DWARF_ONE_KNOWN_DW_AT (mutable, DW_AT_mutable) \ + DWARF_ONE_KNOWN_DW_AT (name, DW_AT_name) \ + DWARF_ONE_KNOWN_DW_AT (namelist_item, DW_AT_namelist_item) \ + DWARF_ONE_KNOWN_DW_AT (noreturn, DW_AT_noreturn) \ + DWARF_ONE_KNOWN_DW_AT (object_pointer, DW_AT_object_pointer) \ + DWARF_ONE_KNOWN_DW_AT (ordering, DW_AT_ordering) \ + DWARF_ONE_KNOWN_DW_AT (picture_string, DW_AT_picture_string) \ + DWARF_ONE_KNOWN_DW_AT (priority, DW_AT_priority) \ + DWARF_ONE_KNOWN_DW_AT (producer, DW_AT_producer) \ + DWARF_ONE_KNOWN_DW_AT (prototyped, DW_AT_prototyped) \ + DWARF_ONE_KNOWN_DW_AT (pure, DW_AT_pure) \ + DWARF_ONE_KNOWN_DW_AT (ranges, DW_AT_ranges) \ + DWARF_ONE_KNOWN_DW_AT (rank, DW_AT_rank) \ + DWARF_ONE_KNOWN_DW_AT (recursive, DW_AT_recursive) \ + DWARF_ONE_KNOWN_DW_AT (reference, DW_AT_reference) \ + DWARF_ONE_KNOWN_DW_AT (return_addr, DW_AT_return_addr) \ + DWARF_ONE_KNOWN_DW_AT (rnglists_base, DW_AT_rnglists_base) \ + DWARF_ONE_KNOWN_DW_AT (rvalue_reference, DW_AT_rvalue_reference) \ + DWARF_ONE_KNOWN_DW_AT (segment, DW_AT_segment) \ + DWARF_ONE_KNOWN_DW_AT (sf_names, DW_AT_sf_names) \ + DWARF_ONE_KNOWN_DW_AT (sibling, DW_AT_sibling) \ + DWARF_ONE_KNOWN_DW_AT (signature, DW_AT_signature) \ + DWARF_ONE_KNOWN_DW_AT (small, DW_AT_small) \ + DWARF_ONE_KNOWN_DW_AT (specification, DW_AT_specification) \ + DWARF_ONE_KNOWN_DW_AT (src_coords, DW_AT_src_coords) \ + DWARF_ONE_KNOWN_DW_AT (src_info, DW_AT_src_info) \ + DWARF_ONE_KNOWN_DW_AT (start_scope, DW_AT_start_scope) \ + DWARF_ONE_KNOWN_DW_AT (static_link, DW_AT_static_link) \ + DWARF_ONE_KNOWN_DW_AT (stmt_list, DW_AT_stmt_list) \ + DWARF_ONE_KNOWN_DW_AT (str_offsets_base, DW_AT_str_offsets_base) \ + DWARF_ONE_KNOWN_DW_AT (string_length, DW_AT_string_length) \ + DWARF_ONE_KNOWN_DW_AT (string_length_bit_size, DW_AT_string_length_bit_size) \ + DWARF_ONE_KNOWN_DW_AT (string_length_byte_size, DW_AT_string_length_byte_size) \ + DWARF_ONE_KNOWN_DW_AT (threads_scaled, DW_AT_threads_scaled) \ + DWARF_ONE_KNOWN_DW_AT (trampoline, DW_AT_trampoline) \ + DWARF_ONE_KNOWN_DW_AT (type, DW_AT_type) \ + DWARF_ONE_KNOWN_DW_AT (upper_bound, DW_AT_upper_bound) \ + DWARF_ONE_KNOWN_DW_AT (use_UTF8, DW_AT_use_UTF8) \ + DWARF_ONE_KNOWN_DW_AT (use_location, DW_AT_use_location) \ + DWARF_ONE_KNOWN_DW_AT (variable_parameter, DW_AT_variable_parameter) \ + DWARF_ONE_KNOWN_DW_AT (virtuality, DW_AT_virtuality) \ + DWARF_ONE_KNOWN_DW_AT (visibility, DW_AT_visibility) \ + DWARF_ONE_KNOWN_DW_AT (vtable_elem_location, DW_AT_vtable_elem_location) \ + /* End of DW_AT_*. */ + +#define DWARF_ALL_KNOWN_DW_ATE \ + DWARF_ONE_KNOWN_DW_ATE (ASCII, DW_ATE_ASCII) \ + DWARF_ONE_KNOWN_DW_ATE (UCS, DW_ATE_UCS) \ + DWARF_ONE_KNOWN_DW_ATE (UTF, DW_ATE_UTF) \ + DWARF_ONE_KNOWN_DW_ATE (address, DW_ATE_address) \ + DWARF_ONE_KNOWN_DW_ATE (boolean, DW_ATE_boolean) \ + DWARF_ONE_KNOWN_DW_ATE (complex_float, DW_ATE_complex_float) \ + DWARF_ONE_KNOWN_DW_ATE (decimal_float, DW_ATE_decimal_float) \ + DWARF_ONE_KNOWN_DW_ATE (edited, DW_ATE_edited) \ + DWARF_ONE_KNOWN_DW_ATE (float, DW_ATE_float) \ + DWARF_ONE_KNOWN_DW_ATE (imaginary_float, DW_ATE_imaginary_float) \ + DWARF_ONE_KNOWN_DW_ATE (numeric_string, DW_ATE_numeric_string) \ + DWARF_ONE_KNOWN_DW_ATE (packed_decimal, DW_ATE_packed_decimal) \ + DWARF_ONE_KNOWN_DW_ATE (signed, DW_ATE_signed) \ + DWARF_ONE_KNOWN_DW_ATE (signed_char, DW_ATE_signed_char) \ + DWARF_ONE_KNOWN_DW_ATE (signed_fixed, DW_ATE_signed_fixed) \ + DWARF_ONE_KNOWN_DW_ATE (unsigned, DW_ATE_unsigned) \ + DWARF_ONE_KNOWN_DW_ATE (unsigned_char, DW_ATE_unsigned_char) \ + DWARF_ONE_KNOWN_DW_ATE (unsigned_fixed, DW_ATE_unsigned_fixed) \ + DWARF_ONE_KNOWN_DW_ATE (void, DW_ATE_void) \ + /* End of DW_ATE_*. */ + +#define DWARF_ALL_KNOWN_DW_CC \ + DWARF_ONE_KNOWN_DW_CC (nocall, DW_CC_nocall) \ + DWARF_ONE_KNOWN_DW_CC (normal, DW_CC_normal) \ + DWARF_ONE_KNOWN_DW_CC (pass_by_reference, DW_CC_pass_by_reference) \ + DWARF_ONE_KNOWN_DW_CC (pass_by_value, DW_CC_pass_by_value) \ + DWARF_ONE_KNOWN_DW_CC (program, DW_CC_program) \ + /* End of DW_CC_*. */ + +#define DWARF_ALL_KNOWN_DW_CFA \ + DWARF_ONE_KNOWN_DW_CFA (AARCH64_negate_ra_state, DW_CFA_AARCH64_negate_ra_state) \ + DWARF_ONE_KNOWN_DW_CFA (GNU_args_size, DW_CFA_GNU_args_size) \ + DWARF_ONE_KNOWN_DW_CFA (GNU_negative_offset_extended, DW_CFA_GNU_negative_offset_extended) \ + DWARF_ONE_KNOWN_DW_CFA (GNU_window_save, DW_CFA_GNU_window_save) \ + DWARF_ONE_KNOWN_DW_CFA (MIPS_advance_loc8, DW_CFA_MIPS_advance_loc8) \ + DWARF_ONE_KNOWN_DW_CFA (advance_loc, DW_CFA_advance_loc) \ + DWARF_ONE_KNOWN_DW_CFA (advance_loc1, DW_CFA_advance_loc1) \ + DWARF_ONE_KNOWN_DW_CFA (advance_loc2, DW_CFA_advance_loc2) \ + DWARF_ONE_KNOWN_DW_CFA (advance_loc4, DW_CFA_advance_loc4) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa, DW_CFA_def_cfa) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa_expression, DW_CFA_def_cfa_expression) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa_offset, DW_CFA_def_cfa_offset) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa_offset_sf, DW_CFA_def_cfa_offset_sf) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa_register, DW_CFA_def_cfa_register) \ + DWARF_ONE_KNOWN_DW_CFA (def_cfa_sf, DW_CFA_def_cfa_sf) \ + DWARF_ONE_KNOWN_DW_CFA (expression, DW_CFA_expression) \ + DWARF_ONE_KNOWN_DW_CFA (extended, DW_CFA_extended) \ + DWARF_ONE_KNOWN_DW_CFA (nop, DW_CFA_nop) \ + DWARF_ONE_KNOWN_DW_CFA (offset, DW_CFA_offset) \ + DWARF_ONE_KNOWN_DW_CFA (offset_extended, DW_CFA_offset_extended) \ + DWARF_ONE_KNOWN_DW_CFA (offset_extended_sf, DW_CFA_offset_extended_sf) \ + DWARF_ONE_KNOWN_DW_CFA (register, DW_CFA_register) \ + DWARF_ONE_KNOWN_DW_CFA (remember_state, DW_CFA_remember_state) \ + DWARF_ONE_KNOWN_DW_CFA (restore, DW_CFA_restore) \ + DWARF_ONE_KNOWN_DW_CFA (restore_extended, DW_CFA_restore_extended) \ + DWARF_ONE_KNOWN_DW_CFA (restore_state, DW_CFA_restore_state) \ + DWARF_ONE_KNOWN_DW_CFA (same_value, DW_CFA_same_value) \ + DWARF_ONE_KNOWN_DW_CFA (set_loc, DW_CFA_set_loc) \ + DWARF_ONE_KNOWN_DW_CFA (undefined, DW_CFA_undefined) \ + DWARF_ONE_KNOWN_DW_CFA (val_expression, DW_CFA_val_expression) \ + DWARF_ONE_KNOWN_DW_CFA (val_offset, DW_CFA_val_offset) \ + DWARF_ONE_KNOWN_DW_CFA (val_offset_sf, DW_CFA_val_offset_sf) \ + /* End of DW_CFA_*. */ + +#define DWARF_ALL_KNOWN_DW_CHILDREN \ + DWARF_ONE_KNOWN_DW_CHILDREN (no, DW_CHILDREN_no) \ + DWARF_ONE_KNOWN_DW_CHILDREN (yes, DW_CHILDREN_yes) \ + /* End of DW_CHILDREN_*. */ + +#define DWARF_ALL_KNOWN_DW_CIE_ID \ + DWARF_ONE_KNOWN_DW_CIE_ID (32, DW_CIE_ID_32) \ + DWARF_ONE_KNOWN_DW_CIE_ID (64, DW_CIE_ID_64) \ + /* End of DW_CIE_ID_*. */ + +#define DWARF_ALL_KNOWN_DW_DEFAULTED \ + DWARF_ONE_KNOWN_DW_DEFAULTED (in_class, DW_DEFAULTED_in_class) \ + DWARF_ONE_KNOWN_DW_DEFAULTED (no, DW_DEFAULTED_no) \ + DWARF_ONE_KNOWN_DW_DEFAULTED (out_of_class, DW_DEFAULTED_out_of_class) \ + /* End of DW_DEFAULTED_*. */ + +#define DWARF_ALL_KNOWN_DW_DS \ + DWARF_ONE_KNOWN_DW_DS (leading_overpunch, DW_DS_leading_overpunch) \ + DWARF_ONE_KNOWN_DW_DS (leading_separate, DW_DS_leading_separate) \ + DWARF_ONE_KNOWN_DW_DS (trailing_overpunch, DW_DS_trailing_overpunch) \ + DWARF_ONE_KNOWN_DW_DS (trailing_separate, DW_DS_trailing_separate) \ + DWARF_ONE_KNOWN_DW_DS (unsigned, DW_DS_unsigned) \ + /* End of DW_DS_*. */ + +#define DWARF_ALL_KNOWN_DW_DSC \ + DWARF_ONE_KNOWN_DW_DSC (label, DW_DSC_label) \ + DWARF_ONE_KNOWN_DW_DSC (range, DW_DSC_range) \ + /* End of DW_DSC_*. */ + +#define DWARF_ALL_KNOWN_DW_EH_PE \ + DWARF_ONE_KNOWN_DW_EH_PE (absptr, DW_EH_PE_absptr) \ + DWARF_ONE_KNOWN_DW_EH_PE (aligned, DW_EH_PE_aligned) \ + DWARF_ONE_KNOWN_DW_EH_PE (datarel, DW_EH_PE_datarel) \ + DWARF_ONE_KNOWN_DW_EH_PE (funcrel, DW_EH_PE_funcrel) \ + DWARF_ONE_KNOWN_DW_EH_PE (indirect, DW_EH_PE_indirect) \ + DWARF_ONE_KNOWN_DW_EH_PE (omit, DW_EH_PE_omit) \ + DWARF_ONE_KNOWN_DW_EH_PE (pcrel, DW_EH_PE_pcrel) \ + DWARF_ONE_KNOWN_DW_EH_PE (sdata2, DW_EH_PE_sdata2) \ + DWARF_ONE_KNOWN_DW_EH_PE (sdata4, DW_EH_PE_sdata4) \ + DWARF_ONE_KNOWN_DW_EH_PE (sdata8, DW_EH_PE_sdata8) \ + DWARF_ONE_KNOWN_DW_EH_PE (signed, DW_EH_PE_signed) \ + DWARF_ONE_KNOWN_DW_EH_PE (sleb128, DW_EH_PE_sleb128) \ + DWARF_ONE_KNOWN_DW_EH_PE (textrel, DW_EH_PE_textrel) \ + DWARF_ONE_KNOWN_DW_EH_PE (udata2, DW_EH_PE_udata2) \ + DWARF_ONE_KNOWN_DW_EH_PE (udata4, DW_EH_PE_udata4) \ + DWARF_ONE_KNOWN_DW_EH_PE (udata8, DW_EH_PE_udata8) \ + DWARF_ONE_KNOWN_DW_EH_PE (uleb128, DW_EH_PE_uleb128) \ + /* End of DW_EH_PE_*. */ + +#define DWARF_ALL_KNOWN_DW_END \ + DWARF_ONE_KNOWN_DW_END (big, DW_END_big) \ + DWARF_ONE_KNOWN_DW_END (default, DW_END_default) \ + DWARF_ONE_KNOWN_DW_END (little, DW_END_little) \ + /* End of DW_END_*. */ + +#define DWARF_ALL_KNOWN_DW_FORM \ + DWARF_ONE_KNOWN_DW_FORM (GNU_addr_index, DW_FORM_GNU_addr_index) \ + DWARF_ONE_KNOWN_DW_FORM (GNU_ref_alt, DW_FORM_GNU_ref_alt) \ + DWARF_ONE_KNOWN_DW_FORM (GNU_str_index, DW_FORM_GNU_str_index) \ + DWARF_ONE_KNOWN_DW_FORM (GNU_strp_alt, DW_FORM_GNU_strp_alt) \ + DWARF_ONE_KNOWN_DW_FORM (addr, DW_FORM_addr) \ + DWARF_ONE_KNOWN_DW_FORM (addrx, DW_FORM_addrx) \ + DWARF_ONE_KNOWN_DW_FORM (addrx1, DW_FORM_addrx1) \ + DWARF_ONE_KNOWN_DW_FORM (addrx2, DW_FORM_addrx2) \ + DWARF_ONE_KNOWN_DW_FORM (addrx3, DW_FORM_addrx3) \ + DWARF_ONE_KNOWN_DW_FORM (addrx4, DW_FORM_addrx4) \ + DWARF_ONE_KNOWN_DW_FORM (block, DW_FORM_block) \ + DWARF_ONE_KNOWN_DW_FORM (block1, DW_FORM_block1) \ + DWARF_ONE_KNOWN_DW_FORM (block2, DW_FORM_block2) \ + DWARF_ONE_KNOWN_DW_FORM (block4, DW_FORM_block4) \ + DWARF_ONE_KNOWN_DW_FORM (data1, DW_FORM_data1) \ + DWARF_ONE_KNOWN_DW_FORM (data16, DW_FORM_data16) \ + DWARF_ONE_KNOWN_DW_FORM (data2, DW_FORM_data2) \ + DWARF_ONE_KNOWN_DW_FORM (data4, DW_FORM_data4) \ + DWARF_ONE_KNOWN_DW_FORM (data8, DW_FORM_data8) \ + DWARF_ONE_KNOWN_DW_FORM (exprloc, DW_FORM_exprloc) \ + DWARF_ONE_KNOWN_DW_FORM (flag, DW_FORM_flag) \ + DWARF_ONE_KNOWN_DW_FORM (flag_present, DW_FORM_flag_present) \ + DWARF_ONE_KNOWN_DW_FORM (implicit_const, DW_FORM_implicit_const) \ + DWARF_ONE_KNOWN_DW_FORM (indirect, DW_FORM_indirect) \ + DWARF_ONE_KNOWN_DW_FORM (line_strp, DW_FORM_line_strp) \ + DWARF_ONE_KNOWN_DW_FORM (loclistx, DW_FORM_loclistx) \ + DWARF_ONE_KNOWN_DW_FORM (ref1, DW_FORM_ref1) \ + DWARF_ONE_KNOWN_DW_FORM (ref2, DW_FORM_ref2) \ + DWARF_ONE_KNOWN_DW_FORM (ref4, DW_FORM_ref4) \ + DWARF_ONE_KNOWN_DW_FORM (ref8, DW_FORM_ref8) \ + DWARF_ONE_KNOWN_DW_FORM (ref_addr, DW_FORM_ref_addr) \ + DWARF_ONE_KNOWN_DW_FORM (ref_sig8, DW_FORM_ref_sig8) \ + DWARF_ONE_KNOWN_DW_FORM (ref_sup4, DW_FORM_ref_sup4) \ + DWARF_ONE_KNOWN_DW_FORM (ref_sup8, DW_FORM_ref_sup8) \ + DWARF_ONE_KNOWN_DW_FORM (ref_udata, DW_FORM_ref_udata) \ + DWARF_ONE_KNOWN_DW_FORM (rnglistx, DW_FORM_rnglistx) \ + DWARF_ONE_KNOWN_DW_FORM (sdata, DW_FORM_sdata) \ + DWARF_ONE_KNOWN_DW_FORM (sec_offset, DW_FORM_sec_offset) \ + DWARF_ONE_KNOWN_DW_FORM (string, DW_FORM_string) \ + DWARF_ONE_KNOWN_DW_FORM (strp, DW_FORM_strp) \ + DWARF_ONE_KNOWN_DW_FORM (strp_sup, DW_FORM_strp_sup) \ + DWARF_ONE_KNOWN_DW_FORM (strx, DW_FORM_strx) \ + DWARF_ONE_KNOWN_DW_FORM (strx1, DW_FORM_strx1) \ + DWARF_ONE_KNOWN_DW_FORM (strx2, DW_FORM_strx2) \ + DWARF_ONE_KNOWN_DW_FORM (strx3, DW_FORM_strx3) \ + DWARF_ONE_KNOWN_DW_FORM (strx4, DW_FORM_strx4) \ + DWARF_ONE_KNOWN_DW_FORM (udata, DW_FORM_udata) \ + /* End of DW_FORM_*. */ + +#define DWARF_ALL_KNOWN_DW_ID \ + DWARF_ONE_KNOWN_DW_ID (case_insensitive, DW_ID_case_insensitive) \ + DWARF_ONE_KNOWN_DW_ID (case_sensitive, DW_ID_case_sensitive) \ + DWARF_ONE_KNOWN_DW_ID (down_case, DW_ID_down_case) \ + DWARF_ONE_KNOWN_DW_ID (up_case, DW_ID_up_case) \ + /* End of DW_ID_*. */ + +#define DWARF_ALL_KNOWN_DW_INL \ + DWARF_ONE_KNOWN_DW_INL (declared_inlined, DW_INL_declared_inlined) \ + DWARF_ONE_KNOWN_DW_INL (declared_not_inlined, DW_INL_declared_not_inlined) \ + DWARF_ONE_KNOWN_DW_INL (inlined, DW_INL_inlined) \ + DWARF_ONE_KNOWN_DW_INL (not_inlined, DW_INL_not_inlined) \ + /* End of DW_INL_*. */ + +#define DWARF_ALL_KNOWN_DW_LANG \ + DWARF_ONE_KNOWN_DW_LANG (Ada83, DW_LANG_Ada83) \ + DWARF_ONE_KNOWN_DW_LANG (Ada95, DW_LANG_Ada95) \ + DWARF_ONE_KNOWN_DW_LANG (BLISS, DW_LANG_BLISS) \ + DWARF_ONE_KNOWN_DW_LANG (C, DW_LANG_C) \ + DWARF_ONE_KNOWN_DW_LANG (C11, DW_LANG_C11) \ + DWARF_ONE_KNOWN_DW_LANG (C89, DW_LANG_C89) \ + DWARF_ONE_KNOWN_DW_LANG (C99, DW_LANG_C99) \ + DWARF_ONE_KNOWN_DW_LANG (C_plus_plus, DW_LANG_C_plus_plus) \ + DWARF_ONE_KNOWN_DW_LANG (C_plus_plus_03, DW_LANG_C_plus_plus_03) \ + DWARF_ONE_KNOWN_DW_LANG (C_plus_plus_11, DW_LANG_C_plus_plus_11) \ + DWARF_ONE_KNOWN_DW_LANG (C_plus_plus_14, DW_LANG_C_plus_plus_14) \ + DWARF_ONE_KNOWN_DW_LANG (Cobol74, DW_LANG_Cobol74) \ + DWARF_ONE_KNOWN_DW_LANG (Cobol85, DW_LANG_Cobol85) \ + DWARF_ONE_KNOWN_DW_LANG (D, DW_LANG_D) \ + DWARF_ONE_KNOWN_DW_LANG (Dylan, DW_LANG_Dylan) \ + DWARF_ONE_KNOWN_DW_LANG (Fortran03, DW_LANG_Fortran03) \ + DWARF_ONE_KNOWN_DW_LANG (Fortran08, DW_LANG_Fortran08) \ + DWARF_ONE_KNOWN_DW_LANG (Fortran77, DW_LANG_Fortran77) \ + DWARF_ONE_KNOWN_DW_LANG (Fortran90, DW_LANG_Fortran90) \ + DWARF_ONE_KNOWN_DW_LANG (Fortran95, DW_LANG_Fortran95) \ + DWARF_ONE_KNOWN_DW_LANG (Go, DW_LANG_Go) \ + DWARF_ONE_KNOWN_DW_LANG (Haskell, DW_LANG_Haskell) \ + DWARF_ONE_KNOWN_DW_LANG (Java, DW_LANG_Java) \ + DWARF_ONE_KNOWN_DW_LANG (Julia, DW_LANG_Julia) \ + DWARF_ONE_KNOWN_DW_LANG (Mips_Assembler, DW_LANG_Mips_Assembler) \ + DWARF_ONE_KNOWN_DW_LANG (Modula2, DW_LANG_Modula2) \ + DWARF_ONE_KNOWN_DW_LANG (Modula3, DW_LANG_Modula3) \ + DWARF_ONE_KNOWN_DW_LANG (OCaml, DW_LANG_OCaml) \ + DWARF_ONE_KNOWN_DW_LANG (ObjC, DW_LANG_ObjC) \ + DWARF_ONE_KNOWN_DW_LANG (ObjC_plus_plus, DW_LANG_ObjC_plus_plus) \ + DWARF_ONE_KNOWN_DW_LANG (OpenCL, DW_LANG_OpenCL) \ + DWARF_ONE_KNOWN_DW_LANG (PLI, DW_LANG_PLI) \ + DWARF_ONE_KNOWN_DW_LANG (Pascal83, DW_LANG_Pascal83) \ + DWARF_ONE_KNOWN_DW_LANG (Python, DW_LANG_Python) \ + DWARF_ONE_KNOWN_DW_LANG (RenderScript, DW_LANG_RenderScript) \ + DWARF_ONE_KNOWN_DW_LANG (Rust, DW_LANG_Rust) \ + DWARF_ONE_KNOWN_DW_LANG (Swift, DW_LANG_Swift) \ + DWARF_ONE_KNOWN_DW_LANG (UPC, DW_LANG_UPC) \ + /* End of DW_LANG_*. */ + +#define DWARF_ALL_KNOWN_DW_LLE \ + DWARF_ONE_KNOWN_DW_LLE (base_address, DW_LLE_base_address) \ + DWARF_ONE_KNOWN_DW_LLE (base_addressx, DW_LLE_base_addressx) \ + DWARF_ONE_KNOWN_DW_LLE (default_location, DW_LLE_default_location) \ + DWARF_ONE_KNOWN_DW_LLE (end_of_list, DW_LLE_end_of_list) \ + DWARF_ONE_KNOWN_DW_LLE (offset_pair, DW_LLE_offset_pair) \ + DWARF_ONE_KNOWN_DW_LLE (start_end, DW_LLE_start_end) \ + DWARF_ONE_KNOWN_DW_LLE (start_length, DW_LLE_start_length) \ + DWARF_ONE_KNOWN_DW_LLE (startx_endx, DW_LLE_startx_endx) \ + DWARF_ONE_KNOWN_DW_LLE (startx_length, DW_LLE_startx_length) \ + /* End of DW_LLE_*. */ + +#define DWARF_ALL_KNOWN_DW_LLE_GNU \ + DWARF_ONE_KNOWN_DW_LLE_GNU (base_address_selection_entry, DW_LLE_GNU_base_address_selection_entry) \ + DWARF_ONE_KNOWN_DW_LLE_GNU (end_of_list_entry, DW_LLE_GNU_end_of_list_entry) \ + DWARF_ONE_KNOWN_DW_LLE_GNU (start_end_entry, DW_LLE_GNU_start_end_entry) \ + DWARF_ONE_KNOWN_DW_LLE_GNU (start_length_entry, DW_LLE_GNU_start_length_entry) \ + DWARF_ONE_KNOWN_DW_LLE_GNU (view_pair, DW_LLE_GNU_view_pair) \ + /* End of DW_LLE_GNU_*. */ + +#define DWARF_ALL_KNOWN_DW_LNCT \ + DWARF_ONE_KNOWN_DW_LNCT (MD5, DW_LNCT_MD5) \ + DWARF_ONE_KNOWN_DW_LNCT (directory_index, DW_LNCT_directory_index) \ + DWARF_ONE_KNOWN_DW_LNCT (path, DW_LNCT_path) \ + DWARF_ONE_KNOWN_DW_LNCT (size, DW_LNCT_size) \ + DWARF_ONE_KNOWN_DW_LNCT (timestamp, DW_LNCT_timestamp) \ + /* End of DW_LNCT_*. */ + +#define DWARF_ALL_KNOWN_DW_LNE \ + DWARF_ONE_KNOWN_DW_LNE (NVIDIA_inlined_call, DW_LNE_NVIDIA_inlined_call) \ + DWARF_ONE_KNOWN_DW_LNE (NVIDIA_set_function_name, DW_LNE_NVIDIA_set_function_name) \ + DWARF_ONE_KNOWN_DW_LNE (define_file, DW_LNE_define_file) \ + DWARF_ONE_KNOWN_DW_LNE (end_sequence, DW_LNE_end_sequence) \ + DWARF_ONE_KNOWN_DW_LNE (set_address, DW_LNE_set_address) \ + DWARF_ONE_KNOWN_DW_LNE (set_discriminator, DW_LNE_set_discriminator) \ + /* End of DW_LNE_*. */ + +#define DWARF_ALL_KNOWN_DW_LNS \ + DWARF_ONE_KNOWN_DW_LNS (advance_line, DW_LNS_advance_line) \ + DWARF_ONE_KNOWN_DW_LNS (advance_pc, DW_LNS_advance_pc) \ + DWARF_ONE_KNOWN_DW_LNS (const_add_pc, DW_LNS_const_add_pc) \ + DWARF_ONE_KNOWN_DW_LNS (copy, DW_LNS_copy) \ + DWARF_ONE_KNOWN_DW_LNS (fixed_advance_pc, DW_LNS_fixed_advance_pc) \ + DWARF_ONE_KNOWN_DW_LNS (negate_stmt, DW_LNS_negate_stmt) \ + DWARF_ONE_KNOWN_DW_LNS (set_basic_block, DW_LNS_set_basic_block) \ + DWARF_ONE_KNOWN_DW_LNS (set_column, DW_LNS_set_column) \ + DWARF_ONE_KNOWN_DW_LNS (set_epilogue_begin, DW_LNS_set_epilogue_begin) \ + DWARF_ONE_KNOWN_DW_LNS (set_file, DW_LNS_set_file) \ + DWARF_ONE_KNOWN_DW_LNS (set_isa, DW_LNS_set_isa) \ + DWARF_ONE_KNOWN_DW_LNS (set_prologue_end, DW_LNS_set_prologue_end) \ + /* End of DW_LNS_*. */ + +#define DWARF_ALL_KNOWN_DW_MACINFO \ + DWARF_ONE_KNOWN_DW_MACINFO (define, DW_MACINFO_define) \ + DWARF_ONE_KNOWN_DW_MACINFO (end_file, DW_MACINFO_end_file) \ + DWARF_ONE_KNOWN_DW_MACINFO (start_file, DW_MACINFO_start_file) \ + DWARF_ONE_KNOWN_DW_MACINFO (undef, DW_MACINFO_undef) \ + DWARF_ONE_KNOWN_DW_MACINFO (vendor_ext, DW_MACINFO_vendor_ext) \ + /* End of DW_MACINFO_*. */ + +#define DWARF_ALL_KNOWN_DW_MACRO \ + DWARF_ONE_KNOWN_DW_MACRO (define, DW_MACRO_define) \ + DWARF_ONE_KNOWN_DW_MACRO (define_strp, DW_MACRO_define_strp) \ + DWARF_ONE_KNOWN_DW_MACRO (define_strx, DW_MACRO_define_strx) \ + DWARF_ONE_KNOWN_DW_MACRO (define_sup, DW_MACRO_define_sup) \ + DWARF_ONE_KNOWN_DW_MACRO (end_file, DW_MACRO_end_file) \ + DWARF_ONE_KNOWN_DW_MACRO (import, DW_MACRO_import) \ + DWARF_ONE_KNOWN_DW_MACRO (import_sup, DW_MACRO_import_sup) \ + DWARF_ONE_KNOWN_DW_MACRO (start_file, DW_MACRO_start_file) \ + DWARF_ONE_KNOWN_DW_MACRO (undef, DW_MACRO_undef) \ + DWARF_ONE_KNOWN_DW_MACRO (undef_strp, DW_MACRO_undef_strp) \ + DWARF_ONE_KNOWN_DW_MACRO (undef_strx, DW_MACRO_undef_strx) \ + DWARF_ONE_KNOWN_DW_MACRO (undef_sup, DW_MACRO_undef_sup) \ + /* End of DW_MACRO_*. */ + +#define DWARF_ALL_KNOWN_DW_OP \ + DWARF_ONE_KNOWN_DW_OP (GNU_addr_index, DW_OP_GNU_addr_index) \ + DWARF_ONE_KNOWN_DW_OP (GNU_const_index, DW_OP_GNU_const_index) \ + DWARF_ONE_KNOWN_DW_OP (GNU_const_type, DW_OP_GNU_const_type) \ + DWARF_ONE_KNOWN_DW_OP (GNU_convert, DW_OP_GNU_convert) \ + DWARF_ONE_KNOWN_DW_OP (GNU_deref_type, DW_OP_GNU_deref_type) \ + DWARF_ONE_KNOWN_DW_OP (GNU_encoded_addr, DW_OP_GNU_encoded_addr) \ + DWARF_ONE_KNOWN_DW_OP (GNU_entry_value, DW_OP_GNU_entry_value) \ + DWARF_ONE_KNOWN_DW_OP (GNU_implicit_pointer, DW_OP_GNU_implicit_pointer) \ + DWARF_ONE_KNOWN_DW_OP (GNU_parameter_ref, DW_OP_GNU_parameter_ref) \ + DWARF_ONE_KNOWN_DW_OP (GNU_push_tls_address, DW_OP_GNU_push_tls_address) \ + DWARF_ONE_KNOWN_DW_OP (GNU_regval_type, DW_OP_GNU_regval_type) \ + DWARF_ONE_KNOWN_DW_OP (GNU_reinterpret, DW_OP_GNU_reinterpret) \ + DWARF_ONE_KNOWN_DW_OP (GNU_uninit, DW_OP_GNU_uninit) \ + DWARF_ONE_KNOWN_DW_OP (GNU_variable_value, DW_OP_GNU_variable_value) \ + DWARF_ONE_KNOWN_DW_OP (abs, DW_OP_abs) \ + DWARF_ONE_KNOWN_DW_OP (addr, DW_OP_addr) \ + DWARF_ONE_KNOWN_DW_OP (addrx, DW_OP_addrx) \ + DWARF_ONE_KNOWN_DW_OP (and, DW_OP_and) \ + DWARF_ONE_KNOWN_DW_OP (bit_piece, DW_OP_bit_piece) \ + DWARF_ONE_KNOWN_DW_OP (bra, DW_OP_bra) \ + DWARF_ONE_KNOWN_DW_OP (breg0, DW_OP_breg0) \ + DWARF_ONE_KNOWN_DW_OP (breg1, DW_OP_breg1) \ + DWARF_ONE_KNOWN_DW_OP (breg10, DW_OP_breg10) \ + DWARF_ONE_KNOWN_DW_OP (breg11, DW_OP_breg11) \ + DWARF_ONE_KNOWN_DW_OP (breg12, DW_OP_breg12) \ + DWARF_ONE_KNOWN_DW_OP (breg13, DW_OP_breg13) \ + DWARF_ONE_KNOWN_DW_OP (breg14, DW_OP_breg14) \ + DWARF_ONE_KNOWN_DW_OP (breg15, DW_OP_breg15) \ + DWARF_ONE_KNOWN_DW_OP (breg16, DW_OP_breg16) \ + DWARF_ONE_KNOWN_DW_OP (breg17, DW_OP_breg17) \ + DWARF_ONE_KNOWN_DW_OP (breg18, DW_OP_breg18) \ + DWARF_ONE_KNOWN_DW_OP (breg19, DW_OP_breg19) \ + DWARF_ONE_KNOWN_DW_OP (breg2, DW_OP_breg2) \ + DWARF_ONE_KNOWN_DW_OP (breg20, DW_OP_breg20) \ + DWARF_ONE_KNOWN_DW_OP (breg21, DW_OP_breg21) \ + DWARF_ONE_KNOWN_DW_OP (breg22, DW_OP_breg22) \ + DWARF_ONE_KNOWN_DW_OP (breg23, DW_OP_breg23) \ + DWARF_ONE_KNOWN_DW_OP (breg24, DW_OP_breg24) \ + DWARF_ONE_KNOWN_DW_OP (breg25, DW_OP_breg25) \ + DWARF_ONE_KNOWN_DW_OP (breg26, DW_OP_breg26) \ + DWARF_ONE_KNOWN_DW_OP (breg27, DW_OP_breg27) \ + DWARF_ONE_KNOWN_DW_OP (breg28, DW_OP_breg28) \ + DWARF_ONE_KNOWN_DW_OP (breg29, DW_OP_breg29) \ + DWARF_ONE_KNOWN_DW_OP (breg3, DW_OP_breg3) \ + DWARF_ONE_KNOWN_DW_OP (breg30, DW_OP_breg30) \ + DWARF_ONE_KNOWN_DW_OP (breg31, DW_OP_breg31) \ + DWARF_ONE_KNOWN_DW_OP (breg4, DW_OP_breg4) \ + DWARF_ONE_KNOWN_DW_OP (breg5, DW_OP_breg5) \ + DWARF_ONE_KNOWN_DW_OP (breg6, DW_OP_breg6) \ + DWARF_ONE_KNOWN_DW_OP (breg7, DW_OP_breg7) \ + DWARF_ONE_KNOWN_DW_OP (breg8, DW_OP_breg8) \ + DWARF_ONE_KNOWN_DW_OP (breg9, DW_OP_breg9) \ + DWARF_ONE_KNOWN_DW_OP (bregx, DW_OP_bregx) \ + DWARF_ONE_KNOWN_DW_OP (call2, DW_OP_call2) \ + DWARF_ONE_KNOWN_DW_OP (call4, DW_OP_call4) \ + DWARF_ONE_KNOWN_DW_OP (call_frame_cfa, DW_OP_call_frame_cfa) \ + DWARF_ONE_KNOWN_DW_OP (call_ref, DW_OP_call_ref) \ + DWARF_ONE_KNOWN_DW_OP (const1s, DW_OP_const1s) \ + DWARF_ONE_KNOWN_DW_OP (const1u, DW_OP_const1u) \ + DWARF_ONE_KNOWN_DW_OP (const2s, DW_OP_const2s) \ + DWARF_ONE_KNOWN_DW_OP (const2u, DW_OP_const2u) \ + DWARF_ONE_KNOWN_DW_OP (const4s, DW_OP_const4s) \ + DWARF_ONE_KNOWN_DW_OP (const4u, DW_OP_const4u) \ + DWARF_ONE_KNOWN_DW_OP (const8s, DW_OP_const8s) \ + DWARF_ONE_KNOWN_DW_OP (const8u, DW_OP_const8u) \ + DWARF_ONE_KNOWN_DW_OP (const_type, DW_OP_const_type) \ + DWARF_ONE_KNOWN_DW_OP (consts, DW_OP_consts) \ + DWARF_ONE_KNOWN_DW_OP (constu, DW_OP_constu) \ + DWARF_ONE_KNOWN_DW_OP (constx, DW_OP_constx) \ + DWARF_ONE_KNOWN_DW_OP (convert, DW_OP_convert) \ + DWARF_ONE_KNOWN_DW_OP (deref, DW_OP_deref) \ + DWARF_ONE_KNOWN_DW_OP (deref_size, DW_OP_deref_size) \ + DWARF_ONE_KNOWN_DW_OP (deref_type, DW_OP_deref_type) \ + DWARF_ONE_KNOWN_DW_OP (div, DW_OP_div) \ + DWARF_ONE_KNOWN_DW_OP (drop, DW_OP_drop) \ + DWARF_ONE_KNOWN_DW_OP (dup, DW_OP_dup) \ + DWARF_ONE_KNOWN_DW_OP (entry_value, DW_OP_entry_value) \ + DWARF_ONE_KNOWN_DW_OP (eq, DW_OP_eq) \ + DWARF_ONE_KNOWN_DW_OP (fbreg, DW_OP_fbreg) \ + DWARF_ONE_KNOWN_DW_OP (form_tls_address, DW_OP_form_tls_address) \ + DWARF_ONE_KNOWN_DW_OP (ge, DW_OP_ge) \ + DWARF_ONE_KNOWN_DW_OP (gt, DW_OP_gt) \ + DWARF_ONE_KNOWN_DW_OP (implicit_pointer, DW_OP_implicit_pointer) \ + DWARF_ONE_KNOWN_DW_OP (implicit_value, DW_OP_implicit_value) \ + DWARF_ONE_KNOWN_DW_OP (le, DW_OP_le) \ + DWARF_ONE_KNOWN_DW_OP (lit0, DW_OP_lit0) \ + DWARF_ONE_KNOWN_DW_OP (lit1, DW_OP_lit1) \ + DWARF_ONE_KNOWN_DW_OP (lit10, DW_OP_lit10) \ + DWARF_ONE_KNOWN_DW_OP (lit11, DW_OP_lit11) \ + DWARF_ONE_KNOWN_DW_OP (lit12, DW_OP_lit12) \ + DWARF_ONE_KNOWN_DW_OP (lit13, DW_OP_lit13) \ + DWARF_ONE_KNOWN_DW_OP (lit14, DW_OP_lit14) \ + DWARF_ONE_KNOWN_DW_OP (lit15, DW_OP_lit15) \ + DWARF_ONE_KNOWN_DW_OP (lit16, DW_OP_lit16) \ + DWARF_ONE_KNOWN_DW_OP (lit17, DW_OP_lit17) \ + DWARF_ONE_KNOWN_DW_OP (lit18, DW_OP_lit18) \ + DWARF_ONE_KNOWN_DW_OP (lit19, DW_OP_lit19) \ + DWARF_ONE_KNOWN_DW_OP (lit2, DW_OP_lit2) \ + DWARF_ONE_KNOWN_DW_OP (lit20, DW_OP_lit20) \ + DWARF_ONE_KNOWN_DW_OP (lit21, DW_OP_lit21) \ + DWARF_ONE_KNOWN_DW_OP (lit22, DW_OP_lit22) \ + DWARF_ONE_KNOWN_DW_OP (lit23, DW_OP_lit23) \ + DWARF_ONE_KNOWN_DW_OP (lit24, DW_OP_lit24) \ + DWARF_ONE_KNOWN_DW_OP (lit25, DW_OP_lit25) \ + DWARF_ONE_KNOWN_DW_OP (lit26, DW_OP_lit26) \ + DWARF_ONE_KNOWN_DW_OP (lit27, DW_OP_lit27) \ + DWARF_ONE_KNOWN_DW_OP (lit28, DW_OP_lit28) \ + DWARF_ONE_KNOWN_DW_OP (lit29, DW_OP_lit29) \ + DWARF_ONE_KNOWN_DW_OP (lit3, DW_OP_lit3) \ + DWARF_ONE_KNOWN_DW_OP (lit30, DW_OP_lit30) \ + DWARF_ONE_KNOWN_DW_OP (lit31, DW_OP_lit31) \ + DWARF_ONE_KNOWN_DW_OP (lit4, DW_OP_lit4) \ + DWARF_ONE_KNOWN_DW_OP (lit5, DW_OP_lit5) \ + DWARF_ONE_KNOWN_DW_OP (lit6, DW_OP_lit6) \ + DWARF_ONE_KNOWN_DW_OP (lit7, DW_OP_lit7) \ + DWARF_ONE_KNOWN_DW_OP (lit8, DW_OP_lit8) \ + DWARF_ONE_KNOWN_DW_OP (lit9, DW_OP_lit9) \ + DWARF_ONE_KNOWN_DW_OP (lt, DW_OP_lt) \ + DWARF_ONE_KNOWN_DW_OP (minus, DW_OP_minus) \ + DWARF_ONE_KNOWN_DW_OP (mod, DW_OP_mod) \ + DWARF_ONE_KNOWN_DW_OP (mul, DW_OP_mul) \ + DWARF_ONE_KNOWN_DW_OP (ne, DW_OP_ne) \ + DWARF_ONE_KNOWN_DW_OP (neg, DW_OP_neg) \ + DWARF_ONE_KNOWN_DW_OP (nop, DW_OP_nop) \ + DWARF_ONE_KNOWN_DW_OP (not, DW_OP_not) \ + DWARF_ONE_KNOWN_DW_OP (or, DW_OP_or) \ + DWARF_ONE_KNOWN_DW_OP (over, DW_OP_over) \ + DWARF_ONE_KNOWN_DW_OP (pick, DW_OP_pick) \ + DWARF_ONE_KNOWN_DW_OP (piece, DW_OP_piece) \ + DWARF_ONE_KNOWN_DW_OP (plus, DW_OP_plus) \ + DWARF_ONE_KNOWN_DW_OP (plus_uconst, DW_OP_plus_uconst) \ + DWARF_ONE_KNOWN_DW_OP (push_object_address, DW_OP_push_object_address) \ + DWARF_ONE_KNOWN_DW_OP (reg0, DW_OP_reg0) \ + DWARF_ONE_KNOWN_DW_OP (reg1, DW_OP_reg1) \ + DWARF_ONE_KNOWN_DW_OP (reg10, DW_OP_reg10) \ + DWARF_ONE_KNOWN_DW_OP (reg11, DW_OP_reg11) \ + DWARF_ONE_KNOWN_DW_OP (reg12, DW_OP_reg12) \ + DWARF_ONE_KNOWN_DW_OP (reg13, DW_OP_reg13) \ + DWARF_ONE_KNOWN_DW_OP (reg14, DW_OP_reg14) \ + DWARF_ONE_KNOWN_DW_OP (reg15, DW_OP_reg15) \ + DWARF_ONE_KNOWN_DW_OP (reg16, DW_OP_reg16) \ + DWARF_ONE_KNOWN_DW_OP (reg17, DW_OP_reg17) \ + DWARF_ONE_KNOWN_DW_OP (reg18, DW_OP_reg18) \ + DWARF_ONE_KNOWN_DW_OP (reg19, DW_OP_reg19) \ + DWARF_ONE_KNOWN_DW_OP (reg2, DW_OP_reg2) \ + DWARF_ONE_KNOWN_DW_OP (reg20, DW_OP_reg20) \ + DWARF_ONE_KNOWN_DW_OP (reg21, DW_OP_reg21) \ + DWARF_ONE_KNOWN_DW_OP (reg22, DW_OP_reg22) \ + DWARF_ONE_KNOWN_DW_OP (reg23, DW_OP_reg23) \ + DWARF_ONE_KNOWN_DW_OP (reg24, DW_OP_reg24) \ + DWARF_ONE_KNOWN_DW_OP (reg25, DW_OP_reg25) \ + DWARF_ONE_KNOWN_DW_OP (reg26, DW_OP_reg26) \ + DWARF_ONE_KNOWN_DW_OP (reg27, DW_OP_reg27) \ + DWARF_ONE_KNOWN_DW_OP (reg28, DW_OP_reg28) \ + DWARF_ONE_KNOWN_DW_OP (reg29, DW_OP_reg29) \ + DWARF_ONE_KNOWN_DW_OP (reg3, DW_OP_reg3) \ + DWARF_ONE_KNOWN_DW_OP (reg30, DW_OP_reg30) \ + DWARF_ONE_KNOWN_DW_OP (reg31, DW_OP_reg31) \ + DWARF_ONE_KNOWN_DW_OP (reg4, DW_OP_reg4) \ + DWARF_ONE_KNOWN_DW_OP (reg5, DW_OP_reg5) \ + DWARF_ONE_KNOWN_DW_OP (reg6, DW_OP_reg6) \ + DWARF_ONE_KNOWN_DW_OP (reg7, DW_OP_reg7) \ + DWARF_ONE_KNOWN_DW_OP (reg8, DW_OP_reg8) \ + DWARF_ONE_KNOWN_DW_OP (reg9, DW_OP_reg9) \ + DWARF_ONE_KNOWN_DW_OP (regval_type, DW_OP_regval_type) \ + DWARF_ONE_KNOWN_DW_OP (regx, DW_OP_regx) \ + DWARF_ONE_KNOWN_DW_OP (reinterpret, DW_OP_reinterpret) \ + DWARF_ONE_KNOWN_DW_OP (rot, DW_OP_rot) \ + DWARF_ONE_KNOWN_DW_OP (shl, DW_OP_shl) \ + DWARF_ONE_KNOWN_DW_OP (shr, DW_OP_shr) \ + DWARF_ONE_KNOWN_DW_OP (shra, DW_OP_shra) \ + DWARF_ONE_KNOWN_DW_OP (skip, DW_OP_skip) \ + DWARF_ONE_KNOWN_DW_OP (stack_value, DW_OP_stack_value) \ + DWARF_ONE_KNOWN_DW_OP (swap, DW_OP_swap) \ + DWARF_ONE_KNOWN_DW_OP (xderef, DW_OP_xderef) \ + DWARF_ONE_KNOWN_DW_OP (xderef_size, DW_OP_xderef_size) \ + DWARF_ONE_KNOWN_DW_OP (xderef_type, DW_OP_xderef_type) \ + DWARF_ONE_KNOWN_DW_OP (xor, DW_OP_xor) \ + /* End of DW_OP_*. */ + +#define DWARF_ALL_KNOWN_DW_ORD \ + DWARF_ONE_KNOWN_DW_ORD (col_major, DW_ORD_col_major) \ + DWARF_ONE_KNOWN_DW_ORD (row_major, DW_ORD_row_major) \ + /* End of DW_ORD_*. */ + +#define DWARF_ALL_KNOWN_DW_RLE \ + DWARF_ONE_KNOWN_DW_RLE (base_address, DW_RLE_base_address) \ + DWARF_ONE_KNOWN_DW_RLE (base_addressx, DW_RLE_base_addressx) \ + DWARF_ONE_KNOWN_DW_RLE (end_of_list, DW_RLE_end_of_list) \ + DWARF_ONE_KNOWN_DW_RLE (offset_pair, DW_RLE_offset_pair) \ + DWARF_ONE_KNOWN_DW_RLE (start_end, DW_RLE_start_end) \ + DWARF_ONE_KNOWN_DW_RLE (start_length, DW_RLE_start_length) \ + DWARF_ONE_KNOWN_DW_RLE (startx_endx, DW_RLE_startx_endx) \ + DWARF_ONE_KNOWN_DW_RLE (startx_length, DW_RLE_startx_length) \ + /* End of DW_RLE_*. */ + +#define DWARF_ALL_KNOWN_DW_SECT_INFO \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + DWARF_ONE_KNOWN_DW_SECT_INFO (, DW_SECT_INFO_) \ + /* End of DW_SECT_INFO_*. */ + +#define DWARF_ALL_KNOWN_DW_TAG \ + DWARF_ONE_KNOWN_DW_TAG (GNU_BINCL, DW_TAG_GNU_BINCL) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_EINCL, DW_TAG_GNU_EINCL) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_call_site, DW_TAG_GNU_call_site) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_call_site_parameter, DW_TAG_GNU_call_site_parameter) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_formal_parameter_pack, DW_TAG_GNU_formal_parameter_pack) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_template_parameter_pack, DW_TAG_GNU_template_parameter_pack) \ + DWARF_ONE_KNOWN_DW_TAG (GNU_template_template_param, DW_TAG_GNU_template_template_param) \ + DWARF_ONE_KNOWN_DW_TAG (MIPS_loop, DW_TAG_MIPS_loop) \ + DWARF_ONE_KNOWN_DW_TAG (access_declaration, DW_TAG_access_declaration) \ + DWARF_ONE_KNOWN_DW_TAG (array_type, DW_TAG_array_type) \ + DWARF_ONE_KNOWN_DW_TAG (atomic_type, DW_TAG_atomic_type) \ + DWARF_ONE_KNOWN_DW_TAG (base_type, DW_TAG_base_type) \ + DWARF_ONE_KNOWN_DW_TAG (call_site, DW_TAG_call_site) \ + DWARF_ONE_KNOWN_DW_TAG (call_site_parameter, DW_TAG_call_site_parameter) \ + DWARF_ONE_KNOWN_DW_TAG (catch_block, DW_TAG_catch_block) \ + DWARF_ONE_KNOWN_DW_TAG (class_template, DW_TAG_class_template) \ + DWARF_ONE_KNOWN_DW_TAG (class_type, DW_TAG_class_type) \ + DWARF_ONE_KNOWN_DW_TAG (coarray_type, DW_TAG_coarray_type) \ + DWARF_ONE_KNOWN_DW_TAG (common_block, DW_TAG_common_block) \ + DWARF_ONE_KNOWN_DW_TAG (common_inclusion, DW_TAG_common_inclusion) \ + DWARF_ONE_KNOWN_DW_TAG (compile_unit, DW_TAG_compile_unit) \ + DWARF_ONE_KNOWN_DW_TAG (condition, DW_TAG_condition) \ + DWARF_ONE_KNOWN_DW_TAG (const_type, DW_TAG_const_type) \ + DWARF_ONE_KNOWN_DW_TAG (constant, DW_TAG_constant) \ + DWARF_ONE_KNOWN_DW_TAG (dwarf_procedure, DW_TAG_dwarf_procedure) \ + DWARF_ONE_KNOWN_DW_TAG (dynamic_type, DW_TAG_dynamic_type) \ + DWARF_ONE_KNOWN_DW_TAG (entry_point, DW_TAG_entry_point) \ + DWARF_ONE_KNOWN_DW_TAG (enumeration_type, DW_TAG_enumeration_type) \ + DWARF_ONE_KNOWN_DW_TAG (enumerator, DW_TAG_enumerator) \ + DWARF_ONE_KNOWN_DW_TAG (file_type, DW_TAG_file_type) \ + DWARF_ONE_KNOWN_DW_TAG (formal_parameter, DW_TAG_formal_parameter) \ + DWARF_ONE_KNOWN_DW_TAG (format_label, DW_TAG_format_label) \ + DWARF_ONE_KNOWN_DW_TAG (friend, DW_TAG_friend) \ + DWARF_ONE_KNOWN_DW_TAG (function_template, DW_TAG_function_template) \ + DWARF_ONE_KNOWN_DW_TAG (generic_subrange, DW_TAG_generic_subrange) \ + DWARF_ONE_KNOWN_DW_TAG (immutable_type, DW_TAG_immutable_type) \ + DWARF_ONE_KNOWN_DW_TAG (imported_declaration, DW_TAG_imported_declaration) \ + DWARF_ONE_KNOWN_DW_TAG (imported_module, DW_TAG_imported_module) \ + DWARF_ONE_KNOWN_DW_TAG (imported_unit, DW_TAG_imported_unit) \ + DWARF_ONE_KNOWN_DW_TAG (inheritance, DW_TAG_inheritance) \ + DWARF_ONE_KNOWN_DW_TAG (inlined_subroutine, DW_TAG_inlined_subroutine) \ + DWARF_ONE_KNOWN_DW_TAG (interface_type, DW_TAG_interface_type) \ + DWARF_ONE_KNOWN_DW_TAG (label, DW_TAG_label) \ + DWARF_ONE_KNOWN_DW_TAG (lexical_block, DW_TAG_lexical_block) \ + DWARF_ONE_KNOWN_DW_TAG (member, DW_TAG_member) \ + DWARF_ONE_KNOWN_DW_TAG (module, DW_TAG_module) \ + DWARF_ONE_KNOWN_DW_TAG (namelist, DW_TAG_namelist) \ + DWARF_ONE_KNOWN_DW_TAG (namelist_item, DW_TAG_namelist_item) \ + DWARF_ONE_KNOWN_DW_TAG (namespace, DW_TAG_namespace) \ + DWARF_ONE_KNOWN_DW_TAG (packed_type, DW_TAG_packed_type) \ + DWARF_ONE_KNOWN_DW_TAG (partial_unit, DW_TAG_partial_unit) \ + DWARF_ONE_KNOWN_DW_TAG (pointer_type, DW_TAG_pointer_type) \ + DWARF_ONE_KNOWN_DW_TAG (ptr_to_member_type, DW_TAG_ptr_to_member_type) \ + DWARF_ONE_KNOWN_DW_TAG (reference_type, DW_TAG_reference_type) \ + DWARF_ONE_KNOWN_DW_TAG (restrict_type, DW_TAG_restrict_type) \ + DWARF_ONE_KNOWN_DW_TAG (rvalue_reference_type, DW_TAG_rvalue_reference_type) \ + DWARF_ONE_KNOWN_DW_TAG (set_type, DW_TAG_set_type) \ + DWARF_ONE_KNOWN_DW_TAG (shared_type, DW_TAG_shared_type) \ + DWARF_ONE_KNOWN_DW_TAG (skeleton_unit, DW_TAG_skeleton_unit) \ + DWARF_ONE_KNOWN_DW_TAG (string_type, DW_TAG_string_type) \ + DWARF_ONE_KNOWN_DW_TAG (structure_type, DW_TAG_structure_type) \ + DWARF_ONE_KNOWN_DW_TAG (subprogram, DW_TAG_subprogram) \ + DWARF_ONE_KNOWN_DW_TAG (subrange_type, DW_TAG_subrange_type) \ + DWARF_ONE_KNOWN_DW_TAG (subroutine_type, DW_TAG_subroutine_type) \ + DWARF_ONE_KNOWN_DW_TAG (template_alias, DW_TAG_template_alias) \ + DWARF_ONE_KNOWN_DW_TAG (template_type_parameter, DW_TAG_template_type_parameter) \ + DWARF_ONE_KNOWN_DW_TAG (template_value_parameter, DW_TAG_template_value_parameter) \ + DWARF_ONE_KNOWN_DW_TAG (thrown_type, DW_TAG_thrown_type) \ + DWARF_ONE_KNOWN_DW_TAG (try_block, DW_TAG_try_block) \ + DWARF_ONE_KNOWN_DW_TAG (type_unit, DW_TAG_type_unit) \ + DWARF_ONE_KNOWN_DW_TAG (typedef, DW_TAG_typedef) \ + DWARF_ONE_KNOWN_DW_TAG (union_type, DW_TAG_union_type) \ + DWARF_ONE_KNOWN_DW_TAG (unspecified_parameters, DW_TAG_unspecified_parameters) \ + DWARF_ONE_KNOWN_DW_TAG (unspecified_type, DW_TAG_unspecified_type) \ + DWARF_ONE_KNOWN_DW_TAG (variable, DW_TAG_variable) \ + DWARF_ONE_KNOWN_DW_TAG (variant, DW_TAG_variant) \ + DWARF_ONE_KNOWN_DW_TAG (variant_part, DW_TAG_variant_part) \ + DWARF_ONE_KNOWN_DW_TAG (volatile_type, DW_TAG_volatile_type) \ + DWARF_ONE_KNOWN_DW_TAG (with_stmt, DW_TAG_with_stmt) \ + /* End of DW_TAG_*. */ + +#define DWARF_ALL_KNOWN_DW_UT \ + DWARF_ONE_KNOWN_DW_UT (compile, DW_UT_compile) \ + DWARF_ONE_KNOWN_DW_UT (partial, DW_UT_partial) \ + DWARF_ONE_KNOWN_DW_UT (skeleton, DW_UT_skeleton) \ + DWARF_ONE_KNOWN_DW_UT (split_compile, DW_UT_split_compile) \ + DWARF_ONE_KNOWN_DW_UT (split_type, DW_UT_split_type) \ + DWARF_ONE_KNOWN_DW_UT (type, DW_UT_type) \ + /* End of DW_UT_*. */ + +#define DWARF_ALL_KNOWN_DW_VIRTUALITY \ + DWARF_ONE_KNOWN_DW_VIRTUALITY (none, DW_VIRTUALITY_none) \ + DWARF_ONE_KNOWN_DW_VIRTUALITY (pure_virtual, DW_VIRTUALITY_pure_virtual) \ + DWARF_ONE_KNOWN_DW_VIRTUALITY (virtual, DW_VIRTUALITY_virtual) \ + /* End of DW_VIRTUALITY_*. */ + +#define DWARF_ALL_KNOWN_DW_VIS \ + DWARF_ONE_KNOWN_DW_VIS (exported, DW_VIS_exported) \ + DWARF_ONE_KNOWN_DW_VIS (local, DW_VIS_local) \ + DWARF_ONE_KNOWN_DW_VIS (qualified, DW_VIS_qualified) \ + /* End of DW_VIS_*. */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libasm.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libasm.h new file mode 100644 index 000000000..b67b77dc9 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libasm.h @@ -0,0 +1,203 @@ +/* Interface for libasm. + Copyright (C) 2002, 2005, 2008 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBASM_H +#define _LIBASM_H 1 + +#include +#include +#include + +typedef struct ebl Ebl; + + +/* Opaque type for the assembler context descriptor. */ +typedef struct AsmCtx AsmCtx_t; + +/* Opaque type for a section. */ +typedef struct AsmScn AsmScn_t; + +/* Opaque type for a section group. */ +typedef struct AsmScnGrp AsmScnGrp_t; + +/* Opaque type for a symbol. */ +typedef struct AsmSym AsmSym_t; + + +/* Opaque type for the disassembler context descriptor. */ +typedef struct DisasmCtx DisasmCtx_t; + +/* Type used for callback functions to retrieve symbol name. The + symbol reference is in the section designated by the second parameter + at an offset described by the first parameter. The value is the + third parameter. */ +typedef int (*DisasmGetSymCB_t) (GElf_Addr, Elf32_Word, GElf_Addr, char **, + size_t *, void *); + +/* Output function callback. */ +typedef int (*DisasmOutputCB_t) (char *, size_t, void *); + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create output file and return descriptor for assembler context. If + TEXTP is true the output is an assembler format text file. + Otherwise an object file is created. The MACHINE parameter + corresponds to an EM_ constant from , KLASS specifies the + class (32- or 64-bit), and DATA specifies the byte order (little or + big endian). */ +extern AsmCtx_t *asm_begin (const char *fname, Ebl *ebl, bool textp); + +/* Abort the operation on the assembler context and free all resources. */ +extern int asm_abort (AsmCtx_t *ctx); + +/* Finalize output file and free all resources. */ +extern int asm_end (AsmCtx_t *ctx); + + +/* Return handle for the named section. If it was not used before + create it. */ +extern AsmScn_t *asm_newscn (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags); + + +/* Similar to 'asm_newscn', but make it part of section group GRP. */ +extern AsmScn_t *asm_newscn_ingrp (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags, + AsmScnGrp_t *grp); + +/* Create new subsection NR in the given section. */ +extern AsmScn_t *asm_newsubscn (AsmScn_t *asmscn, unsigned int nr); + + +/* Return handle for new section group. The signature symbol can be + set later. */ +extern AsmScnGrp_t *asm_newscngrp (AsmCtx_t *ctx, const char *grpname, + AsmSym_t *signature, Elf32_Word flags); + +/* Set or overwrite signature symbol for group. */ +extern int asm_scngrp_newsignature (AsmScnGrp_t *grp, AsmSym_t *signature); + + +/* Add zero terminated string STR of size LEN to (sub)section ASMSCN. */ +extern int asm_addstrz (AsmScn_t *asmscn, const char *str, size_t len); + +/* Add 8-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint8 (AsmScn_t *asmscn, int8_t num); + +/* Add 8-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint8 (AsmScn_t *asmscn, uint8_t num); + +/* Add 16-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint16 (AsmScn_t *asmscn, int16_t num); + +/* Add 16-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint16 (AsmScn_t *asmscn, uint16_t num); + +/* Add 32-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint32 (AsmScn_t *asmscn, int32_t num); + +/* Add 32-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint32 (AsmScn_t *asmscn, uint32_t num); + +/* Add 64-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint64 (AsmScn_t *asmscn, int64_t num); + +/* Add 64-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint64 (AsmScn_t *asmscn, uint64_t num); + + +/* Add signed little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_addsleb128 (AsmScn_t *asmscn, int32_t num); + +/* Add unsigned little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_adduleb128 (AsmScn_t *asmscn, uint32_t num); + + +/* Define new symbol NAME for current position in given section ASMSCN. */ +extern AsmSym_t *asm_newsym (AsmScn_t *asmscn, const char *name, + GElf_Xword size, int type, int binding); + + +/* Define new common symbol NAME with given SIZE and alignment. */ +extern AsmSym_t *asm_newcomsym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr align); + +/* Define new common symbol NAME with given SIZE, VALUE, TYPE, and BINDING. */ +extern AsmSym_t *asm_newabssym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr value, + int type, int binding); + + +/* Align (sub)section offset according to VALUE. */ +extern int asm_align (AsmScn_t *asmscn, GElf_Word value); + +/* Set the byte pattern used to fill gaps created by alignment. */ +extern int asm_fill (AsmScn_t *asmscn, void *bytes, size_t len); + + +/* Return ELF descriptor created for the output file of the given context. */ +extern Elf *asm_getelf (AsmCtx_t *ctx); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int asm_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *asm_errmsg (int __error); + + +/* Create context descriptor for disassembler. */ +extern DisasmCtx_t *disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb); + +/* Release descriptor for disassembler. */ +extern int disasm_end (DisasmCtx_t *ctx); + +/* Produce of disassembly output for given memory, store text in + provided buffer. */ +extern int disasm_str (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + char **bufp, size_t len, void *symcbarg); + +/* Produce disassembly output for given memory and output it using the + given callback functions. */ +extern int disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + DisasmOutputCB_t outcb, void *outcbarg, void *symcbarg); + +#ifdef __cplusplus +} +#endif + +#endif /* libasm.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdw.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdw.h new file mode 100644 index 000000000..64d1689a3 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdw.h @@ -0,0 +1,1120 @@ +/* Interfaces for libdw. + Copyright (C) 2002-2010, 2013, 2014, 2016, 2018 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBDW_H +#define _LIBDW_H 1 + +#include +#include +#include +#include + +/* Mode for the session. */ +typedef enum + { + DWARF_C_READ, /* Read .. */ + DWARF_C_RDWR, /* Read and write .. */ + DWARF_C_WRITE, /* Write .. */ + } +Dwarf_Cmd; + + +/* Callback results. */ +enum +{ + DWARF_CB_OK = 0, + DWARF_CB_ABORT +}; + + +/* Error values. */ +enum + { + DW_TAG_invalid = 0 +#define DW_TAG_invalid DW_TAG_invalid + }; + + +/* Type for offset in DWARF file. */ +typedef GElf_Off Dwarf_Off; + +/* Type for address in DWARF file. */ +typedef GElf_Addr Dwarf_Addr; + +/* Integer types. Big enough to hold any numeric value. */ +typedef GElf_Xword Dwarf_Word; +typedef GElf_Sxword Dwarf_Sword; +/* For the times we know we do not need that much. */ +typedef GElf_Half Dwarf_Half; + + +/* DWARF abbreviation record. */ +typedef struct Dwarf_Abbrev Dwarf_Abbrev; + +/* Returned to show the last DIE has be returned. */ +#define DWARF_END_ABBREV ((Dwarf_Abbrev *) -1l) + +/* Source code line information for CU. */ +typedef struct Dwarf_Lines_s Dwarf_Lines; + +/* One source code line information. */ +typedef struct Dwarf_Line_s Dwarf_Line; + +/* Source file information. */ +typedef struct Dwarf_Files_s Dwarf_Files; + +/* One address range record. */ +typedef struct Dwarf_Arange_s Dwarf_Arange; + +/* Address ranges of a file. */ +typedef struct Dwarf_Aranges_s Dwarf_Aranges; + +/* CU representation. */ +struct Dwarf_CU; +typedef struct Dwarf_CU Dwarf_CU; + +/* Macro information. */ +typedef struct Dwarf_Macro_s Dwarf_Macro; + +/* Attribute representation. */ +typedef struct +{ + unsigned int code; + unsigned int form; + unsigned char *valp; + struct Dwarf_CU *cu; +} Dwarf_Attribute; + + +/* Data block representation. */ +typedef struct +{ + Dwarf_Word length; + unsigned char *data; +} Dwarf_Block; + + +/* DIE information. */ +typedef struct +{ + /* The offset can be computed from the address. */ + void *addr; + struct Dwarf_CU *cu; + Dwarf_Abbrev *abbrev; + // XXX We'll see what other information will be needed. + long int padding__; +} Dwarf_Die; + +/* Returned to show the last DIE has be returned. */ +#define DWARF_END_DIE ((Dwarf_Die *) -1l) + + +/* Global symbol information. */ +typedef struct +{ + Dwarf_Off cu_offset; + Dwarf_Off die_offset; + const char *name; +} Dwarf_Global; + + +/* One operation in a DWARF location expression. + A location expression is an array of these. */ +typedef struct +{ + uint8_t atom; /* Operation */ + Dwarf_Word number; /* Operand */ + Dwarf_Word number2; /* Possible second operand */ + Dwarf_Word offset; /* Offset in location expression */ +} Dwarf_Op; + + +/* This describes one Common Information Entry read from a CFI section. + Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi. */ +typedef struct +{ + Dwarf_Off CIE_id; /* Always DW_CIE_ID_64 in Dwarf_CIE structures. */ + + /* Instruction stream describing initial state used by FDEs. If + we did not understand the whole augmentation string and it did + not use 'z', then there might be more augmentation data here + (and in FDEs) before the actual instructions. */ + const uint8_t *initial_instructions; + const uint8_t *initial_instructions_end; + + Dwarf_Word code_alignment_factor; + Dwarf_Sword data_alignment_factor; + Dwarf_Word return_address_register; + + const char *augmentation; /* Augmentation string. */ + + /* Augmentation data, might be NULL. The size is correct only if + we understood the augmentation string sufficiently. */ + const uint8_t *augmentation_data; + size_t augmentation_data_size; + size_t fde_augmentation_data_size; +} Dwarf_CIE; + +/* This describes one Frame Description Entry read from a CFI section. + Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi. */ +typedef struct +{ + /* Section offset of CIE this FDE refers to. This will never be + DW_CIE_ID_64 in an FDE. If this value is DW_CIE_ID_64, this is + actually a Dwarf_CIE structure. */ + Dwarf_Off CIE_pointer; + + /* We can't really decode anything further without looking up the CIE + and checking its augmentation string. Here follows the encoded + initial_location and address_range, then any augmentation data, + then the instruction stream. This FDE describes PC locations in + the byte range [initial_location, initial_location+address_range). + When the CIE augmentation string uses 'z', the augmentation data is + a DW_FORM_block (self-sized). Otherwise, when we understand the + augmentation string completely, fde_augmentation_data_size gives + the number of bytes of augmentation data before the instructions. */ + const uint8_t *start; + const uint8_t *end; +} Dwarf_FDE; + +/* Each entry in a CFI section is either a CIE described by Dwarf_CIE or + an FDE described by Dward_FDE. Check CIE_id to see which you have. */ +typedef union +{ + Dwarf_Off CIE_id; /* Always DW_CIE_ID_64 in Dwarf_CIE structures. */ + Dwarf_CIE cie; + Dwarf_FDE fde; +} Dwarf_CFI_Entry; + +/* Same as DW_CIE_ID_64 from dwarf.h to keep libdw.h independent. */ +#define LIBDW_CIE_ID 0xffffffffffffffffULL +#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == LIBDW_CIE_ID) + +/* Opaque type representing a frame state described by CFI. */ +typedef struct Dwarf_Frame_s Dwarf_Frame; + +/* Opaque type representing a CFI section found in a DWARF or ELF file. */ +typedef struct Dwarf_CFI_s Dwarf_CFI; + + +/* Handle for debug sessions. */ +typedef struct Dwarf Dwarf; + + +/* Out-Of-Memory handler. */ +typedef void (*__noreturn_attribute__ Dwarf_OOM) (void); + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create a handle for a new debug session. */ +extern Dwarf *dwarf_begin (int fildes, Dwarf_Cmd cmd); + +/* Create a handle for a new debug session for an ELF file. */ +extern Dwarf *dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp); + +/* Retrieve ELF descriptor used for DWARF access. */ +extern Elf *dwarf_getelf (Dwarf *dwarf); + +/* Retrieve DWARF descriptor used for a Dwarf_Die or Dwarf_Attribute. + A Dwarf_Die or a Dwarf_Attribute is associated with a particular + Dwarf_CU handle. This function returns the DWARF descriptor for + that Dwarf_CU. */ +extern Dwarf *dwarf_cu_getdwarf (Dwarf_CU *cu); + +/* Retrieves the DWARF descriptor for debugaltlink data. Returns NULL + if no alternate debug data has been supplied yet. libdw will try + to set the alt file on first use of an alt FORM if not yet explicitly + provided by dwarf_setalt. */ +extern Dwarf *dwarf_getalt (Dwarf *main); + +/* Provides the data referenced by the .gnu_debugaltlink section. The + caller should check that MAIN and ALT match (i.e., they have the + same build ID). It is the responsibility of the caller to ensure + that the data referenced by ALT stays valid while it is used by + MAIN, until dwarf_setalt is called on MAIN with a different + descriptor, or dwarf_end. Must be called before inspecting DIEs + that might have alt FORMs. Otherwise libdw will try to set the + alt file itself on first use. */ +extern void dwarf_setalt (Dwarf *main, Dwarf *alt); + +/* Release debugging handling context. */ +extern int dwarf_end (Dwarf *dwarf); + + +/* Read the header for the DWARF CU. */ +extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, + size_t *header_sizep, Dwarf_Off *abbrev_offsetp, + uint8_t *address_sizep, uint8_t *offset_sizep) + __nonnull_attribute__ (3); + +/* Read the header of a DWARF CU or type unit. If TYPE_SIGNATUREP is not + null, this reads a type unit from the .debug_types section; otherwise + this reads a CU from the .debug_info section. */ +extern int dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, + size_t *header_sizep, Dwarf_Half *versionp, + Dwarf_Off *abbrev_offsetp, + uint8_t *address_sizep, uint8_t *offset_sizep, + uint64_t *type_signaturep, Dwarf_Off *type_offsetp) + __nonnull_attribute__ (3); + + +/* Gets the next Dwarf_CU (unit), version, unit type and if available + the CU DIE and sub (type) DIE of the unit. Returns 0 on success, + -1 on error or 1 if there are no more units. To start iterating + provide NULL for CU. If version < 5 the unit type is set from the + CU DIE if available (DW_UT_compile for DW_TAG_compile_unit, + DW_UT_type for DW_TAG_type_unit or DW_UT_partial for + DW_TAG_partial_unit), otherwise it is set to zero. If unavailable + (the version or unit type is unknown) the CU DIE is cleared. + Likewise if the sub DIE isn't isn't available (the unit type is not + DW_UT_type or DW_UT_split_type) the sub DIE tag is cleared. */ +extern int dwarf_get_units (Dwarf *dwarf, Dwarf_CU *cu, Dwarf_CU **next_cu, + Dwarf_Half *version, uint8_t *unit_type, + Dwarf_Die *cudie, Dwarf_Die *subdie) + __nonnull_attribute__ (3); + +/* Provides information and DIEs associated with the given Dwarf_CU + unit. Returns -1 on error, zero on success. Arguments not needed + may be NULL. If they are NULL and aren't known yet, they won't be + looked up. If the subdie doesn't exist for this unit_type it will + be cleared. If there is no unit_id for this unit type it will be + set to zero. */ +extern int dwarf_cu_info (Dwarf_CU *cu, + Dwarf_Half *version, uint8_t *unit_type, + Dwarf_Die *cudie, Dwarf_Die *subdie, + uint64_t *unit_id, + uint8_t *address_size, uint8_t *offset_size); + +/* Decode one DWARF CFI entry (CIE or FDE) from the raw section data. + The E_IDENT from the originating ELF file indicates the address + size and byte order used in the CFI section contained in DATA; + EH_FRAME_P should be true for .eh_frame format and false for + .debug_frame format. OFFSET is the byte position in the section + to start at; on return *NEXT_OFFSET is filled in with the byte + position immediately after this entry. + + On success, returns 0 and fills in *ENTRY; use dwarf_cfi_cie_p to + see whether ENTRY->cie or ENTRY->fde is valid. + + On errors, returns -1. Some format errors will permit safely + skipping to the next CFI entry though the current one is unusable. + In that case, *NEXT_OFF will be updated before a -1 return. + + If there are no more CFI entries left in the section, + returns 1 and sets *NEXT_OFFSET to (Dwarf_Off) -1. */ +extern int dwarf_next_cfi (const unsigned char e_ident[], + Elf_Data *data, bool eh_frame_p, + Dwarf_Off offset, Dwarf_Off *next_offset, + Dwarf_CFI_Entry *entry) + __nonnull_attribute__ (1, 2, 5, 6); + +/* Use the CFI in the DWARF .debug_frame section. + Returns NULL if there is no such section (not an error). + The pointer returned can be used until dwarf_end is called on DWARF, + and must not be passed to dwarf_cfi_end. + Calling this more than once returns the same pointer. */ +extern Dwarf_CFI *dwarf_getcfi (Dwarf *dwarf); + +/* Use the CFI in the ELF file's exception-handling data. + Returns NULL if there is no such data. + The pointer returned can be used until elf_end is called on ELF, + and must be passed to dwarf_cfi_end before then. + Calling this more than once allocates independent data structures. */ +extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf); + +/* Release resources allocated by dwarf_getcfi_elf. */ +extern int dwarf_cfi_end (Dwarf_CFI *cache); + + +/* Return DIE at given offset in .debug_info section. */ +extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result) __nonnull_attribute__ (3); + +/* Return DIE at given offset in .debug_types section. */ +extern Dwarf_Die *dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result) + __nonnull_attribute__ (3); + +/* Return offset of DIE. */ +extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die); + +/* Return offset of DIE in CU. */ +extern Dwarf_Off dwarf_cuoffset (Dwarf_Die *die); + +/* Return CU DIE containing given DIE. */ +extern Dwarf_Die *dwarf_diecu (Dwarf_Die *die, Dwarf_Die *result, + uint8_t *address_sizep, uint8_t *offset_sizep) + __nonnull_attribute__ (2); + +/* Given a Dwarf_Die addr returns a (reconstructed) Dwarf_Die, or NULL + if the given addr didn't come from a valid Dwarf_Die. In particular + it will make sure that the correct Dwarf_CU pointer is set for the + Dwarf_Die, the Dwarf_Abbrev pointer will not be set up yet (it will + only be once the Dwarf_Die is used to read attributes, children or + siblings). This functions can be used to keep a reference to a + Dwarf_Die which you want to refer to later. The addr, and the result + of this function, is only valid while the associated Dwarf is valid. */ +extern Dwarf_Die *dwarf_die_addr_die (Dwarf *dbg, void *addr, + Dwarf_Die *result) + __nonnull_attribute__ (3); + +/* Return the CU DIE and the header info associated with a Dwarf_Die + or Dwarf_Attribute. A Dwarf_Die or a Dwarf_Attribute is associated + with a particular Dwarf_CU handle. This function returns the CU or + type unit DIE and header information for that Dwarf_CU. The + returned DIE is either a compile_unit, partial_unit or type_unit. + If it is a type_unit, then the type signature and type offset are + also provided, otherwise type_offset will be set to zero. See also + dwarf_diecu and dwarf_next_unit. */ +extern Dwarf_Die *dwarf_cu_die (Dwarf_CU *cu, Dwarf_Die *result, + Dwarf_Half *versionp, + Dwarf_Off *abbrev_offsetp, + uint8_t *address_sizep, + uint8_t *offset_sizep, + uint64_t *type_signaturep, + Dwarf_Off *type_offsetp) + __nonnull_attribute__ (2); + +/* Return CU DIE containing given address. */ +extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr, + Dwarf_Die *result) __nonnull_attribute__ (3); + +/* Return child of current DIE. */ +extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result) + __nonnull_attribute__ (2); + +/* Locates the first sibling of DIE and places it in RESULT. + Returns 0 if a sibling was found, -1 if something went wrong. + Returns 1 if no sibling could be found and, if RESULT is not + the same as DIE, it sets RESULT->addr to the address of the + (non-sibling) DIE that follows this one, or NULL if this DIE + was the last one in the compilation unit. */ +extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result) + __nonnull_attribute__ (2); + +/* For type aliases and qualifier type DIEs, which don't modify or + change the structural layout of the underlying type, follow the + DW_AT_type attribute (recursively) and return the underlying type + Dwarf_Die. + + Returns 0 when RESULT contains a Dwarf_Die (possibly equal to the + given DIE) that isn't a type alias or qualifier type. Returns 1 + when RESULT contains a type alias or qualifier Dwarf_Die that + couldn't be peeled further (it doesn't have a DW_TAG_type + attribute). Returns -1 when an error occurred. + + The current DWARF specification defines one type alias tag + (DW_TAG_typedef) and seven modifier/qualifier type tags + (DW_TAG_const_type, DW_TAG_volatile_type, DW_TAG_restrict_type, + DW_TAG_atomic_type, DW_TAG_immutable_type, DW_TAG_packed_type and + DW_TAG_shared_type). This function won't peel modifier type + tags that change the way the underlying type is accessed such + as the pointer or reference type tags (DW_TAG_pointer_type, + DW_TAG_reference_type or DW_TAG_rvalue_reference_type). + + A future version of this function might peel other alias or + qualifier type tags if a future DWARF version or GNU extension + defines other type aliases or qualifier type tags that don't modify, + change the structural layout or the way to access the underlying type. */ +extern int dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result) + __nonnull_attribute__ (2); + +/* Check whether the DIE has children. */ +extern int dwarf_haschildren (Dwarf_Die *die) __nonnull_attribute__ (1); + +/* Walks the attributes of DIE, starting at the one OFFSET bytes in, + calling the CALLBACK function for each one. Stops if the callback + function ever returns a value other than DWARF_CB_OK and returns the + offset of the offending attribute. If the end of the attributes + is reached 1 is returned. If something goes wrong -1 is returned and + the dwarf error number is set. */ +extern ptrdiff_t dwarf_getattrs (Dwarf_Die *die, + int (*callback) (Dwarf_Attribute *, void *), + void *arg, ptrdiff_t offset) + __nonnull_attribute__ (2); + +/* Return tag of given DIE. */ +extern int dwarf_tag (Dwarf_Die *die) __nonnull_attribute__ (1); + + +/* Return specific attribute of DIE. */ +extern Dwarf_Attribute *dwarf_attr (Dwarf_Die *die, unsigned int search_name, + Dwarf_Attribute *result) + __nonnull_attribute__ (3); + +/* Check whether given DIE has specific attribute. */ +extern int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name); + +/* These are the same as dwarf_attr and dwarf_hasattr, respectively, + but they resolve an indirect attribute through + DW_AT_abstract_origin, DW_AT_specification or, if the DIE is a + top-level split CU, the skeleton DIE. Note that the attribute + might come from a DIE in a different CU (possibly from a different + Dwarf file). In that case all attribute information needs to be + resolved through the CU associated with the returned + Dwarf_Attribute. The dwarf_form functions already do this + automatically. */ +extern Dwarf_Attribute *dwarf_attr_integrate (Dwarf_Die *die, + unsigned int search_name, + Dwarf_Attribute *result) + __nonnull_attribute__ (3); +extern int dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name); + + + + +/* Check whether given attribute has specific form. */ +extern int dwarf_hasform (Dwarf_Attribute *attr, unsigned int search_form); + +/* Return attribute code of given attribute. */ +extern unsigned int dwarf_whatattr (Dwarf_Attribute *attr); + +/* Return form code of given attribute. */ +extern unsigned int dwarf_whatform (Dwarf_Attribute *attr); + + +/* Return string associated with given attribute. */ +extern const char *dwarf_formstring (Dwarf_Attribute *attrp); + +/* Return unsigned constant represented by attribute. */ +extern int dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval) + __nonnull_attribute__ (2); + +/* Return signed constant represented by attribute. */ +extern int dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_uval) + __nonnull_attribute__ (2); + +/* Return address represented by attribute. */ +extern int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* This function is deprecated. Always use dwarf_formref_die instead. + Return reference offset represented by attribute. */ +extern int dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset) + __nonnull_attribute__ (2) __deprecated_attribute__; + +/* Look up the DIE in a reference-form attribute. */ +extern Dwarf_Die *dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem) + __nonnull_attribute__ (2); + +/* Return block represented by attribute. */ +extern int dwarf_formblock (Dwarf_Attribute *attr, Dwarf_Block *return_block) + __nonnull_attribute__ (2); + +/* Return flag represented by attribute. */ +extern int dwarf_formflag (Dwarf_Attribute *attr, bool *return_bool) + __nonnull_attribute__ (2); + + +/* Simplified attribute value access functions. */ + +/* Return string in name attribute of DIE. */ +extern const char *dwarf_diename (Dwarf_Die *die); + +/* Return high PC attribute of DIE. */ +extern int dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return low PC attribute of DIE. */ +extern int dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return entry_pc or low_pc attribute of DIE. */ +extern int dwarf_entrypc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return 1 if DIE's lowpc/highpc or ranges attributes match the PC address, + 0 if not, or -1 for errors. */ +extern int dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc); + +/* Enumerate the PC address ranges covered by this DIE, covering all + addresses where dwarf_haspc returns true. In the first call OFFSET + should be zero and *BASEP need not be initialized. Returns -1 for + errors, zero when there are no more address ranges to report, or a + nonzero OFFSET value to pass to the next call. Each subsequent call + must preserve *BASEP from the prior call. Successful calls fill in + *STARTP and *ENDP with a contiguous address range. */ +extern ptrdiff_t dwarf_ranges (Dwarf_Die *die, + ptrdiff_t offset, Dwarf_Addr *basep, + Dwarf_Addr *startp, Dwarf_Addr *endp); + + +/* Return byte size attribute of DIE. */ +extern int dwarf_bytesize (Dwarf_Die *die); + +/* Return bit size attribute of DIE. */ +extern int dwarf_bitsize (Dwarf_Die *die); + +/* Return bit offset attribute of DIE. */ +extern int dwarf_bitoffset (Dwarf_Die *die); + +/* Return array order attribute of DIE. */ +extern int dwarf_arrayorder (Dwarf_Die *die); + +/* Return source language attribute of DIE. */ +extern int dwarf_srclang (Dwarf_Die *die); + + +/* Get abbreviation at given offset for given DIE. */ +extern Dwarf_Abbrev *dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset, + size_t *lengthp); + +/* Get abbreviation at given offset in .debug_abbrev section. */ +extern int dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp, + Dwarf_Abbrev *abbrevp) + __nonnull_attribute__ (4); + +/* Get abbreviation code. */ +extern unsigned int dwarf_getabbrevcode (Dwarf_Abbrev *abbrev); + +/* Get abbreviation tag. */ +extern unsigned int dwarf_getabbrevtag (Dwarf_Abbrev *abbrev); + +/* Return true if abbreviation is children flag set. */ +extern int dwarf_abbrevhaschildren (Dwarf_Abbrev *abbrev); + +/* Get number of attributes of abbreviation. */ +extern int dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp) + __nonnull_attribute__ (2); + +/* Get specific attribute of abbreviation. */ +extern int dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, + unsigned int *namep, unsigned int *formp, + Dwarf_Off *offset); + +/* Get specific attribute of abbreviation and any data encoded with it. + Specifically for DW_FORM_implicit_const data will be set to the + constant value associated. */ +extern int dwarf_getabbrevattr_data (Dwarf_Abbrev *abbrev, size_t idx, + unsigned int *namep, unsigned int *formp, + Dwarf_Sword *datap, Dwarf_Off *offset); + +/* Get string from-debug_str section. */ +extern const char *dwarf_getstring (Dwarf *dbg, Dwarf_Off offset, + size_t *lenp); + + +/* Get public symbol information. */ +extern ptrdiff_t dwarf_getpubnames (Dwarf *dbg, + int (*callback) (Dwarf *, Dwarf_Global *, + void *), + void *arg, ptrdiff_t offset) + __nonnull_attribute__ (2); + + +/* Get source file information for CU. */ +extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, + size_t *nlines) __nonnull_attribute__ (2, 3); + +/* Return one of the source lines of the CU. */ +extern Dwarf_Line *dwarf_onesrcline (Dwarf_Lines *lines, size_t idx); + +/* Get the file source files used in the CU. */ +extern int dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, + size_t *nfiles) + __nonnull_attribute__ (2); + + +/* Get source for address in CU. */ +extern Dwarf_Line *dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr); + +/* Get source for file and line number. */ +extern int dwarf_getsrc_file (Dwarf *dbg, const char *fname, int line, int col, + Dwarf_Line ***srcsp, size_t *nsrcs) + __nonnull_attribute__ (2, 5, 6); + + +/* Return line address. */ +extern int dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp); + +/* Return line VLIW operation index. */ +extern int dwarf_lineop_index (Dwarf_Line *line, unsigned int *op_indexp); + +/* Return line number. */ +extern int dwarf_lineno (Dwarf_Line *line, int *linep) + __nonnull_attribute__ (2); + +/* Return column in line. */ +extern int dwarf_linecol (Dwarf_Line *line, int *colp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of a statement. */ +extern int dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for end of sequence. */ +extern int dwarf_lineendsequence (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of a basic block. */ +extern int dwarf_lineblock (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for end of prologue. */ +extern int dwarf_lineprologueend (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of epilogue. */ +extern int dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return instruction-set architecture in this record. */ +extern int dwarf_lineisa (Dwarf_Line *line, unsigned int *isap) + __nonnull_attribute__ (2); + +/* Return code path discriminator in this record. */ +extern int dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp) + __nonnull_attribute__ (2); + + +/* Find line information for address. The returned string is NULL when + an error occurred, or the file path. The file path is either absolute + or relative to the compilation directory. See dwarf_decl_file. */ +extern const char *dwarf_linesrc (Dwarf_Line *line, + Dwarf_Word *mtime, Dwarf_Word *length); + +/* Return the caller of this line if inlined. If not inlined, + return NULL. */ +extern Dwarf_Line *dwarf_linecontext (Dwarf_Lines *lines, Dwarf_Line *line); + +/* Return the function name in this line record. If this line is + inlined, this is the name of the function that was inlined. If this line + is not inlined, return NULL. */ +extern const char *dwarf_linefunctionname (Dwarf *dbg, Dwarf_Line *line); + +/* Return file information. The returned string is NULL when + an error occurred, or the file path. The file path is either absolute + or relative to the compilation directory. See dwarf_decl_file. */ +extern const char *dwarf_filesrc (Dwarf_Files *file, size_t idx, + Dwarf_Word *mtime, Dwarf_Word *length); + +/* Return the Dwarf_Files and index associated with the given Dwarf_Line. */ +extern int dwarf_line_file (Dwarf_Line *line, + Dwarf_Files **files, size_t *idx) + __nonnull_attribute__ (2, 3); + +/* Return the directory list used in the file information extracted. + (*RESULT)[0] is the CU's DW_AT_comp_dir value, and may be null. + (*RESULT)[0..*NDIRS-1] are the compile-time include directory path + encoded by the compiler. */ +extern int dwarf_getsrcdirs (Dwarf_Files *files, + const char *const **result, size_t *ndirs) + __nonnull_attribute__ (2, 3); + +/* Iterates through the debug line units. Returns 0 on success, -1 on + error or 1 if there are no more units. To start iterating use zero + for OFF and set *CU to NULL. On success NEXT_OFF will be set to + the next offset to use. The *CU will be set if this line table + needed a specific CU and needs to be given when calling + dwarf_next_lines again (to help dwarf_next_lines quickly find the + next CU). *CU might be set to NULL when it couldn't be found (the + compilation directory entry will be the empty string in that case) + or for DWARF 5 or later tables, which are self contained. SRCFILES + and SRCLINES may be NULL if the caller is not interested in the + actual line or file table. On success and when not NULL, NFILES + and NLINES will be set to the number of files in the file table and + number of lines in the line table. */ +extern int dwarf_next_lines (Dwarf *dwarf, Dwarf_Off off, + Dwarf_Off *next_off, Dwarf_CU **cu, + Dwarf_Files **srcfiles, size_t *nfiles, + Dwarf_Lines **srclines, size_t *nlines) + __nonnull_attribute__ (3,4); + +/* Return location expression, decoded as a list of operations. */ +extern int dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **expr, + size_t *exprlen) __nonnull_attribute__ (2, 3); + +/* Return location expressions. If the attribute uses a location list, + ADDRESS selects the relevant location expressions from the list. + There can be multiple matches, resulting in multiple expressions to + return. EXPRS and EXPRLENS are parallel arrays of NLOCS slots to + fill in. Returns the number of locations filled in, or -1 for + errors. If EXPRS is a null pointer, stores nothing and returns the + total number of locations. A return value of zero means that the + location list indicated no value is accessible. */ +extern int dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address, + Dwarf_Op **exprs, size_t *exprlens, + size_t nlocs); + +/* Enumerate the locations ranges and descriptions covered by the + given attribute. In the first call OFFSET should be zero and + *BASEP need not be initialized. Returns -1 for errors, zero when + there are no more locations to report, or a nonzero OFFSET + value to pass to the next call. Each subsequent call must preserve + *BASEP from the prior call. Successful calls fill in *STARTP and + *ENDP with a contiguous address range and *EXPR with a pointer to + an array of operations with length *EXPRLEN. If the attribute + describes a single location description and not a location list the + first call (with OFFSET zero) will return the location description + in *EXPR with *STARTP set to zero and *ENDP set to minus one. */ +extern ptrdiff_t dwarf_getlocations (Dwarf_Attribute *attr, + ptrdiff_t offset, Dwarf_Addr *basep, + Dwarf_Addr *startp, Dwarf_Addr *endp, + Dwarf_Op **expr, size_t *exprlen); + +/* Return the block associated with a DW_OP_implicit_value operation. + The OP pointer must point into an expression that dwarf_getlocation + or dwarf_getlocation_addr has returned given the same ATTR. */ +extern int dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Block *return_block) + __nonnull_attribute__ (2, 3); + +/* Return the attribute indicated by a DW_OP_GNU_implicit_pointer operation. + The OP pointer must point into an expression that dwarf_getlocation + or dwarf_getlocation_addr has returned given the same ATTR. + The result is the DW_AT_location or DW_AT_const_value attribute + of the OP->number DIE. */ +extern int dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Attribute *result) + __nonnull_attribute__ (2, 3); + +/* Return the DIE associated with an operation such as + DW_OP_GNU_implicit_pointer, DW_OP_GNU_parameter_ref, DW_OP_GNU_convert, + DW_OP_GNU_reinterpret, DW_OP_GNU_const_type, DW_OP_GNU_regval_type or + DW_OP_GNU_deref_type. The OP pointer must point into an expression that + dwarf_getlocation or dwarf_getlocation_addr has returned given the same + ATTR. The RESULT is a DIE that expresses a type or value needed by the + given OP. */ +extern int dwarf_getlocation_die (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Die *result) + __nonnull_attribute__ (2, 3); + +/* Return the attribute expressing a value associated with an operation such + as DW_OP_implicit_value, DW_OP_GNU_entry_value or DW_OP_GNU_const_type. + The OP pointer must point into an expression that dwarf_getlocation + or dwarf_getlocation_addr has returned given the same ATTR. + The RESULT is a value expressed by an attribute such as DW_AT_location + or DW_AT_const_value. */ +extern int dwarf_getlocation_attr (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Attribute *result) + __nonnull_attribute__ (2, 3); + + +/* Compute the byte-size of a type DIE according to DWARF rules. + For most types, this is just DW_AT_byte_size. + For DW_TAG_array_type it can apply much more complex rules. */ +extern int dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size); + +/* Given a language code, as returned by dwarf_srclan, get the default + lower bound for a subrange type without a lower bound attribute. + Returns zero on success or -1 on failure when the given language + wasn't recognized. */ +extern int dwarf_default_lower_bound (int lang, Dwarf_Sword *result) + __nonnull_attribute__ (2); + +/* Return scope DIEs containing PC address. + Sets *SCOPES to a malloc'd array of Dwarf_Die structures, + and returns the number of elements in the array. + (*SCOPES)[0] is the DIE for the innermost scope containing PC, + (*SCOPES)[1] is the DIE for the scope containing that scope, and so on. + Returns -1 for errors or 0 if no scopes match PC. */ +extern int dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, + Dwarf_Die **scopes); + +/* Return scope DIEs containing the given DIE. + Sets *SCOPES to a malloc'd array of Dwarf_Die structures, + and returns the number of elements in the array. + (*SCOPES)[0] is a copy of DIE. + (*SCOPES)[1] is the DIE for the scope containing that scope, and so on. + Returns -1 for errors or 0 if DIE is not found in any scope entry. */ +extern int dwarf_getscopes_die (Dwarf_Die *die, Dwarf_Die **scopes); + + +/* Search SCOPES[0..NSCOPES-1] for a variable called NAME. + Ignore the first SKIP_SHADOWS scopes that match the name. + If MATCH_FILE is not null, accept only declaration in that source file; + if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration + at that line and column. + + If successful, fill in *RESULT with the DIE of the variable found, + and return N where SCOPES[N] is the scope defining the variable. + Return -1 for errors or -2 for no matching variable found. */ +extern int dwarf_getscopevar (Dwarf_Die *scopes, int nscopes, + const char *name, int skip_shadows, + const char *match_file, + int match_lineno, int match_linecol, + Dwarf_Die *result); + + + +/* Return list address ranges. */ +extern int dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, + size_t *naranges) + __nonnull_attribute__ (2); + +/* Return one of the address range entries. */ +extern Dwarf_Arange *dwarf_onearange (Dwarf_Aranges *aranges, size_t idx); + +/* Return information in address range record. */ +extern int dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp, + Dwarf_Word *lengthp, Dwarf_Off *offsetp); + +/* Get address range which includes given address. */ +extern Dwarf_Arange *dwarf_getarange_addr (Dwarf_Aranges *aranges, + Dwarf_Addr addr); + + + +/* Get functions in CUDIE. The given callback will be called for all + defining DW_TAG_subprograms in the CU DIE tree. If the callback + returns DWARF_CB_ABORT the return value can be used as offset argument + to resume the function to find all remaining functions (this is not + really recommended, since it needs to rewalk the CU DIE tree first till + that offset is found again). If the callback returns DWARF_CB_OK + dwarf_getfuncs will not return but keep calling the callback for each + function DIE it finds. Pass zero for offset on the first call to walk + the full CU DIE tree. If no more functions can be found and the callback + returned DWARF_CB_OK then the function returns zero. */ +extern ptrdiff_t dwarf_getfuncs (Dwarf_Die *cudie, + int (*callback) (Dwarf_Die *, void *), + void *arg, ptrdiff_t offset); + + +/* Return file name containing definition of the given declaration. + Of the DECL has an (indirect, see dwarf_attr_integrate) decl_file + attribute. The returned file path is either absolute, or relative + to the compilation directory. Given the decl DIE, the compilation + directory can be retrieved through: + dwarf_formstring (dwarf_attr (dwarf_diecu (decl, &cudie, NULL, NULL), + DW_AT_comp_dir, &attr)); + Returns NULL if no decl_file could be found or an error occurred. */ +extern const char *dwarf_decl_file (Dwarf_Die *decl); + +/* Get line number of beginning of given declaration. */ +extern int dwarf_decl_line (Dwarf_Die *decl, int *linep) + __nonnull_attribute__ (2); + +/* Get column number of beginning of given declaration. */ +extern int dwarf_decl_column (Dwarf_Die *decl, int *colp) + __nonnull_attribute__ (2); + + +/* Return nonzero if given function is an abstract inline definition. */ +extern int dwarf_func_inline (Dwarf_Die *func); + +/* Find each concrete inlined instance of the abstract inline definition. */ +extern int dwarf_func_inline_instances (Dwarf_Die *func, + int (*callback) (Dwarf_Die *, void *), + void *arg); + + +/* Find the appropriate PC location or locations for function entry + breakpoints for the given DW_TAG_subprogram DIE. Returns -1 for errors. + On success, returns the number of breakpoint locations (never zero) + and sets *BKPTS to a malloc'd vector of addresses. */ +extern int dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts); + + +/* Iterate through the macro unit referenced by CUDIE and call + CALLBACK for each macro information entry. To start the iteration, + one would pass DWARF_GETMACROS_START for TOKEN. + + The iteration continues while CALLBACK returns DWARF_CB_OK. If the + callback returns DWARF_CB_ABORT, the iteration stops and a + continuation token is returned, which can be used to restart the + iteration at the point where it ended. Returns -1 for errors or 0 + if there are no more macro entries. + + Note that the Dwarf_Macro pointer passed to the callback is only + valid for the duration of the callback invocation. + + For backward compatibility, a token of 0 is accepted for starting + the iteration as well, but in that case this interface will refuse + to serve opcode 0xff from .debug_macro sections. Such opcode would + be considered invalid and would cause dwarf_getmacros to return + with error. */ +#define DWARF_GETMACROS_START PTRDIFF_MIN +extern ptrdiff_t dwarf_getmacros (Dwarf_Die *cudie, + int (*callback) (Dwarf_Macro *, void *), + void *arg, ptrdiff_t token) + __nonnull_attribute__ (2); + +/* This is similar in operation to dwarf_getmacros, but selects the + unit to iterate through by offset instead of by CU, and always + iterates .debug_macro. This can be used for handling + DW_MACRO_GNU_transparent_include's or similar opcodes. + + TOKEN value of DWARF_GETMACROS_START can be used to start the + iteration. + + It is not appropriate to obtain macro unit offset by hand from a CU + DIE and then request iteration through this interface. The reason + for this is that if a dwarf_macro_getsrcfiles is later called, + there would be no way to figure out what DW_AT_comp_dir was present + on the CU DIE, and file names referenced in either the macro unit + itself, or the .debug_line unit that it references, might be wrong. + Use dwarf_getmacros. */ +extern ptrdiff_t dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff, + int (*callback) (Dwarf_Macro *, void *), + void *arg, ptrdiff_t token) + __nonnull_attribute__ (3); + +/* Get the source files used by the macro entry. You shouldn't assume + that Dwarf_Files references will remain valid after MACRO becomes + invalid. (Which is to say it's only valid within the + dwarf_getmacros* callback.) Returns 0 for success or a negative + value in case of an error. */ +extern int dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro, + Dwarf_Files **files, size_t *nfiles) + __nonnull_attribute__ (2, 3, 4); + +/* Return macro opcode. That's a constant that can be either from + DW_MACINFO_* domain or DW_MACRO_GNU_* domain. The two domains have + compatible values, so it's OK to use either of them for + comparisons. The only differences is 0xff, which could be either + DW_MACINFO_vendor_ext or a vendor-defined DW_MACRO_* constant. One + would need to look if the CU DIE which the iteration was requested + for has attribute DW_AT_macro_info, or either of DW_AT_GNU_macros + or DW_AT_macros to differentiate the two interpretations. */ +extern int dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep) + __nonnull_attribute__ (2); + +/* Get number of parameters of MACRO and store it to *PARAMCNTP. */ +extern int dwarf_macro_getparamcnt (Dwarf_Macro *macro, size_t *paramcntp); + +/* Get IDX-th parameter of MACRO (numbered from zero), and stores it + to *ATTRIBUTE. Returns 0 on success or -1 for errors. + + After a successful call, you can query ATTRIBUTE by dwarf_whatform + to determine which of the dwarf_formX calls to make to get actual + value out of ATTRIBUTE. Note that calling dwarf_whatattr is not + meaningful for pseudo-attributes formed this way. */ +extern int dwarf_macro_param (Dwarf_Macro *macro, size_t idx, + Dwarf_Attribute *attribute); + +/* Return macro parameter with index 0. This will return -1 if the + parameter is not an integral value. Use dwarf_macro_param for more + general access. */ +extern int dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp) + __nonnull_attribute__ (2); + +/* Return macro parameter with index 1. This will return -1 if the + parameter is not an integral or string value. Use + dwarf_macro_param for more general access. */ +extern int dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp, + const char **strp); + +/* Compute what's known about a call frame when the PC is at ADDRESS. + Returns 0 for success or -1 for errors. + On success, *FRAME is a malloc'd pointer. */ +extern int dwarf_cfi_addrframe (Dwarf_CFI *cache, + Dwarf_Addr address, Dwarf_Frame **frame) + __nonnull_attribute__ (3); + +/* Return the DWARF register number used in FRAME to denote + the return address in FRAME's caller frame. The remaining + arguments can be non-null to fill in more information. + + Fill [*START, *END) with the PC range to which FRAME's information applies. + Fill in *SIGNALP to indicate whether this is a signal-handling frame. + If true, this is the implicit call frame that calls a signal handler. + This frame's "caller" is actually the interrupted state, not a call; + its return address is an exact PC, not a PC after a call instruction. */ +extern int dwarf_frame_info (Dwarf_Frame *frame, + Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp); + +/* Return a DWARF expression that yields the Canonical Frame Address at + this frame state. Returns -1 for errors, or zero for success, with + *NOPS set to the number of operations stored at *OPS. That pointer + can be used only as long as FRAME is alive and unchanged. *NOPS is + zero if the CFA cannot be determined here. Note that if nonempty, + *OPS is a DWARF expression, not a location description--append + DW_OP_stack_value to a get a location description for the CFA. */ +extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops, size_t *nops) + __nonnull_attribute__ (2); + +/* Deliver a DWARF location description that yields the location or + value of DWARF register number REGNO in the state described by FRAME. + + Returns -1 for errors or zero for success, setting *NOPS to the + number of operations in the array stored at *OPS. Note the last + operation is DW_OP_stack_value if there is no mutable location but + only a computable value. + + *NOPS zero with *OPS set to OPS_MEM means CFI says the caller's + REGNO is "undefined", i.e. it's call-clobbered and cannot be recovered. + + *NOPS zero with *OPS set to a null pointer means CFI says the + caller's REGNO is "same_value", i.e. this frame did not change it; + ask the caller frame where to find it. + + For common simple expressions *OPS is OPS_MEM (which is a caller + owned array for at least 3 Dwarf_Ops). For arbitrary DWARF + expressions in the CFI, *OPS is an internal pointer that can be + used as long as the Dwarf_CFI used to create FRAME remains + alive. */ +extern int dwarf_frame_register (Dwarf_Frame *frame, int regno, + Dwarf_Op ops_mem[3], + Dwarf_Op **ops, size_t *nops) + __nonnull_attribute__ (3, 4, 5); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int dwarf_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *dwarf_errmsg (int err); + + +/* Register new Out-Of-Memory handler. The old handler is returned. */ +extern Dwarf_OOM dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler); + + +/* Inline optimizations. */ +#ifdef __OPTIMIZE__ +/* Return attribute code of given attribute. */ +__libdw_extern_inline unsigned int +dwarf_whatattr (Dwarf_Attribute *attr) +{ + return attr == NULL ? 0 : attr->code; +} + +/* Return attribute code of given attribute. */ +__libdw_extern_inline unsigned int +dwarf_whatform (Dwarf_Attribute *attr) +{ + return attr == NULL ? 0 : attr->form; +} +#endif /* Optimize. */ + +#ifdef __cplusplus +} +#endif + +#endif /* libdw.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwelf.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwelf.h new file mode 100644 index 000000000..263ca60e3 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwelf.h @@ -0,0 +1,147 @@ +/* Interfaces for libdwelf. DWARF ELF Low-level Functions. + Copyright (C) 2014, 2015, 2016, 2018 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBDWELF_H +#define _LIBDWELF_H 1 + +#include "libdw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* DWARF ELF Low-level Functions (dwelf). + Functions starting with dwelf_elf will take a (libelf) Elf object as + first argument and might set elf_errno on error. Functions starting + with dwelf_dwarf will take a (libdw) Dwarf object as first argument + and might set dwarf_errno on error. */ + +/* Returns the name and the CRC32 of the separate debug file from the + .gnu_debuglink section if found in the ELF. Return NULL if the ELF + file didn't have a .gnu_debuglink section, had malformed data in the + section or some other error occurred. */ +extern const char *dwelf_elf_gnu_debuglink (Elf *elf, GElf_Word *crc); + +/* Returns the name and build ID from the .gnu_debugaltlink section if + found in the ELF. On success, pointers to the name and build ID + are written to *NAMEP and *BUILDID_P, and the positive length of + the build ID is returned. Returns 0 if the ELF lacks a + .gnu_debugaltlink section. Returns -1 in case of malformed data or + other errors. */ +extern ssize_t dwelf_dwarf_gnu_debugaltlink (Dwarf *dwarf, + const char **namep, + const void **build_idp); + +/* Returns the build ID as found in a NT_GNU_BUILD_ID note from either + a SHT_NOTE section or from a PT_NOTE segment if the ELF file + doesn't contain any section headers. On success a pointer to the + build ID is written to *BUILDID_P, and the positive length of the + build ID is returned. Returns 0 if the ELF lacks a NT_GNU_BUILD_ID + note. Returns -1 in case of malformed data or other errors. */ +extern ssize_t dwelf_elf_gnu_build_id (Elf *elf, const void **build_idp); + +/* Returns the size of the uncompressed data of a GNU compressed + section. The section name should start with .zdebug (but this + isn't checked by this function). If the section isn't compressed + (the section data doesn't start with ZLIB) -1 is returned. If an + error occurred -1 is returned and elf_errno is set. */ +extern ssize_t dwelf_scn_gnu_compressed_size (Elf_Scn *scn); + +/* ELF/DWARF string table handling. */ +typedef struct Dwelf_Strtab Dwelf_Strtab; +typedef struct Dwelf_Strent Dwelf_Strent; + +/* Create a new ELF/DWARF string table object in memory. ELF string + tables have a required zero length null string at offset zero. + DWARF string tables don't require such a null entry (unless they + are shared with an ELF string table). If NULLSTR is true then a + null entry is always created (even if the string table is empty + otherwise). */ +extern Dwelf_Strtab *dwelf_strtab_init (bool nullstr); + +/* Add string STR to string table ST. Returns NULL if no memory could + be allocated. The given STR is owned by the called and must be + valid till dwelf_strtab_free is called. dwelf_strtab_finalize + might copy the string into the final table and dwelf_strent_str + might return it, or a reference to an identical copy/substring + added to the string table. */ +extern Dwelf_Strent *dwelf_strtab_add (Dwelf_Strtab *st, const char *str) + __nonnull_attribute__ (1, 2); + +/* This is an optimized version of dwelf_strtab_add if the length of + the string is already known. LEN is the length of STR including + zero terminator. Calling dwelf_strtab_add (st, str) is similar to + calling dwelf_strtab_len (st, str, strlen (str) + 1). */ +extern Dwelf_Strent *dwelf_strtab_add_len (Dwelf_Strtab *st, + const char *str, size_t len) + __nonnull_attribute__ (1, 2); + +/* Finalize string table ST and store size and memory location + information in DATA d_size and d_buf. DATA d_type will be set to + ELF_T_BYTE, d_off will be zero, d_align will be 1 and d_version + will be set to EV_CURRENT. If no memory could be allocated NULL is + returned and DATA->d_buf will be set to NULL. Otherwise DATA will + be returned. */ +extern Elf_Data *dwelf_strtab_finalize (Dwelf_Strtab *st, + Elf_Data *data) + __nonnull_attribute__ (1, 2); + +/* Get offset in string table for string associated with entry. Only + valid after dwelf_strtab_finalize has been called. */ +extern size_t dwelf_strent_off (Dwelf_Strent *se) + __nonnull_attribute__ (1); + +/* Return the string associated with the entry. */ +extern const char *dwelf_strent_str (Dwelf_Strent *se) + __nonnull_attribute__ (1); + +/* Free resources allocated for the string table. This invalidates + any Dwelf_Strent references returned earlier. */ +extern void dwelf_strtab_free (Dwelf_Strtab *st) + __nonnull_attribute__ (1); + +/* Creates a read-only Elf handle from the given file handle. The + file may be compressed and/or contain a linux kernel image header, + in which case it is eagerly decompressed in full and the Elf handle + is created as if created with elf_memory (). On decompression or + file errors NULL is returned (and elf_errno will be set). If there + was no error, but the file is not an ELF file, then an ELF_K_NONE + Elf handle is returned (just like with elf_begin). The Elf handle + should be closed with elf_end (). The file handle will not be + closed. */ +extern Elf *dwelf_elf_begin (int fd); + +/* Returns a human readable string for the given ELF header e_machine + value, or NULL if the given number isn't currently known. */ +extern const char *dwelf_elf_e_machine_string (int machine); + +#ifdef __cplusplus +} +#endif + +#endif /* libdwelf.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwfl.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwfl.h new file mode 100644 index 000000000..49ad66648 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/elfutils/libdwfl.h @@ -0,0 +1,825 @@ +/* Interfaces for libdwfl. + Copyright (C) 2005-2010, 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBDWFL_H +#define _LIBDWFL_H 1 + +#include "libdw.h" +#include + +/* Handle for a session using the library. */ +typedef struct Dwfl Dwfl; + +/* Handle for a module. */ +typedef struct Dwfl_Module Dwfl_Module; + +/* Handle describing a line record. */ +typedef struct Dwfl_Line Dwfl_Line; + +/* This holds information common for all the frames of one backtrace for + a particular thread/task/TID. Several threads belong to one Dwfl. */ +typedef struct Dwfl_Thread Dwfl_Thread; + +/* This holds everything we know about the state of the frame at a particular + PC location described by an FDE belonging to Dwfl_Thread. */ +typedef struct Dwfl_Frame Dwfl_Frame; + +/* Handle for debuginfod-client connection. */ +#ifndef _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF +typedef struct debuginfod_client debuginfod_client; +#define _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF 1 +#endif + +/* Callbacks. */ +typedef struct +{ + int (*find_elf) (Dwfl_Module *mod, void **userdata, + const char *modname, Dwarf_Addr base, + char **file_name, Elf **elfp); + + int (*find_debuginfo) (Dwfl_Module *mod, void **userdata, + const char *modname, Dwarf_Addr base, + const char *file_name, + const char *debuglink_file, GElf_Word debuglink_crc, + char **debuginfo_file_name); + + /* Fill *ADDR with the loaded address of the section called SECNAME in + the given module. Use (Dwarf_Addr) -1 if this section is omitted from + accessible memory. This is called exactly once for each SHF_ALLOC + section that relocations affecting DWARF data refer to, so it can + easily be used to collect state about the sections referenced. */ + int (*section_address) (Dwfl_Module *mod, void **userdata, + const char *modname, Dwarf_Addr base, + const char *secname, + GElf_Word shndx, const GElf_Shdr *shdr, + Dwarf_Addr *addr); + + char **debuginfo_path; /* See dwfl_standard_find_debuginfo. */ +} Dwfl_Callbacks; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Start a new session with the library. */ +extern Dwfl *dwfl_begin (const Dwfl_Callbacks *callbacks) + __nonnull_attribute__ (1); + + +/* End a session. */ +extern void dwfl_end (Dwfl *); + +/* Return implementation's version string suitable for printing. */ +extern const char *dwfl_version (Dwfl *); + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int dwfl_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL if none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *dwfl_errmsg (int err); + + +/* Start reporting the current set of segments and modules to the library. + All existing segments are wiped. Existing modules are marked to be + deleted, and will not be found via dwfl_addrmodule et al if they are not + re-reported before dwfl_report_end is called. */ +extern void dwfl_report_begin (Dwfl *dwfl); + +/* Report that segment NDX begins at PHDR->p_vaddr + BIAS. + If NDX is < 0, the value succeeding the last call's NDX + is used instead (zero on the first call). IDENT is ignored. + + If nonzero, the smallest PHDR->p_align value seen sets the + effective page size for the address space DWFL describes. + This is the granularity at which reported module boundary + addresses will be considered to fall in or out of a segment. + + Returns -1 for errors, or NDX (or its assigned replacement) on success. + + Reporting segments at all is optional. Its only benefit to the caller is to + offer this quick lookup via dwfl_addrsegment, or use other segment-based + calls. */ +extern int dwfl_report_segment (Dwfl *dwfl, int ndx, + const GElf_Phdr *phdr, GElf_Addr bias, + const void *ident); + +/* Report that a module called NAME spans addresses [START, END). + Returns the module handle, either existing or newly allocated, + or returns a null pointer for an allocation error. */ +extern Dwfl_Module *dwfl_report_module (Dwfl *dwfl, const char *name, + Dwarf_Addr start, Dwarf_Addr end); + +/* Report a module to address BASE with start and end addresses computed + from the ELF program headers in the given file - see the table below. + FD may be -1 to open FILE_NAME. On success, FD is consumed by the + library, and the `find_elf' callback will not be used for this module. + ADD_P_VADDR BASE + ET_EXEC ignored ignored + ET_DYN false absolute address where to place the file + true start address relative to ELF's phdr p_vaddr + ET_REL ignored absolute address where to place the file + ET_CORE ignored ignored + ET_DYN ELF phdr p_vaddr address can be non-zero if the shared library + has been prelinked by tool prelink(8). */ +extern Dwfl_Module *dwfl_report_elf (Dwfl *dwfl, const char *name, + const char *file_name, int fd, + GElf_Addr base, bool add_p_vaddr); + +/* Similar, but report the module for offline use. All ET_EXEC files + being reported must be reported before any relocatable objects. + If this is used, dwfl_report_module and dwfl_report_elf may not be + used in the same reporting session. */ +extern Dwfl_Module *dwfl_report_offline (Dwfl *dwfl, const char *name, + const char *file_name, int fd); + +/* Similar, but report ELF from memory region. */ +extern Dwfl_Module *dwfl_report_offline_memory (Dwfl *dwfl, const char *name, + const char *file_name, + char *data, size_t size); + +/* Finish reporting the current set of modules to the library. + If REMOVED is not null, it's called for each module that + existed before but was not included in the current report. + Returns a nonzero return value from the callback. + The callback may call dwfl_report_module; doing so with the + details of the module being removed prevents its removal. + DWFL cannot be used until this function has returned zero. */ +extern int dwfl_report_end (Dwfl *dwfl, + int (*removed) (Dwfl_Module *, void *, + const char *, Dwarf_Addr, + void *arg), + void *arg); + +/* Start reporting additional modules to the library. No calls but + dwfl_report_* can be made on DWFL until dwfl_report_end is called. + This is like dwfl_report_begin, but all the old modules are kept on. + More dwfl_report_* calls can follow to add more modules. + When dwfl_report_end is called, no old modules will be removed. */ +extern void dwfl_report_begin_add (Dwfl *dwfl); + + +/* Return the name of the module, and for each non-null argument store + interesting details: *USERDATA is a location for storing your own + pointer, **USERDATA is initially null; *START and *END give the address + range covered by the module; *DWBIAS is the address bias for debugging + information, and *SYMBIAS for symbol table entries (either is -1 if not + yet accessed); *MAINFILE is the name of the ELF file, and *DEBUGFILE the + name of the debuginfo file (might be equal to *MAINFILE; either is null + if not yet accessed). */ +extern const char *dwfl_module_info (Dwfl_Module *mod, void ***userdata, + Dwarf_Addr *start, Dwarf_Addr *end, + Dwarf_Addr *dwbias, Dwarf_Addr *symbias, + const char **mainfile, + const char **debugfile); + +/* Iterate through the modules, starting the walk with OFFSET == 0. + Calls *CALLBACK for each module as long as it returns DWARF_CB_OK. + When *CALLBACK returns another value, the walk stops and the + return value can be passed as OFFSET to resume it. Returns 0 when + there are no more modules, or -1 for errors. */ +extern ptrdiff_t dwfl_getmodules (Dwfl *dwfl, + int (*callback) (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + void *arg), + void *arg, + ptrdiff_t offset); + +/* Find the module containing the given address. */ +extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address); + +/* Find the segment, if any, and module, if any, containing ADDRESS. + Returns a segment index returned by dwfl_report_segment, or -1 + if no segment matches the address. Regardless of the return value, + *MOD is always set to the module containing ADDRESS, or to null. */ +extern int dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod); + + + +/* Report the known build ID bits associated with a module. + If VADDR is nonzero, it gives the absolute address where those + bits are found within the module. This can be called at any + time, but is usually used immediately after dwfl_report_module. + Once the module's main ELF file is opened, the ID note found + there takes precedence and cannot be changed. */ +extern int dwfl_module_report_build_id (Dwfl_Module *mod, + const unsigned char *bits, size_t len, + GElf_Addr vaddr) + __nonnull_attribute__ (2); + +/* Extract the build ID bits associated with a module. + Returns -1 for errors, 0 if no ID is known, or the number of ID bytes. + When an ID is found, *BITS points to it; *VADDR is the absolute address + at which the ID bits are found within the module, or 0 if unknown. + + This returns 0 when the module's main ELF file has not yet been loaded + and its build ID bits were not reported. To ensure the ID is always + returned when determinable, call dwfl_module_getelf first. */ +extern int dwfl_module_build_id (Dwfl_Module *mod, + const unsigned char **bits, GElf_Addr *vaddr) + __nonnull_attribute__ (2, 3); + + +/*** Standard callbacks ***/ + +/* These standard find_elf and find_debuginfo callbacks are + controlled by a string specifying directories to look in. + If `debuginfo_path' is set in the Dwfl_Callbacks structure + and the char * it points to is not null, that supplies the + string. Otherwise a default path is used. + + If the first character of the string is + or - that enables or + disables CRC32 checksum validation when it's necessary. The + remainder of the string is composed of elements separated by + colons. Each element can start with + or - to override the + global checksum behavior. This flag is never relevant when + working with build IDs, but it's always parsed in the path + string. The remainder of the element indicates a directory. + + Searches by build ID consult only the elements naming absolute + directory paths. They look under those directories for a link + named ".build-id/xx/yy" or ".build-id/xx/yy.debug", where "xxyy" + is the lower-case hexadecimal representation of the ID bytes. + + In searches for debuginfo by name, if the remainder of the + element is empty, the directory containing the main file is + tried; if it's an absolute path name, the absolute directory path + (and any subdirectory of that path) containing the main file is + taken as a subdirectory of this path; a relative path name is taken + as a subdirectory of the directory containing the main file. + Hence for /usr/bin/ls, the default string ":.debug:/usr/lib/debug" + says to look in /usr/bin, then /usr/bin/.debug, then the path subdirs + under /usr/lib/debug, in the order /usr/lib/debug/usr/bin, then + /usr/lib/debug/bin, and finally /usr/lib/debug, for the file name in + the .gnu_debuglink section (or "ls.debug" if none was found). */ + +/* Standard find_elf callback function working solely on build ID. + This can be tried first by any find_elf callback, to use the + bits passed to dwfl_module_report_build_id, if any. */ +extern int dwfl_build_id_find_elf (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + char **, Elf **); + +/* Standard find_debuginfo callback function working solely on build ID. + This can be tried first by any find_debuginfo callback, + to use the build ID bits from the main file when present. */ +extern int dwfl_build_id_find_debuginfo (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + const char *, const char *, + GElf_Word, char **); + +/* Standard find_debuginfo callback function. + If a build ID is available, this tries first to use that. + If there is no build ID or no valid debuginfo found by ID, + it searches the debuginfo path by name, as described above. + Any file found in the path is validated by build ID if possible, + or else by CRC32 checksum if enabled, and skipped if it does not match. */ +extern int dwfl_standard_find_debuginfo (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + const char *, const char *, + GElf_Word, char **); + + +/* This callback must be used when using dwfl_offline_* to report modules, + if ET_REL is to be supported. */ +extern int dwfl_offline_section_address (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + const char *, GElf_Word, + const GElf_Shdr *, + Dwarf_Addr *addr); + + +/* Callbacks for working with kernel modules in the running Linux kernel. */ +extern int dwfl_linux_kernel_find_elf (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + char **, Elf **); +extern int dwfl_linux_kernel_module_section_address (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + const char *, GElf_Word, + const GElf_Shdr *, + Dwarf_Addr *addr); + +/* Call dwfl_report_elf for the running Linux kernel. + Returns zero on success, -1 if dwfl_report_module failed, + or an errno code if opening the kernel binary failed. */ +extern int dwfl_linux_kernel_report_kernel (Dwfl *dwfl); + +/* Call dwfl_report_module for each kernel module in the running Linux kernel. + Returns zero on success, -1 if dwfl_report_module failed, + or an errno code if reading the list of modules failed. */ +extern int dwfl_linux_kernel_report_modules (Dwfl *dwfl); + +/* Report a kernel and its modules found on disk, for offline use. + If RELEASE starts with '/', it names a directory to look in; + if not, it names a directory to find under /lib/modules/; + if null, /lib/modules/`uname -r` is used. + Returns zero on success, -1 if dwfl_report_module failed, + or an errno code if finding the files on disk failed. + + If PREDICATE is not null, it is called with each module to be reported; + its arguments are the module name, and the ELF file name or null if unknown, + and its return value should be zero to skip the module, one to report it, + or -1 to cause the call to fail and return errno. */ +extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release, + int (*predicate) (const char *, + const char *)); + +/* Examine an ET_CORE file and report modules based on its contents. + This can follow a dwfl_report_offline call to bootstrap the + DT_DEBUG method of following the dynamic linker link_map chain, in + case the core file does not contain enough of the executable's text + segment to locate its PT_DYNAMIC in the dump. In such case you need to + supply non-NULL EXECUTABLE, otherwise dynamic libraries will not be loaded + into the DWFL map. This might call dwfl_report_elf on file names found in + the dump if reading some link_map files is the only way to ascertain those + modules' addresses. Returns the number of modules reported, or -1 for + errors. */ +extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable); + +/* Call dwfl_report_module for each file mapped into the address space of PID. + Returns zero on success, -1 if dwfl_report_module failed, + or an errno code if opening the proc files failed. */ +extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid); + +/* Similar, but reads an input stream in the format of Linux /proc/PID/maps + files giving module layout, not the file for a live process. */ +extern int dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *); + +/* Trivial find_elf callback for use with dwfl_linux_proc_report. + This uses the module name as a file name directly and tries to open it + if it begin with a slash, or handles the magic string "[vdso]". */ +extern int dwfl_linux_proc_find_elf (Dwfl_Module *mod, void **userdata, + const char *module_name, Dwarf_Addr base, + char **file_name, Elf **); + +/* Standard argument parsing for using a standard callback set. */ +struct argp; +extern const struct argp *dwfl_standard_argp (void) __const_attribute__; + + +/*** Relocation of addresses from Dwfl ***/ + +/* Return the number of relocatable bases associated with the module, + which is zero for ET_EXEC and one for ET_DYN. Returns -1 for errors. */ +extern int dwfl_module_relocations (Dwfl_Module *mod); + +/* Return the relocation base index associated with the *ADDRESS location, + and adjust *ADDRESS to be an offset relative to that base. + Returns -1 for errors. */ +extern int dwfl_module_relocate_address (Dwfl_Module *mod, + Dwarf_Addr *address); + +/* Return the ELF section name for the given relocation base index; + if SHNDXP is not null, set *SHNDXP to the ELF section index. + For ET_DYN, returns "" and sets *SHNDXP to SHN_ABS; the relocation + base is the runtime start address reported for the module. + Returns null for errors. */ +extern const char *dwfl_module_relocation_info (Dwfl_Module *mod, + unsigned int idx, + GElf_Word *shndxp); + +/* Validate that ADDRESS and ADDRESS+OFFSET lie in a known module + and both within the same contiguous region for relocation purposes. + Returns zero for success and -1 for errors. */ +extern int dwfl_validate_address (Dwfl *dwfl, + Dwarf_Addr address, Dwarf_Sword offset); + + +/*** ELF access functions ***/ + +/* Fetch the module main ELF file (where the allocated sections + are found) for use with libelf. If successful, fills in *BIAS + with the difference between addresses within the loaded module + and those in symbol tables or Dwarf information referring to it. */ +extern Elf *dwfl_module_getelf (Dwfl_Module *, GElf_Addr *bias) + __nonnull_attribute__ (2); + +/* Return the number of symbols in the module's symbol table, + or -1 for errors. */ +extern int dwfl_module_getsymtab (Dwfl_Module *mod); + +/* Return the index of the first global symbol in the module's symbol + table, or -1 for errors. In each symbol table, all symbols with + STB_LOCAL binding precede the weak and global symbols. This + function returns the symbol table index one greater than the last + local symbol. */ +extern int dwfl_module_getsymtab_first_global (Dwfl_Module *mod); + +/* Fetch one entry from the module's symbol table. On errors, returns + NULL. If successful, fills in *SYM and returns the string for st_name. + This works like gelf_getsym except that st_value is always adjusted to + an absolute value based on the module's location, when the symbol is in + an SHF_ALLOC section. If SHNDXP is non-null, it's set with the section + index (whether from st_shndx or extended index table); in case of a + symbol in a non-allocated section, *SHNDXP is instead set to -1. + Note that since symbols can come from either the main, debug or auxiliary + ELF symbol file (either dynsym or symtab) the section index can only + be reliably used to compare against special section constants like + SHN_UNDEF or SHN_ABS. It is recommended to use dwfl_module_getsym_info + which doesn't have these deficiencies. */ +extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx, + GElf_Sym *sym, GElf_Word *shndxp) + __nonnull_attribute__ (3); + +/* Fetch one entry from the module's symbol table and the associated + address value. On errors, returns NULL. If successful, fills in + *SYM, *ADDR and returns the string for st_name. This works like + gelf_getsym. *ADDR is set to the st_value adjusted to an absolute + value based on the module's location, when the symbol is in an + SHF_ALLOC section. For non-ET_REL files, if the arch uses function + descriptors, and the st_value points to one, *ADDR will be resolved + to the actual function entry address. The SYM->ST_VALUE itself + isn't adjusted in any way. Fills in ELFP, if not NULL, with the + ELF file the symbol originally came from. Note that symbols can + come from either the main, debug or auxiliary ELF symbol file + (either dynsym or symtab). If SHNDXP is non-null, it's set with + the section index (whether from st_shndx or extended index table); + in case of a symbol in a non-allocated section, *SHNDXP is instead + set to -1. Fills in BIAS, if not NULL, with the difference between + addresses within the loaded module and those in symbol table of the + ELF file. Note that the address associated with the symbol might + be in a different section than the returned symbol. The section in + the main elf file in which returned ADDR falls can be found with + dwfl_module_address_section. */ +extern const char *dwfl_module_getsym_info (Dwfl_Module *mod, int ndx, + GElf_Sym *sym, GElf_Addr *addr, + GElf_Word *shndxp, + Elf **elfp, Dwarf_Addr *bias) + __nonnull_attribute__ (3, 4); + +/* Find the symbol that ADDRESS lies inside, and return its name. */ +extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address); + +/* Find the symbol associated with ADDRESS. Return its name or NULL + when nothing was found. If the architecture uses function + descriptors, and symbol st_value points to one, ADDRESS will be + matched against either the adjusted st_value or the associated + function entry value as described in dwfl_module_getsym_info. + OFFSET will be filled in with the difference from the start of the + symbol (or function entry), OFFSET cannot be NULL. SYM is filled + in with the symbol associated with the matched ADDRESS, SYM cannot + be NULL. The SYM->ST_VALUE itself isn't adjusted in any way. + Fills in ELFP, if not NULL, with the ELF file the symbol originally + came from. Note that symbols can come from either the main, debug + or auxiliary ELF symbol file (either dynsym or symtab). If SHNDXP + is non-null, it's set with the section index (whether from st_shndx + or extended index table). Fills in BIAS, if not NULL, with the + difference between addresses within the loaded module and those in + symbol table of the ELF file. Note that the address matched + against the symbol might be in a different section than the + returned symbol. The section in the main elf file in ADDRESS falls + can be found with dwfl_module_address_section. */ +extern const char *dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address, + GElf_Off *offset, GElf_Sym *sym, + GElf_Word *shndxp, Elf **elfp, + Dwarf_Addr *bias) + __nonnull_attribute__ (3, 4); + +/* Find the symbol that ADDRESS lies inside, and return detailed + information as for dwfl_module_getsym (above). Note that like + dwfl_module_getsym this function also adjusts SYM->ST_VALUE to an + absolute value based on the module's location. ADDRESS is only + matched against this adjusted SYM->ST_VALUE. This means that + depending on architecture this might only match symbols that + represent function descriptor addresses (and not function entry + addresses). For these reasons it is recommended to use + dwfl_module_addrinfo instead. */ +extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address, + GElf_Sym *sym, GElf_Word *shndxp) + __nonnull_attribute__ (3); + +/* Find the ELF section that *ADDRESS lies inside and return it. + On success, adjusts *ADDRESS to be relative to the section, + and sets *BIAS to the difference between addresses used in + the returned section's headers and run-time addresses. */ +extern Elf_Scn *dwfl_module_address_section (Dwfl_Module *mod, + Dwarf_Addr *address, + Dwarf_Addr *bias) + __nonnull_attribute__ (2, 3); + + +/*** Dwarf access functions ***/ + +/* Fetch the module's debug information for use with libdw. + If successful, fills in *BIAS with the difference between + addresses within the loaded module and those to use with libdw. */ +extern Dwarf *dwfl_module_getdwarf (Dwfl_Module *, Dwarf_Addr *bias) + __nonnull_attribute__ (2); + +/* Get the libdw handle for each module. */ +extern ptrdiff_t dwfl_getdwarf (Dwfl *, + int (*callback) (Dwfl_Module *, void **, + const char *, Dwarf_Addr, + Dwarf *, Dwarf_Addr, void *), + void *arg, ptrdiff_t offset); + +/* Look up the module containing ADDR and return its debugging information, + loading it if necessary. */ +extern Dwarf *dwfl_addrdwarf (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias) + __nonnull_attribute__ (3); + + +/* Find the CU containing ADDR and return its DIE. */ +extern Dwarf_Die *dwfl_addrdie (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias) + __nonnull_attribute__ (3); +extern Dwarf_Die *dwfl_module_addrdie (Dwfl_Module *mod, + Dwarf_Addr addr, Dwarf_Addr *bias) + __nonnull_attribute__ (3); + +/* Iterate through the CUs, start with null for LASTCU. */ +extern Dwarf_Die *dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias) + __nonnull_attribute__ (3); +extern Dwarf_Die *dwfl_module_nextcu (Dwfl_Module *mod, + Dwarf_Die *lastcu, Dwarf_Addr *bias) + __nonnull_attribute__ (3); + +/* Return the module containing the CU DIE. */ +extern Dwfl_Module *dwfl_cumodule (Dwarf_Die *cudie); + + +/* Cache the source line information for the CU and return the + number of Dwfl_Line entries it has. */ +extern int dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines); + +/* Access one line number entry within the CU. */ +extern Dwfl_Line *dwfl_onesrcline (Dwarf_Die *cudie, size_t idx); + +/* Get source for address. */ +extern Dwfl_Line *dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr); +extern Dwfl_Line *dwfl_getsrc (Dwfl *dwfl, Dwarf_Addr addr); + +/* Get address for source. */ +extern int dwfl_module_getsrc_file (Dwfl_Module *mod, + const char *fname, int lineno, int column, + Dwfl_Line ***srcsp, size_t *nsrcs); + +/* Return the module containing this line record. */ +extern Dwfl_Module *dwfl_linemodule (Dwfl_Line *line); + +/* Return the CU containing this line record. */ +extern Dwarf_Die *dwfl_linecu (Dwfl_Line *line); + +/* Return the source file name and fill in other information. + Arguments may be null for unneeded fields. */ +extern const char *dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, + int *linep, int *colp, + Dwarf_Word *mtime, Dwarf_Word *length); + + /* Return the equivalent Dwarf_Line and the bias to apply to its address. */ +extern Dwarf_Line *dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias); + +/* Return the compilation directory (AT_comp_dir) from this line's CU. */ +extern const char *dwfl_line_comp_dir (Dwfl_Line *line); + + +/*** Machine backend access functions ***/ + +/* Return location expression to find return value given a + DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing + function itself (whose DW_AT_type attribute describes its return type). + The given DIE must come from the given module. Returns -1 for errors. + Returns zero if the function has no return value (e.g. "void" in C). + Otherwise, *LOCOPS gets a location expression to find the return value, + and returns the number of operations in the expression. The pointer is + permanently allocated at least as long as the module is live. */ +extern int dwfl_module_return_value_location (Dwfl_Module *mod, + Dwarf_Die *functypedie, + const Dwarf_Op **locops); + +/* Enumerate the DWARF register numbers and their names. + For each register, CALLBACK gets its DWARF number, a string describing + the register set (such as "integer" or "FPU"), a prefix used in + assembler syntax (such as "%" or "$", may be ""), and the name for the + register (contains identifier characters only, possibly all digits). + The REGNAME string is valid only during the callback. */ +extern int dwfl_module_register_names (Dwfl_Module *mod, + int (*callback) (void *arg, + int regno, + const char *setname, + const char *prefix, + const char *regname, + int bits, int type), + void *arg); + + +/* Find the CFI for this module. Returns NULL if there is no CFI. + On success, fills in *BIAS with the difference between addresses + within the loaded module and those in the CFI referring to it. + The pointer returned can be used until the module is cleaned up. + Calling these more than once returns the same pointers. + + dwfl_module_dwarf_cfi gets the '.debug_frame' information found with the + rest of the DWARF information. dwfl_module_eh_cfi gets the '.eh_frame' + information found linked into the text. A module might have either or + both. */ +extern Dwarf_CFI *dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias); +extern Dwarf_CFI *dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias); + + +typedef struct +{ + /* Called to iterate through threads. Returns next TID (thread ID) on + success, a negative number on failure and zero if there are no more + threads. dwfl_errno () should be set if negative number has been + returned. *THREAD_ARGP is NULL on first call, and may be optionally + set by the implementation. The value set by the implementation will + be passed in on the next call to NEXT_THREAD. THREAD_ARGP is never + NULL. *THREAD_ARGP will be passed to set_initial_registers or + thread_detach callbacks together with Dwfl_Thread *thread. This + method must not be NULL. */ + pid_t (*next_thread) (Dwfl *dwfl, void *dwfl_arg, void **thread_argp) + __nonnull_attribute__ (1); + + /* Called to get a specific thread. Returns true if there is a + thread with the given thread id number, returns false if no such + thread exists and will set dwfl_errno in that case. THREAD_ARGP + is never NULL. *THREAD_ARGP will be passed to + set_initial_registers or thread_detach callbacks together with + Dwfl_Thread *thread. This method may be NULL and will then be + emulated using the next_thread callback. */ + bool (*get_thread) (Dwfl *dwfl, pid_t tid, void *dwfl_arg, + void **thread_argp) + __nonnull_attribute__ (1); + + /* Called during unwinding to access memory (stack) state. Returns true for + successfully read *RESULT or false and sets dwfl_errno () on failure. + This method may be NULL - in such case dwfl_thread_getframes will return + only the initial frame. */ + bool (*memory_read) (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, + void *dwfl_arg) + __nonnull_attribute__ (1, 3); + + /* Called on initial unwind to get the initial register state of the first + frame. Should call dwfl_thread_state_registers, possibly multiple times + for different ranges and possibly also dwfl_thread_state_register_pc, to + fill in initial (DWARF) register values. After this call, till at least + thread_detach is called, the thread is assumed to be frozen, so that it is + safe to unwind. Returns true on success or false and sets dwfl_errno () + on failure. In the case of a failure thread_detach will not be called. + This method must not be NULL. */ + bool (*set_initial_registers) (Dwfl_Thread *thread, void *thread_arg) + __nonnull_attribute__ (1); + + /* Called by dwfl_end. All thread_detach method calls have been already + done. This method may be NULL. */ + void (*detach) (Dwfl *dwfl, void *dwfl_arg) + __nonnull_attribute__ (1); + + /* Called when unwinding is done. No callback will be called after + this method has been called. Iff set_initial_registers was called for + a TID and it returned success thread_detach will be called before the + detach method above. This method may be NULL. */ + void (*thread_detach) (Dwfl_Thread *thread, void *thread_arg) + __nonnull_attribute__ (1); +} Dwfl_Thread_Callbacks; + +/* PID is the process id associated with the DWFL state. Architecture of DWFL + modules is specified by ELF, ELF must remain valid during DWFL lifetime. + Use NULL ELF to detect architecture from DWFL, the function will then detect + it from arbitrary Dwfl_Module of DWFL. DWFL_ARG is the callback backend + state. DWFL_ARG will be provided to the callbacks. *THREAD_CALLBACKS + function pointers must remain valid during lifetime of DWFL. Function + returns true on success, false otherwise. */ +bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid, + const Dwfl_Thread_Callbacks *thread_callbacks, + void *dwfl_arg) + __nonnull_attribute__ (1, 4); + +/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting + thread state from the ELF core file. Returns the pid number extracted + from the core file, or -1 for errors. */ +extern int dwfl_core_file_attach (Dwfl *dwfl, Elf *elf); + +/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting + thread state from the proc file system. Uses ptrace to attach and stop + the thread under inspection and detaches when thread_detach is called + and unwinding for the thread is done, unless ASSUME_PTRACE_STOPPED is + true. If ASSUME_PTRACE_STOPPED is true the caller should make sure that + the thread is ptrace attached and stopped before unwinding by calling + either dwfl_thread_getframes or dwfl_getthread_frames. Returns zero on + success, -1 if dwfl_attach_state failed, or an errno code if opening the + proc files failed. */ +extern int dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, + bool assume_ptrace_stopped); + +/* Return PID for the process associated with DWFL. Function returns -1 if + dwfl_attach_state was not called for DWFL. */ +pid_t dwfl_pid (Dwfl *dwfl) + __nonnull_attribute__ (1); + +/* Return DWFL from which THREAD was created using dwfl_getthreads. */ +Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread) + __nonnull_attribute__ (1); + +/* Return positive TID (thread ID) for THREAD. This function never fails. */ +pid_t dwfl_thread_tid (Dwfl_Thread *thread) + __nonnull_attribute__ (1); + +/* Return thread for frame STATE. This function never fails. */ +Dwfl_Thread *dwfl_frame_thread (Dwfl_Frame *state) + __nonnull_attribute__ (1); + +/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation. + For every known continuous block of registers . */ + +#ifndef _ELFUTILS_VERSION_H +#define _ELFUTILS_VERSION_H 1 + +#define _ELFUTILS_VERSION 189 + +#define _ELFUTILS_PREREQ(major, minor) \ + (_ELFUTILS_VERSION >= ((major) * 1000 + (minor))) + +#endif /* elfutils/version.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/gelf.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/gelf.h new file mode 100644 index 000000000..7a3c87aae --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/gelf.h @@ -0,0 +1,342 @@ +/* This file defines generic ELF types, structures, and macros. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2015 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _GELF_H +#define _GELF_H 1 + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Class independent type definitions. Correctly speaking this is not + true. We assume that 64-bit binaries are the largest class and + therefore all other classes can be represented without loss. */ + +/* Type for a 16-bit quantity. */ +typedef Elf64_Half GElf_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef Elf64_Word GElf_Word; +typedef Elf64_Sword GElf_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef Elf64_Xword GElf_Xword; +typedef Elf64_Sxword GElf_Sxword; + +/* Type of addresses. */ +typedef Elf64_Addr GElf_Addr; + +/* Type of file offsets. */ +typedef Elf64_Off GElf_Off; + + +/* The ELF file header. This appears at the start of every ELF file. */ +typedef Elf64_Ehdr GElf_Ehdr; + +/* Section header. */ +typedef Elf64_Shdr GElf_Shdr; + +/* Section index. */ +/* XXX This should probably be a larger type in preparation of times when + regular section indices can be larger. */ +typedef Elf64_Section GElf_Section; + +/* Symbol table entry. */ +typedef Elf64_Sym GElf_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ +typedef Elf64_Syminfo GElf_Syminfo; + +/* Relocation table entry without addend (in section of type SHT_REL). */ +typedef Elf64_Rel GElf_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ +typedef Elf64_Rela GElf_Rela; + +/* Program segment header. */ +typedef Elf64_Phdr GElf_Phdr; + +/* Header of a compressed section. */ +typedef Elf64_Chdr GElf_Chdr; + +/* Dynamic section entry. */ +typedef Elf64_Dyn GElf_Dyn; + + +/* Version definition sections. */ +typedef Elf64_Verdef GElf_Verdef; + +/* Auxiliary version information. */ +typedef Elf64_Verdaux GElf_Verdaux; + +/* Version dependency section. */ +typedef Elf64_Verneed GElf_Verneed; + +/* Auxiliary needed version information. */ +typedef Elf64_Vernaux GElf_Vernaux; + + +/* Type for version symbol information. */ +typedef Elf64_Versym GElf_Versym; + + +/* Auxiliary vector. */ +typedef Elf64_auxv_t GElf_auxv_t; + + +/* Note section contents. */ +typedef Elf64_Nhdr GElf_Nhdr; + + +/* Move structure. */ +typedef Elf64_Move GElf_Move; + + +/* Library list structure. */ +typedef Elf64_Lib GElf_Lib; + + +/* How to extract and insert information held in the st_info field. */ + +#define GELF_ST_BIND(val) ELF64_ST_BIND (val) +#define GELF_ST_TYPE(val) ELF64_ST_TYPE (val) +#define GELF_ST_INFO(bind, type) ELF64_ST_INFO (bind, type) + +/* How to extract information held in the st_other field. */ + +#define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val) + + +/* How to extract and insert information held in the r_info field. */ + +#define GELF_R_SYM(info) ELF64_R_SYM (info) +#define GELF_R_TYPE(info) ELF64_R_TYPE (info) +#define GELF_R_INFO(sym, type) ELF64_R_INFO (sym, type) + + +/* How to extract and insert information held in the m_info field. */ +#define GELF_M_SYM(info) ELF64_M_SYM (info) +#define GELF_M_SIZE(info) ELF64_M_SIZE (info) +#define GELF_M_INFO(sym, size) ELF64_M_INFO (sym, size) + + +/* Get class of the file associated with ELF. */ +extern int gelf_getclass (Elf *__elf); + + +/* Return size of array of COUNT elements of the type denoted by TYPE + in the external representation. The binary class is taken from ELF. + The result is based on version VERSION of the ELF standard. */ +extern size_t gelf_fsize (Elf *__elf, Elf_Type __type, size_t __count, + unsigned int __version); + +/* Retrieve object file header. */ +extern GElf_Ehdr *gelf_getehdr (Elf *__elf, GElf_Ehdr *__dest); + +/* Update the ELF header. */ +extern int gelf_update_ehdr (Elf *__elf, GElf_Ehdr *__src); + +/* Create new ELF header if none exists. Creates an Elf32_Ehdr if CLASS + is ELFCLASS32 or an Elf64_Ehdr if CLASS is ELFCLASS64. Returns NULL + on error. */ +extern void *gelf_newehdr (Elf *__elf, int __class); + +/* Get section at OFFSET. */ +extern Elf_Scn *gelf_offscn (Elf *__elf, GElf_Off __offset); + +/* Retrieve section header. */ +extern GElf_Shdr *gelf_getshdr (Elf_Scn *__scn, GElf_Shdr *__dst); + +/* Update section header. */ +extern int gelf_update_shdr (Elf_Scn *__scn, GElf_Shdr *__src); + +/* Retrieve program header table entry. */ +extern GElf_Phdr *gelf_getphdr (Elf *__elf, int __ndx, GElf_Phdr *__dst); + +/* Update the program header. */ +extern int gelf_update_phdr (Elf *__elf, int __ndx, GElf_Phdr *__src); + +/* Create new program header with PHNUM entries. Creates either an + Elf32_Phdr or an Elf64_Phdr depending on whether the given ELF is + ELFCLASS32 or ELFCLASS64. Returns NULL on error. */ +extern void *gelf_newphdr (Elf *__elf, size_t __phnum); + +/* Get compression header of section if any. Returns NULL and sets + elf_errno if the section isn't compressed or an error occurred. */ +extern GElf_Chdr *gelf_getchdr (Elf_Scn *__scn, GElf_Chdr *__dst); + +/* Convert data structure from the representation in the file represented + by ELF to their memory representation. */ +extern Elf_Data *gelf_xlatetom (Elf *__elf, Elf_Data *__dest, + const Elf_Data *__src, unsigned int __encode); + +/* Convert data structure from to the representation in memory + represented by ELF file representation. */ +extern Elf_Data *gelf_xlatetof (Elf *__elf, Elf_Data *__dest, + const Elf_Data *__src, unsigned int __encode); + + +/* Retrieve REL relocation info at the given index. */ +extern GElf_Rel *gelf_getrel (Elf_Data *__data, int __ndx, GElf_Rel *__dst); + +/* Retrieve RELA relocation info at the given index. */ +extern GElf_Rela *gelf_getrela (Elf_Data *__data, int __ndx, GElf_Rela *__dst); + +/* Update REL relocation information at given index. */ +extern int gelf_update_rel (Elf_Data *__dst, int __ndx, GElf_Rel *__src); + +/* Update RELA relocation information at given index. */ +extern int gelf_update_rela (Elf_Data *__dst, int __ndx, GElf_Rela *__src); + + +/* Retrieve symbol information from the symbol table at the given index. */ +extern GElf_Sym *gelf_getsym (Elf_Data *__data, int __ndx, GElf_Sym *__dst); + +/* Update symbol information in the symbol table at the given index. */ +extern int gelf_update_sym (Elf_Data *__data, int __ndx, GElf_Sym *__src); + + +/* Retrieve symbol information and separate section index from the + symbol table at the given index. */ +extern GElf_Sym *gelf_getsymshndx (Elf_Data *__symdata, Elf_Data *__shndxdata, + int __ndx, GElf_Sym *__sym, + Elf32_Word *__xshndx); + +/* Update symbol information and separate section index in the symbol + table at the given index. */ +extern int gelf_update_symshndx (Elf_Data *__symdata, Elf_Data *__shndxdata, + int __ndx, GElf_Sym *__sym, + Elf32_Word __xshndx); + + +/* Retrieve additional symbol information from the symbol table at the + given index. */ +extern GElf_Syminfo *gelf_getsyminfo (Elf_Data *__data, int __ndx, + GElf_Syminfo *__dst); + +/* Update additional symbol information in the symbol table at the + given index. */ +extern int gelf_update_syminfo (Elf_Data *__data, int __ndx, + GElf_Syminfo *__src); + + +/* Get information from dynamic table at the given index. */ +extern GElf_Dyn *gelf_getdyn (Elf_Data *__data, int __ndx, GElf_Dyn *__dst); + +/* Update information in dynamic table at the given index. */ +extern int gelf_update_dyn (Elf_Data *__dst, int __ndx, GElf_Dyn *__src); + + +/* Get move structure at the given index. */ +extern GElf_Move *gelf_getmove (Elf_Data *__data, int __ndx, GElf_Move *__dst); + +/* Update move structure at the given index. */ +extern int gelf_update_move (Elf_Data *__data, int __ndx, + GElf_Move *__src); + + +/* Get library from table at the given index. */ +extern GElf_Lib *gelf_getlib (Elf_Data *__data, int __ndx, GElf_Lib *__dst); + +/* Update library in table at the given index. */ +extern int gelf_update_lib (Elf_Data *__data, int __ndx, GElf_Lib *__src); + + + +/* Retrieve symbol version information at given index. */ +extern GElf_Versym *gelf_getversym (Elf_Data *__data, int __ndx, + GElf_Versym *__dst); + +/* Update symbol version information. */ +extern int gelf_update_versym (Elf_Data *__data, int __ndx, + GElf_Versym *__src); + + +/* Retrieve required symbol version information at given offset. */ +extern GElf_Verneed *gelf_getverneed (Elf_Data *__data, int __offset, + GElf_Verneed *__dst); + +/* Update required symbol version information. */ +extern int gelf_update_verneed (Elf_Data *__data, int __offset, + GElf_Verneed *__src); + +/* Retrieve additional required symbol version information at given offset. */ +extern GElf_Vernaux *gelf_getvernaux (Elf_Data *__data, int __offset, + GElf_Vernaux *__dst); + +/* Update additional required symbol version information. */ +extern int gelf_update_vernaux (Elf_Data *__data, int __offset, + GElf_Vernaux *__src); + + +/* Retrieve symbol version definition information at given offset. */ +extern GElf_Verdef *gelf_getverdef (Elf_Data *__data, int __offset, + GElf_Verdef *__dst); + +/* Update symbol version definition information. */ +extern int gelf_update_verdef (Elf_Data *__data, int __offset, + GElf_Verdef *__src); + +/* Retrieve additional symbol version definition information at given + offset. */ +extern GElf_Verdaux *gelf_getverdaux (Elf_Data *__data, int __offset, + GElf_Verdaux *__dst); + +/* Update additional symbol version definition information. */ +extern int gelf_update_verdaux (Elf_Data *__data, int __offset, + GElf_Verdaux *__src); + + +/* Get auxv entry at the given index. */ +extern GElf_auxv_t *gelf_getauxv (Elf_Data *__data, int __ndx, + GElf_auxv_t *__dst); + +/* Update auxv entry at the given index. */ +extern int gelf_update_auxv (Elf_Data *__data, int __ndx, GElf_auxv_t *__src); + + +/* Get note header at the given offset into the data, and the offsets of + the note's name and descriptor data. Returns the offset of the next + note header, or 0 for an invalid offset or corrupt note header. */ +extern size_t gelf_getnote (Elf_Data *__data, size_t __offset, + GElf_Nhdr *__result, + size_t *__name_offset, size_t *__desc_offset); + + +/* Compute simple checksum from permanent parts of the ELF file. */ +extern long int gelf_checksum (Elf *__elf); + +#ifdef __cplusplus +} +#endif + +#endif /* gelf.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/libelf.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/libelf.h new file mode 100644 index 000000000..2374a48a0 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/libelf.h @@ -0,0 +1,527 @@ +/* Interface for libelf. + Copyright (C) 1998-2010, 2015 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBELF_H +#define _LIBELF_H 1 + +#include +#include + +/* Get the ELF types. */ +#include + +#ifndef SHF_COMPRESSED + /* Older glibc elf.h might not yet define the ELF compression types. */ + #define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ + + /* Section compression header. Used when SHF_COMPRESSED is set. */ + + typedef struct + { + Elf32_Word ch_type; /* Compression format. */ + Elf32_Word ch_size; /* Uncompressed data size. */ + Elf32_Word ch_addralign; /* Uncompressed data alignment. */ + } Elf32_Chdr; + + typedef struct + { + Elf64_Word ch_type; /* Compression format. */ + Elf64_Word ch_reserved; + Elf64_Xword ch_size; /* Uncompressed data size. */ + Elf64_Xword ch_addralign; /* Uncompressed data alignment. */ + } Elf64_Chdr; + + /* Legal values for ch_type (compression algorithm). */ + #define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */ + #define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */ + #define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */ + #define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */ + #define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */ +#endif + +#ifndef ELFCOMPRESS_ZSTD + /* So ZSTD compression can be used even with an old system elf.h. */ + #define ELFCOMPRESS_ZSTD 2 /* Zstandard algorithm. */ +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__))) +# define __deprecated_attribute__ __attribute__ ((__deprecated__)) +# define __pure_attribute__ __attribute__ ((__pure__)) +# define __const_attribute__ __attribute__ ((__const__)) +#else +# define __nonnull_attribute__(...) +# define __deprecated_attribute__ +# define __pure_attribute__ +# define __const_attribute__ +#endif + +#if __GNUC__ < 4 +#define __noreturn_attribute__ +#else +#define __noreturn_attribute__ __attribute__ ((noreturn)) +#endif + +#ifdef __GNUC_STDC_INLINE__ +# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__)) +#else +# define __libdw_extern_inline extern __inline +#endif + +/* Known translation types. */ +typedef enum +{ + ELF_T_BYTE, /* unsigned char */ + ELF_T_ADDR, /* Elf32_Addr, Elf64_Addr, ... */ + ELF_T_DYN, /* Dynamic section record. */ + ELF_T_EHDR, /* ELF header. */ + ELF_T_HALF, /* Elf32_Half, Elf64_Half, ... */ + ELF_T_OFF, /* Elf32_Off, Elf64_Off, ... */ + ELF_T_PHDR, /* Program header. */ + ELF_T_RELA, /* Relocation entry with addend. */ + ELF_T_REL, /* Relocation entry. */ + ELF_T_SHDR, /* Section header. */ + ELF_T_SWORD, /* Elf32_Sword, Elf64_Sword, ... */ + ELF_T_SYM, /* Symbol record. */ + ELF_T_WORD, /* Elf32_Word, Elf64_Word, ... */ + ELF_T_XWORD, /* Elf32_Xword, Elf64_Xword, ... */ + ELF_T_SXWORD, /* Elf32_Sxword, Elf64_Sxword, ... */ + ELF_T_VDEF, /* Elf32_Verdef, Elf64_Verdef, ... */ + ELF_T_VDAUX, /* Elf32_Verdaux, Elf64_Verdaux, ... */ + ELF_T_VNEED, /* Elf32_Verneed, Elf64_Verneed, ... */ + ELF_T_VNAUX, /* Elf32_Vernaux, Elf64_Vernaux, ... */ + ELF_T_NHDR, /* Elf32_Nhdr, Elf64_Nhdr, ... */ + ELF_T_SYMINFO, /* Elf32_Syminfo, Elf64_Syminfo, ... */ + ELF_T_MOVE, /* Elf32_Move, Elf64_Move, ... */ + ELF_T_LIB, /* Elf32_Lib, Elf64_Lib, ... */ + ELF_T_GNUHASH, /* GNU-style hash section. */ + ELF_T_AUXV, /* Elf32_auxv_t, Elf64_auxv_t, ... */ + ELF_T_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */ + ELF_T_NHDR8, /* Special GNU Properties note. Same as Nhdr, + except padding. */ + /* Keep this the last entry. */ + ELF_T_NUM +} Elf_Type; + +/* Descriptor for data to be converted to or from memory format. */ +typedef struct +{ + void *d_buf; /* Pointer to the actual data. */ + Elf_Type d_type; /* Type of this piece of data. */ + unsigned int d_version; /* ELF version. */ + size_t d_size; /* Size in bytes. */ + int64_t d_off; /* Offset into section. */ + size_t d_align; /* Alignment in section. */ +} Elf_Data; + + +/* Commands for `...'. */ +typedef enum +{ + ELF_C_NULL, /* Nothing, terminate, or compute only. */ + ELF_C_READ, /* Read .. */ + ELF_C_RDWR, /* Read and write .. */ + ELF_C_WRITE, /* Write .. */ + ELF_C_CLR, /* Clear flag. */ + ELF_C_SET, /* Set flag. */ + ELF_C_FDDONE, /* Signal that file descriptor will not be + used anymore. */ + ELF_C_FDREAD, /* Read rest of data so that file descriptor + is not used anymore. */ + /* The following are extensions. */ + ELF_C_READ_MMAP, /* Read, but mmap the file if possible. */ + ELF_C_RDWR_MMAP, /* Read and write, with mmap. */ + ELF_C_WRITE_MMAP, /* Write, with mmap. */ + ELF_C_READ_MMAP_PRIVATE, /* Read, but memory is writable, results are + not written to the file. */ + ELF_C_EMPTY, /* Copy basic file data but not the content. */ + /* Keep this the last entry. */ + ELF_C_NUM +} Elf_Cmd; + + +/* Flags for the ELF structures. */ +enum +{ + ELF_F_DIRTY = 0x1, +#define ELF_F_DIRTY ELF_F_DIRTY + ELF_F_LAYOUT = 0x4, +#define ELF_F_LAYOUT ELF_F_LAYOUT + ELF_F_PERMISSIVE = 0x8 +#define ELF_F_PERMISSIVE ELF_F_PERMISSIVE +}; + +/* Flags for elf_compress[_gnu]. */ +enum +{ + ELF_CHF_FORCE = 0x1 +#define ELF_CHF_FORCE ELF_CHF_FORCE +}; + +/* Identification values for recognized object files. */ +typedef enum +{ + ELF_K_NONE, /* Unknown. */ + ELF_K_AR, /* Archive. */ + ELF_K_COFF, /* Stupid old COFF. */ + ELF_K_ELF, /* ELF file. */ + /* Keep this the last entry. */ + ELF_K_NUM +} Elf_Kind; + + +/* Archive member header. */ +typedef struct +{ + char *ar_name; /* Name of archive member. */ + time_t ar_date; /* File date. */ + uid_t ar_uid; /* User ID. */ + gid_t ar_gid; /* Group ID. */ + mode_t ar_mode; /* File mode. */ + int64_t ar_size; /* File size. */ + char *ar_rawname; /* Original name of archive member. */ +} Elf_Arhdr; + + +/* Archive symbol table entry. */ +typedef struct +{ + char *as_name; /* Symbol name. */ + size_t as_off; /* Offset for this file in the archive. */ + unsigned long int as_hash; /* Hash value of the name. */ +} Elf_Arsym; + + +/* Descriptor for the ELF file. */ +typedef struct Elf Elf; + +/* Descriptor for ELF file section. */ +typedef struct Elf_Scn Elf_Scn; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return descriptor for ELF file to work according to CMD. */ +extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref); + +/* Create a clone of an existing ELF descriptor. */ + extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd); + +/* Create descriptor for memory region. */ +extern Elf *elf_memory (char *__image, size_t __size); + +/* Advance archive descriptor to next element. */ +extern Elf_Cmd elf_next (Elf *__elf); + +/* Free resources allocated for ELF. */ +extern int elf_end (Elf *__elf); + +/* Update ELF descriptor and write file to disk. */ +extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd); + +/* Determine what kind of file is associated with ELF. */ +extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__; + +/* Get the base offset for an object file. */ +extern int64_t elf_getbase (Elf *__elf); + + +/* Retrieve file identification data. */ +extern char *elf_getident (Elf *__elf, size_t *__nbytes); + +/* Retrieve class-dependent object file header. */ +extern Elf32_Ehdr *elf32_getehdr (Elf *__elf); +/* Similar but this time the binary calls is ELFCLASS64. */ +extern Elf64_Ehdr *elf64_getehdr (Elf *__elf); + +/* Create ELF header if none exists. */ +extern Elf32_Ehdr *elf32_newehdr (Elf *__elf); +/* Similar but this time the binary calls is ELFCLASS64. */ +extern Elf64_Ehdr *elf64_newehdr (Elf *__elf); + +/* Get the number of program headers in the ELF file. If the file uses + more headers than can be represented in the e_phnum field of the ELF + header the information from the sh_info field in the zeroth section + header is used. */ +extern int elf_getphdrnum (Elf *__elf, size_t *__dst); + +/* Retrieve class-dependent program header table. */ +extern Elf32_Phdr *elf32_getphdr (Elf *__elf); +/* Similar but this time the binary calls is ELFCLASS64. */ +extern Elf64_Phdr *elf64_getphdr (Elf *__elf); + +/* Create ELF program header. */ +extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt); +/* Similar but this time the binary calls is ELFCLASS64. */ +extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt); + + +/* Get section at INDEX. */ +extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index); + +/* Get section at OFFSET. */ +extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset); +/* Similar bug this time the binary calls is ELFCLASS64. */ +extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset); + +/* Get index of section. */ +extern size_t elf_ndxscn (Elf_Scn *__scn); + +/* Get section with next section index. */ +extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn); + +/* Create a new section and append it at the end of the table. */ +extern Elf_Scn *elf_newscn (Elf *__elf); + +/* Get the section index of the extended section index table for the + given symbol table. */ +extern int elf_scnshndx (Elf_Scn *__scn); + +/* Get the number of sections in the ELF file. If the file uses more + sections than can be represented in the e_shnum field of the ELF + header the information from the sh_size field in the zeroth section + header is used. */ +extern int elf_getshdrnum (Elf *__elf, size_t *__dst); +/* Sun messed up the implementation of 'elf_getshnum' in their implementation. + It was agreed to make the same functionality available under a different + name and obsolete the old name. */ +extern int elf_getshnum (Elf *__elf, size_t *__dst) + __deprecated_attribute__; + + +/* Get the section index of the section header string table in the ELF + file. If the index cannot be represented in the e_shstrndx field of + the ELF header the information from the sh_link field in the zeroth + section header is used. */ +extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst); +/* Sun messed up the implementation of 'elf_getshstrndx' in their + implementation. It was agreed to make the same functionality available + under a different name and obsolete the old name. */ +extern int elf_getshstrndx (Elf *__elf, size_t *__dst) + __deprecated_attribute__; + + +/* Retrieve section header of ELFCLASS32 binary. */ +extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn); +/* Similar for ELFCLASS64. */ +extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn); + +/* Returns compression header for a section if section data is + compressed. Returns NULL and sets elf_errno if the section isn't + compressed or an error occurred. */ +extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn); +extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn); + +/* Compress or decompress the data of a section and adjust the section + header. + + elf_compress works by setting or clearing the SHF_COMPRESS flag + from the section Shdr and will encode or decode a Elf32_Chdr or + Elf64_Chdr at the start of the section data. elf_compress_gnu will + encode or decode any section, but is traditionally only used for + sections that have a name starting with ".debug" when + uncompressed or ".zdebug" when compressed and stores just the + uncompressed size. The GNU compression method is deprecated and + should only be used for legacy support. + + elf_compress takes a compression type that should be either zero to + decompress or an ELFCOMPRESS algorithm to use for compression. + Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported. + elf_compress_gnu will compress in the traditional GNU compression + format when compress is one and decompress the section data when + compress is zero. + + The FLAGS argument can be zero or ELF_CHF_FORCE. If FLAGS contains + ELF_CHF_FORCE then it will always compress the section, even if + that would not reduce the size of the data section (including the + header). Otherwise elf_compress and elf_compress_gnu will compress + the section only if the total data size is reduced. + + On successful compression or decompression the function returns + one. If (not forced) compression is requested and the data section + would not actually reduce in size, the section is not actually + compressed and zero is returned. Otherwise -1 is returned and + elf_errno is set. + + It is an error to request compression for a section that already + has SHF_COMPRESSED set, or (for elf_compress) to request + decompression for an section that doesn't have SHF_COMPRESSED set. + If a section has SHF_COMPRESSED set then calling elf_compress_gnu + will result in an error. The section has to be decompressed first + using elf_compress. Calling elf_compress on a section compressed + with elf_compress_gnu is fine, but probably useless. + + It is always an error to call these functions on SHT_NOBITS + sections or if the section has the SHF_ALLOC flag set. + elf_compress_gnu will not check whether the section name starts + with ".debug" or .zdebug". It is the responsibility of the caller + to make sure the deprecated GNU compression method is only called + on correctly named sections (and to change the name of the section + when using elf_compress_gnu). + + All previous returned Shdrs and Elf_Data buffers are invalidated by + this call and should no longer be accessed. + + Note that although this changes the header and data returned it + doesn't mark the section as dirty. To keep the changes when + calling elf_update the section has to be flagged ELF_F_DIRTY. */ +extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags); +extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags); + +/* Set or clear flags for ELF file. */ +extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd, + unsigned int __flags); +/* Similarly for the ELF header. */ +extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd, + unsigned int __flags); +/* Similarly for the ELF program header. */ +extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd, + unsigned int __flags); +/* Similarly for the given ELF section. */ +extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd, + unsigned int __flags); +/* Similarly for the given ELF data. */ +extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd, + unsigned int __flags); +/* Similarly for the given ELF section header. */ +extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd, + unsigned int __flags); + + +/* Get data from section while translating from file representation to + memory representation. The Elf_Data d_type is set based on the + section type if known. Otherwise d_type is set to ELF_T_BYTE. If + the section contains compressed data then d_type is always set to + ELF_T_CHDR. */ +extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data); + +/* Get uninterpreted section content. */ +extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data); + +/* Create new data descriptor for section SCN. */ +extern Elf_Data *elf_newdata (Elf_Scn *__scn); + +/* Get data translated from a chunk of the file contents as section data + would be for TYPE. The resulting Elf_Data pointer is valid until + elf_end (ELF) is called. */ +extern Elf_Data *elf_getdata_rawchunk (Elf *__elf, + int64_t __offset, size_t __size, + Elf_Type __type); + + +/* Return pointer to string at OFFSET in section INDEX. */ +extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset); + + +/* Return header of archive. */ +extern Elf_Arhdr *elf_getarhdr (Elf *__elf); + +/* Return offset in archive for current file ELF. */ +extern int64_t elf_getaroff (Elf *__elf); + +/* Select archive element at OFFSET. */ +extern size_t elf_rand (Elf *__elf, size_t __offset); + +/* Get symbol table of archive. */ +extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms); + + +/* Control ELF descriptor. */ +extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd); + +/* Retrieve uninterpreted file contents. */ +extern char *elf_rawfile (Elf *__elf, size_t *__nbytes); + + +/* Return size of array of COUNT elements of the type denoted by TYPE + in the external representation. The binary class is taken from ELF. + The result is based on version VERSION of the ELF standard. */ +extern size_t elf32_fsize (Elf_Type __type, size_t __count, + unsigned int __version) + __const_attribute__; +/* Similar but this time the binary calls is ELFCLASS64. */ +extern size_t elf64_fsize (Elf_Type __type, size_t __count, + unsigned int __version) + __const_attribute__; + + +/* Convert data structure from the representation in the file represented + by ELF to their memory representation. */ +extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src, + unsigned int __encode); +/* Same for 64 bit class. */ +extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src, + unsigned int __encode); + +/* Convert data structure from to the representation in memory + represented by ELF file representation. */ +extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src, + unsigned int __encode); +/* Same for 64 bit class. */ +extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src, + unsigned int __encode); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int elf_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *elf_errmsg (int __error); + + +/* Coordinate ELF library and application versions. */ +extern unsigned int elf_version (unsigned int __version); + +/* Set fill bytes used to fill holes in data structures. */ +extern void elf_fill (int __fill); + +/* Compute hash value. */ +extern unsigned long int elf_hash (const char *__string) + __pure_attribute__; + +/* Compute hash value using the GNU-specific hash function. */ +extern unsigned long int elf_gnu_hash (const char *__string) + __pure_attribute__; + + +/* Compute simple checksum from permanent parts of the ELF file. */ +extern long int elf32_checksum (Elf *__elf); +/* Similar but this time the binary calls is ELFCLASS64. */ +extern long int elf64_checksum (Elf *__elf); + +#ifdef __cplusplus +} +#endif + +#endif /* libelf.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/nlist.h b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/nlist.h new file mode 100644 index 000000000..599091828 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/include/nlist.h @@ -0,0 +1,56 @@ +/* Interface for nlist. + Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _NLIST_H +#define _NLIST_H 1 + + +/* Symbol list type. */ +struct nlist +{ + char *n_name; /* Symbol name. */ + long int n_value; /* Value of symbol. */ + short int n_scnum; /* Section number found in. */ + unsigned short int n_type; /* Type of symbol. */ + char n_sclass; /* Storage class. */ + char n_numaux; /* Number of auxiliary entries. */ +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Get specified entries from file. */ +extern int nlist (__const char *__filename, struct nlist *__nl); + +#ifdef __cplusplus +} +#endif + +#endif /* nlist.h */ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libasm.so.1 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libasm.so.1 new file mode 120000 index 000000000..2c5675c41 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libasm.so.1 @@ -0,0 +1 @@ +libasm-0.189.so \ No newline at end of file diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libdw.so.1 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libdw.so.1 new file mode 120000 index 000000000..8c87c91b4 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libdw.so.1 @@ -0,0 +1 @@ +libdw-0.189.so \ No newline at end of file diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.a b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.a new file mode 100644 index 000000000..715f6dcf0 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.a differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.so.1 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.so.1 new file mode 120000 index 000000000..097f0eaf0 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/libelf.so.1 @@ -0,0 +1 @@ +libelf-0.189.so \ No newline at end of file diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libdw.pc b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libdw.pc new file mode 100644 index 000000000..6edc1a577 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libdw.pc @@ -0,0 +1,22 @@ +prefix=/home/jerry/Downloads/toolchain/elfutils-0.189/_install +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libdw +Description: elfutils library for DWARF data and ELF file or process inspection +Version: 0.189 +URL: http://elfutils.org/ + +Libs: -L${libdir} -ldw +Cflags: -I${includedir} + +# We need the exact matching elfutils libelf version since internal data +# structures are used. +Requires: libelf = 0.189 + +# We support various compressed ELF images, but don't export any of the +# data structures or functions. zlib (gz) is always required, bzip2 (bz2) +# lzma (xz) and zstd () are optional. But bzip2 doesn't have a pkg-config file. +Requires.private: zlib +Libs.private: diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libelf.pc b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libelf.pc new file mode 100644 index 000000000..b279cdfec --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/lib/pkgconfig/libelf.pc @@ -0,0 +1,14 @@ +prefix=/home/jerry/Downloads/toolchain/elfutils-0.189/_install +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libelf +Description: elfutils libelf library to read and write ELF files +Version: 0.189 +URL: http://elfutils.org/ + +Libs: -L${libdir} -lelf +Cflags: -I${includedir} + +Requires.private: zlib diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/de/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/de/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..13525305c Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/de/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@boldquot/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@boldquot/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..b86ac0656 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@boldquot/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@quot/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@quot/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..1dfa4b71f Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/en@quot/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/es/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/es/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..427040349 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/es/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/ja/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/ja/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..252fd01d7 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/ja/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/pl/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/pl/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..9054fdb47 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/pl/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/uk/LC_MESSAGES/elfutils.mo b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/uk/LC_MESSAGES/elfutils.mo new file mode 100644 index 000000000..ed6b5a50b Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/locale/uk/LC_MESSAGES/elfutils.mo differ diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-elfclassify.1 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-elfclassify.1 new file mode 100644 index 000000000..cbfdae483 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-elfclassify.1 @@ -0,0 +1,197 @@ +.\" Copyright 2019 Red Hat Inc. +.\" Tue 2019-Aug 20 Ben Woodard +.\" Florian Wiemer +.\" Mark Wielaard +.\" Contact elfutils-devel@sourceware.org to correct errors or typos. +.TH EU-ELFCLASSIFY 1 "2019-Aug-20" "elfutils" +.SH "NAME" +eu-elfclassify \- Determine the type of an ELF file. +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +eu-elfclassify [\fB\-\-core\fR] + [\fB\-\-debug-only\fR] + [\fB\-\-elf\fR] + [\fB\-\-elf\-archive\fR] + [\fB\-\-elf\-file\fR] + [\fB\-\-executable\fR] + [\fB\-\-library\fR] + [\fB\-\-linux\-kernel\-module\fR] + [\fB\-\-loadable\fR] + [\fB\-\-program\fR] + [\fB\-\-shared\fR] + [\fB\-\-unstripped\fR] + [\fB\-f\fR|\fB \-\-file\fR] + [\fB\-\-no\-stdin\fR] + [\fB\-\-stdin\fR] + [\fB\-\-stdin0\fR] + [\fB\-z\fR|\fB \-\-compressed\fR] + [\fB\-\-matching\fR] + [\fB\-\-no\-print\fR] + [\fB\-\-not\-matching\fR] + [\fB\-\-print\fR] + [\fB\-\-print0\fR] + [\fB\-q\fR|\fB \-\-quiet\fR] + [\fB\-v\fR|\fB \-\-verbose\fR] + [\fB\-?\fR|\fB \-\-help\fR] + [\fB\-\-usage\fR] + [\fB\-V\fR|\fB \-\-version\fR] + \fIelffile\fR... +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBeu-elfclassify\fR identifies the primary purpose of a particular kind of + \s-1ELF\s0 file or files +.SH "OPTIONS" +.IX Header "OPTIONS" +The long and short forms of options, shown here as alternatives, are +equivalent. All of the classification options must apply at the same time to a +particular file. Classification options can be negated using a +\fB\-\-not\-\fR prefix. +.SS "Classification Options" +.IX Subsection "Classification Options" +.IP "\fB\-\-core\fR" 4 +.IX Item "--core" +.PD +File is an ELF core dump file. +.IP "\FB\-\-debug\-only\fR" 4 +.IX Item "--debug-only" +.PD +File is a debug only ELF file (separate .debug, .dwo or dwz multi-file). +.IP "\fB\-\-elf\fR" 4 +.IX Item "--elf" +.PD +File looks like an ELF object or archive/static library (default). +.IP "\fB\-\-elf\-archive\fR" 4 +.IX Item "--elf-archive" +.PD +File is an ELF archive or static library. +.IP "\fB\-\-elf\-file\fR" 4 +.IX Item "--elf-file" +.PD +File is an regular ELF object (not an archive/static library). +.IP "\fB\-\-executable\fR" 4 +.IX Item "--executable" +.PD +File is (primarily) an ELF program executable (not primarily a DS.O) +.IP "\fB\-\-library\fR" 4 +.IX Item "--library" +.PD +File is an ELF shared object (DSO) (might also be an executable). +.IP "\fB\-\-linux\-kernel\-module\fR" 4 +.IX Item "--linux-kernel-module" +.PD +File is a linux kernel module. +.IP "\fB\-\-loadable\fR" 4 +.IX Item "--loadable" +.PD +File is a loadable ELF object (program or shared object). +.IP "\fB\--program\fR" 4 +.IX Item "--program" +.PD +File is an ELF program executable (might also be a DSO). +.IP "\fB\-\-shared\fR" 4 +.IX Item "--shared" +.PD +File is (primarily) an ELF shared object (DSO) (not primarily an executable). +.IP "\fB\-\-unstripped\fR" 4 +.IX Item "--unstripped" +.PD +File is an ELF file with symbol table or .debug_* sections and can be stripped +further. +.SS "Input flags" +.IX Subsection "Input flags" +.IP "\fB\-f\fR" 4 +.IX Item "-f" +.PD 0 +.IP "\fB\-\-file\fR" 4 +.IX Item "--file" +.PD +Only classify regular (not symlink nor special device) files. +.IP "\fB\-\-no\-stdin\fR" 4 +.IX Item "--no-stdin" +.PD +Do not read files from standard input (default). +.IP "\fB\-\-stdin\fR" 4 +.IX Item "--stdin" +.PD +Also read file names to process from standard input, separated by newlines. +.IP "\fB\-\-stdin0\fR" 4 +.IX Item "--stdin0" +.PD +Also read file names to process from standard input, separated by ASCII NUL +bytes. +.IP "\fB\-z\fR" 4 +.IX Item "-z" +.PD 0 +.IP "\fB\-\-compressed\fR" 4 +.IX Item "--compressed" +.PD +Try to open compressed files or embedded (kernel) ELF images. +.SS "Output flags" +.IX Subsection "Output flags" +.IP "\fB\-\-matching\fR" 4 +.IX Item "--matching" +.PD +If printing file names, print matching files (default). +.IP "\fB\-\-no\-print\fR" 4 +.IX Item "--no-print" +.PD +Do not output file names. +.IP "\fB\-\-not\-matching\fR" 4 +.IX Item "--not-matching" +.PD +If printing file names, print files that do not match. +.IP "\fB\-\-print\fR" 4 +.IX Item "--print" +.PD +Output names of files, separated by newline. +.IP "\fB\-\-print0\fR" 4 +.IX Item "--print0" +.PD +Output names of files, separated by ASCII NUL. +.SS " Additional flags" +.IX Subsection " Additional flags" +.IP "\fB\-q\fR" 4 +.IX Item "-q," +.PD +.IP "\fB\-\-quiet\fR" 4 +.IX Item "--quiet" +.PD +Suppress some error output (counterpart to --verbose). +.IP "\fB\-v\fR" 4 +.IX Item "-v" +.PD +.IP "\fB\-\-verbose\fR" 4 +.IX Item "--verbose" +.PD +Output additional information (can be specified multiple times). +.IP "\fB\-?\fR" 4 +.IX Item "-?" +.PD +.IP "\fB\-\-help\fR" 4 +.IX Item "--help" +.PD +Give this help list. +.IP "\fB\-\-usage\fR" 4 +.IX Item "--usage" +.PD +Give a short usage message. +.IP "\fB\-V\fR" 4 +.IX Item "-V" +.PD +.IP "\fB\-\-version\fR" 4 +.IX Item "--version" +.PD +Print program version. + +.SH "AUTHOR" +.IX Header "AUTHOR" +Written by Florian Wiemer. +.SH "REPORTING BUGS" +.IX Header "REPORTING BUGS" +Please reports bugs at https://sourceware.org/bugzilla/ +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +Copyright © 2019 Red Hat Inc. License GPLv3+: GNU GPL version 3 or +later . This is free software: you +are free to change and redistribute it. There is NO WARRANTY, to the +extent permitted by law. diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-readelf.1 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-readelf.1 new file mode 100644 index 000000000..1d182071d --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man1/eu-readelf.1 @@ -0,0 +1,514 @@ +.\" Modified from readelf.1 man page +.\" Tue 2019-Aug 20 by Ben Woodard +.\" Contact elfutils-devel@sourceware.org to correct errors or typos. +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1q +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "EU-READELF 1" +.TH EU-READELF 1 "2019-Aug-20" "elfutils" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +eu-readelf \- Displays information about ELF files. +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +eu-readelf [\fB\-a\fR|\fB\-\-all\fR] + [\fB\-h\fR|\fB\-\-file\-header\fR] + [\fB\-l\fR|\fB\-\-program\-headers\fR|\fB\-\-segments\fR] + [\fB\-S\fR|\fB\-\-section\-headers\fR|\fB\-\-sections\fR] + [\fB\-g\fR|\fB\-\-section\-groups\fR] + [\fB\-e\fR|\fB\-\-exception\fR] + [\fB\-\-syms\fR|\fB\-s\fR|\fB\-\-symbols\fR [section name] ] + [\fB\-\-dyn-syms\fR] + [\fB\-n\fR|\fB\-\-notes\fR [section name] ] + [\fB\-r\fR|\fB\-\-relocs\fR] + [\fB\-d\fR|\fB\-\-dynamic\fR] + [\fB\-V\fR|\fB\-\-version\-info\fR] + [\fB\-A\fR|\fB\-\-arch\-specific\fR] + [\fB\-x\fR |\fB\-\-hex\-dump=\fR] + [\fB\-p\fR |\fB\-\-string\-dump=\fR] + [\fB\-z\fR|\fB\-\-decompress\fR] + [\fB\-c\fR|\fB\-\-archive\-index\fR] + [\fB\-\-dwarf\-skeleton\fR ] + [\fB\-\-elf\-section\fR [section] ] + [\fB\-w\fR| + \fB\-\-debug\-dump\fR[=line,=decodedline,=info,=info+,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=ranges,=gdb_index,=addr]] + [\fB\-I\fR|\fB\-\-histogram\fR] + [\fB\-v\fR|\fB\-\-version\fR] + [\fB\-W\fR|\fB\-\-wide\fR] + [\fB\-H\fR|\fB\-\-help\fR] + \fIelffile\fR... +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBeu-readelf\fR displays information about one or more \s-1ELF\s0 format object +files. The options control what particular information to display. +.PP +\&\fIelffile\fR... are the object files to be examined. 32\-bit and +64\-bit \s-1ELF\s0 files are supported, as are archives containing \s-1ELF\s0 files. +.PP +This program performs a similar function to \fBobjdump\fR but it +goes into more detail and it exists independently of the \s-1BFD\s0 +library, so if there is a bug in \s-1BFD\s0 then readelf will not be +affected. +.SH "OPTIONS" +.IX Header "OPTIONS" +The long and short forms of options, shown here as alternatives, are +equivalent. At least one option in addition to \fB\-v\fR or \fB\-H\fR must be +given. +.SS "ELF Input Selection" +.IX Subsection "ELF Input Selection" +.IP "\fB\-\-dwarf\-skeleton \fR" 4 +.IX Item "--dwarf-skeleton " +.PD +Used with -w to find the skeleton Compile Units in FILE associated +with the Split Compile units in a .dwo input file. +.IP "\fB\-\-elf\-section [section]\fR" 4 +.IX Item "--elf-section [section]" +.PD +Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data +.SS "ELF Output Selection" +.IX Subsection "ELF Output Selection" +.IP "\fB\-a\fR" 4 +.IX Item "-a" +.PD 0 +.IP "\fB\-\-all\fR" 4 +.IX Item "--all" +.PD +Equivalent to specifying \fB\-\-file\-header\fR, +\&\fB\-\-program\-headers\fR, \fB\-\-sections\fR, \fB\-\-symbols\fR, +\&\fB\-\-relocs\fR, \fB\-\-dynamic\fR, \fB\-\-notes\fR, +\&\fB\-\-version\-info\fR, \fB\-\-arch\-specific\fR, +\&\fB\-\-section\-groups\fR and \fB\-\-histogram\fR. +.Sp +.IP "\fB\-h\fR" 4 +.IX Item "-h" +.PD 0 +.IP "\fB\-\-file\-header\fR" 4 +.IX Item "--file-header" +.PD +Displays the information contained in the \s-1ELF\s0 header at the start of the +file. +.IP "\fB\-l\fR" 4 +.IX Item "-l" +.PD 0 +.IP "\fB\-\-program\-headers\fR" 4 +.IX Item "--program-headers" +.IP "\fB\-\-segments\fR" 4 +.IX Item "--segments" +.PD +Displays the information contained in the file's segment headers, if it +has any. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +.PD 0 +.IP "\fB\-\-sections\fR" 4 +.IX Item "--sections" +.IP "\fB\-\-section\-headers\fR" 4 +.IX Item "--section-headers" +.PD +Displays the information contained in the file's section headers, if it +has any. +.IP "\fB\-g\fR" 4 +.IX Item "-g" +.PD 0 +.IP "\fB\-\-section\-groups\fR" 4 +.IX Item "--section-groups" +.PD +Displays the information contained in the file's section groups, if it +has any. +.IP "\fB\-I\fR" 4 +.IX Item "-I" +.PD 0 +.IP "\fB\-\-histogram\fR" 4 +.IX Item "--histogram" +.PD +Display a histogram of bucket list lengths when displaying the contents +of the symbol tables. +.IP "\fB\-s\fR" 4 +.IX Item "-s" +.PD 0 +.IP "\fB\--syms\fR" 4 +.IX Item "--syms" +.PD 0 +.IP "\fB\-\-symbols\fR [section name]" 4 +.IX Item "--symbols" +.PD +Displays the entries in symbol table section of the file, if it has one. +If a symbol has version information associated with it then this is +displayed as well. The version string is displayed as a suffix to the +symbol name, preceded by an @ character. For example +\&\fBfoo@VER_1\fR. If the version is the default version to be used +when resolving unversioned references to the symbol then it is +displayed as a suffix preceded by two @ characters. For example +\&\fBfoo@@VER_2\fR. +.IP "\fB\-\-dyn-syms\fR" 4 +.IX Item "--dyn-syms" +.PD +Display (only) the dynamic symbol table. +.IP "\fB\-e\fR" 4 +.IX Item "-e" +.PD 0 +.IP "\fB\-\-exception\fR" 4 +.IX Item "--exception" +.PD +Display sections for exception handling. +.IP "\fB\-n\fR" 4 +.IX Item "-n [section name]" +.PD 0 +.IP "\fB\-\-notes [section name]\fR" 4 +.IX Item "--notes" +.PD +Displays the contents of the \s-1NOTE\s0 segments and/or sections, if any. +.IP "\fB\-r\fR" 4 +.IX Item "-r" +.PD 0 +.IP "\fB\-\-relocs\fR" 4 +.IX Item "--relocs" +.PD +Displays the contents of the file's relocation section, if it has one. +.IP "\fB\-d\fR" 4 +.IX Item "-d" +.PD 0 +.IP "\fB\-\-dynamic\fR" 4 +.IX Item "--dynamic" +.PD +Displays the contents of the file's dynamic section, if it has one. +.IP "\fB\-V\fR" 4 +.IX Item "-V" +.PD 0 +.IP "\fB\-\-version\-info\fR" 4 +.IX Item "--version-info" +.PD +Displays the contents of the version sections in the file, it they +exist. +.IP "\fB\-A\fR" 4 +.IX Item "-A" +.PD 0 +.IP "\fB\-\-arch\-specific\fR" 4 +.IX Item "--arch-specific" +.PD +Displays architecture-specific information in the file, if there +is any. +.SS "Additional output selection" +.IX Subsection "Additional output selection" +.IP "\fB\-x \fR" 4 +.IX Item "-x " +.PD 0 +.IP "\fB\-\-hex\-dump=\fR" 4 +.IX Item "--hex-dump=" +.PD +Displays the contents of the indicated section name as a hexadecimal bytes. +.IP "\fB\-w\fR" 4 +.IX Item "-w" +.PD 0 +.IP "\fB\-\-debug\-dump[=decodedline,=info,=info+,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=ranges,=gdb_index,=addr]\fR" 4 +.IX Item "--debug-dump[=line,=decodedline,=info,=info+,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=ranges,=gdb_index,=addr]" +.PD +Displays the contents of the \s-1DWARF\s0 debug sections in the file, if any +are present. Compressed debug sections are automatically decompressed +(temporarily) before they are displayed. If one or more of the +optional letters or words follows the switch then only those type(s) +of data will be dumped. The letters and words refer to the following +information: +.RS 4 +.PD 0 +.ie n .IP """=abbrev""" 4 +.el .IP "\f(CW=abbrev\fR" 4 +.IX Item "=abbrev" +.PD +Displays the contents of the \fB.debug_abbrev\fR section. +.PD 0 +.ie n .IP """=addr""" 4 +.el .IP "\f(CW=addr\fR" 4 +.IX Item "=addr" +.PD +Displays the contents of the \fB.debug_addr\fR section. +.PD 0 +.ie n .IP """=frames""" 4 +.el .IP "\f(CW=frames\fR" 4 +.IX Item "=frames" +.PD +Display the raw contents of a \fB.debug_frame\fR section. +.PD 0 +.ie n .IP """=gdb_index""" 4 +.el .IP "\f(CW=gdb_index\fR" 4 +.IX Item "=gdb_index" +.PD +Displays the contents of the \fB.gdb_index\fR and/or +\&\fB.debug_names\fR sections. +.PD 0 +.ie n .IP """=info""" 4 +.el .IP "\f(CW=info\fR" 4 +.IX Item "=info" +.PD +Displays the contents of the \fB.debug_info\fR section. +.PD 0 +.ie n .IP """=info+""" 4 +.el .IP "\f(CW=info+\fR" 4 +.IX Item "=info+" +.PD +Displays the contents of the \fB.debug_info\fR section, plus any skeleton +unit will be immediately followed by the corresponding split compile unit +(from the .dwo file). To show the difference between "regular" CUs and +split CUs print offsets and references between { and } instead of [ and ]. +.PD 0 +.ie n .IP """=decodedline""" 4 +.el .IP "\f(CW=decodedline\fR" 4 +.IX Item "=decodedline" +.PD +Displays the interpreted contents of the \fB.debug_line\fR section. +.PD 0 +.ie n .IP """=macro""" 4 +.el .IP "\f(CW=macro\fR" 4 +.IX Item "=macro" +.PD +Displays the contents of the \fB.debug_macro\fR and/or +\&\fB.debug_macinfo\fR sections. +.PD 0 +.ie n .IP """=loc""" 4 +.el .IP "\f(CW=loc\fR" 4 +.IX Item "=loc" +.PD +Displays the contents of the \fB.debug_loc\fR and/or +\&\fB.debug_loclists\fR sections. +.PD 0 +.ie n .IP """=pubnames""" 4 +.el .IP "\f(CW=pubnames\fR" 4 +.IX Item "=pubnames" +.PD +Displays the contents of the \fB.debug_pubnames\fR and/or +\&\fB.debug_gnu_pubnames\fR sections. +.PD 0 +.ie n .IP """=aranges""" 4 +.el .IP "\f(CW=aranges\fR" 4 +.IX Item "=aranges" +.PD +Displays the contents of the \fB.debug_aranges\fR section. +.PD 0 +.ie n .IP """=ranges""" 4 +.el .IP "\f(CW=ranges\fR" 4 +.IX Item "=ranges" +.PD +Displays the contents of the \fB.debug_ranges\fR and/or +\&\fB.debug_rnglists\fR sections. +.PD 0 +.ie n .IP """=str""" 4 +.el .IP "\f(CW=str\fR" 4 +.IX Item "=str" +.PD +Displays the contents of the \fB.debug_str\fR, \fB.debug_line_str\fR +and/or \fB.debug_str_offsets\fR sections. +.PD 0 +.RS 4 +.Sp +Note: displaying the contents of \fB.debug_static_funcs\fR, +\&\fB.debug_static_vars\fR and \fBdebug_weaknames\fR sections is not +currently supported. +.RE +.IP "\fB\-p \fR" 4 +.IX Item "-p " +.PD 0 +.IP "\fB\-\-string\-dump=\fR" 4 +.IX Item "--string-dump=" +.PD +Displays the contents of the indicated section as printable strings. +A number identifies a particular section by index in the section table; +any other string identifies all sections with that name in the object file. +.IP "\fB\-c\fR" 4 +.IX Item "-c" +.PD 0 +.IP "\fB\-\-archive\-index\fR" 4 +.IX Item "--archive-index" +.PD +Displays the file symbol index information contained in the header part +of binary archives. Performs the same function as the \fBt\fR +command to \fBar\fR, but without using the \s-1BFD\s0 library. +.SS "Output control" +.IX Subsection "Output control" +.IP "\fB\-z\fR" 4 +.IX Item "-z" +.PD 0 +.IP "\fB\-\-decompress\fR" 4 +.IX Item "--decompress" +.PD +Requests that the section(s) being dumped by \fBx\fR, \fBR\fR or +\&\fBp\fR options are decompressed before being displayed. If the +section(s) are not compressed then they are displayed as is. +.IP "\fB\-v\fR" 4 +.IX Item "-v" +.PD 0 +.IP "\fB\-\-version\fR" 4 +.IX Item "--version" +.PD +Display the version number of eu-readelf. +.IP "\fB\-W\fR" 4 +.IX Item "-W" +.PD 0 +.IP "\fB\-\-wide\fR" 4 +.IX Item "--wide" +.PD +Ignored for compatibility (lines always wide). +.IP "\fB\-H\fR" 4 +.IX Item "-H" +.PD 0 +.IP "\fB\-\-help\fR" 4 +.IX Item "--help" +.PD +Display the command line options understood by \fBeu-readelf\fR. +.IP "\fB@\fR\fIfile\fR" 4 +.IX Item "@file" +Read command-line options from \fIfile\fR. The options read are +inserted in place of the original @\fIfile\fR option. If \fIfile\fR +does not exist, or cannot be read, then the option will be treated +literally, and not removed. +.Sp +Options in \fIfile\fR are separated by whitespace. A whitespace +character may be included in an option by surrounding the entire +option in either single or double quotes. Any character (including a +backslash) may be included by prefixing the character to be included +with a backslash. The \fIfile\fR may itself contain additional +@\fIfile\fR options; any such options will be processed recursively. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fIobjdump\fR\|(1), \fIreadelf\fR\|(1) and the Info entries for +\fIbinutils\fR. +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +Copyright (c) 1991\-2018 Free Software Foundation, Inc. + +Copyright (c) 2019 Red Hat Inc. +.PP +Permission is granted to copy, distribute and/or modify this document +under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, with no Front-Cover Texts, and with no +Back-Cover Texts. A copy of the license is included in the +section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R". diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_begin.3 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_begin.3 new file mode 100644 index 000000000..6a1d0c271 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_begin.3 @@ -0,0 +1,37 @@ +.\" Modified Thu Sep 5 2017 by Ben Woodard +.\" +.TH ELF_BEGIN 3 2017-09-05 "Libelf" "Libelf Programmer's Manual" +.SH NAME +elf_begin \- Return descriptor for ELF file. +.nf +.SH SYNOPSIS +.B #include +.sp +.BI "Elf *elf_begin (int " filedes ", Elf_Cmd " cmd ", Elf *" ref ");" +.BI "Elf *elf_clone (int " filedes ", Elf_Cmd " cmd ");" +.BI "int elf_end (Elf *" elf ");" +.fi +.SH DESCRIPTION +The +.BR elf_begin () +.SH RETURN VALUE +.SH ERRORS +elf_begin ELF_E_NO_VERSION ELF_E_INVALID_FILE ELF_E_INVALID_CMD ELF_E_NOMEM +elf_clone ELF_E_NOMEM +elf_end +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lbw29 lb lb +l l l. +Interface Attribute Value +T{ +.BR elf_begin (), +.BR elf_clone (), +.BR elf_end () +T} Thread safety MT-Safe +.TE + +.SH SEE ALSO diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_clone.3 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_clone.3 new file mode 100644 index 000000000..38ec9217f --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_clone.3 @@ -0,0 +1,14 @@ +.\" Modified Thu Sep 5 2017 by Ben Woodard +.\" +.TH ELF_CLONE 3 2017-09-05 "Libelf" "Libelf Programmer's Manual" +.SH NAME +elf_clone \- Create a clone of an existing ELF descriptor. +.nf +.SH SYNOPSIS +.B #include +.sp +.BI "Elf *elf_clone (int " filedes ", Elf_Cmd " cmd ");" +.fi +.SH DESCRIPTION +The +.BR elf_clone () diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_getdata.3 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_getdata.3 new file mode 100644 index 000000000..44d9304e0 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_getdata.3 @@ -0,0 +1,28 @@ +.\" Modified Thu Aug 17 2017 by Ben Woodard +.\" +.TH ELF_GETDATA 3 2017-08-17 "Libelf" "Libelf Programmer's Manual" +.SH NAME +elf_getdata \- Get washed data of section +.nf +.SH SYNOPSIS +.B #include +.sp +.BI "Elf_Data * elf_getdata (Elf_Scn *" scn ", Elf_Data *" data ");" +.fi +.SH DESCRIPTION +The +.BR elf_getdata () +function allows the user to retrieve the data buffers of the section +.I scn + . There can be more than one buffer if the user explicitly added them. +When a file is read the libelf library creates exactly one data buffer. + +The first buffer in the list can be obtained by passing a null pointer in the +parameter data. To get the next data buffer the previously returned value must +be passed in the data parameter. If there are no more buffer left in the list a +null pointer is returned. + +If the data parameter is not a null pointer it must be a descriptor for a +buffer associated with the section scn . If this is not the case a null pointer +is returned. To facilitate error handling elf_getdata also returns a null +pointer if the scn parameter is a null pointer. diff --git a/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_update.3 b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_update.3 new file mode 100644 index 000000000..d0a7ab10d --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/elfutils-0.189/share/man/man3/elf_update.3 @@ -0,0 +1,14 @@ +.\" Modified Thu Sep 5 2017 by Ben Woodard +.\" +.TH ELF_UPDATE 3 2017-09-05 "Libelf" "Libelf Programmer's Manual" +.SH NAME +elf_update \- update an ELF descriptor +.nf +.SH SYNOPSIS +.B #include +.sp +.BI "off_t elf_update (Elf *" elf ", Elf_Cmd " cmd ");" +.fi +.SH DESCRIPTION +The +.BR elf_update () diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zconf.h b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zconf.h new file mode 100644 index 000000000..ede3c82e3 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zconf.h @@ -0,0 +1,543 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zlib.h b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zlib.h new file mode 100644 index 000000000..8d4b932ea --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/include/zlib.h @@ -0,0 +1,1938 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.3.1, January 22nd, 2024 + + Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.3.1" +#define ZLIB_VERNUM 0x1310 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 1 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, + uLong sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); + +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, resetting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written or 0 in case of error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf(), + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. len2 must be non-negative. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.a b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.a new file mode 100644 index 000000000..7e360afe5 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.a differ diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1 b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1 new file mode 120000 index 000000000..1468e125e --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1 @@ -0,0 +1 @@ +libz.so.1.3.1 \ No newline at end of file diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1.3.1 b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1.3.1 new file mode 100755 index 000000000..01a5fe324 Binary files /dev/null and b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/libz.so.1.3.1 differ diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/pkgconfig/zlib.pc b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/pkgconfig/zlib.pc new file mode 100644 index 000000000..45a412588 --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/lib/pkgconfig/zlib.pc @@ -0,0 +1,13 @@ +prefix=/home/jerry/Downloads/toolchain/zlib-1.3.1/_install +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.3.1 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/share/man/man3/zlib.3 b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/share/man/man3/zlib.3 new file mode 100644 index 000000000..c716020ea --- /dev/null +++ b/MagicEyes/platforms/aarch64/dependency/zlib-1.3.1/share/man/man3/zlib.3 @@ -0,0 +1,149 @@ +.TH ZLIB 3 "22 Jan 2024" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I test/example.c +and +.IR test/minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is built in to many languages and operating systems, including but not limited to +Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. +.LP +An experimental package to read and write files in the .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the +.I zlib +library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) +.br +http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) +.br +http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS AND LICENSE +Version 1.3.1 +.LP +Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler +.LP +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. +.LP +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +.LP +.nr step 1 1 +.IP \n[step]. 3 +The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +.IP \n+[step]. +Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +.IP \n+[step]. +This notice may not be removed or altered from any source distribution. +.LP +Jean-loup Gailly Mark Adler +.br +jloup@gzip.org madler@alumni.caltech.edu +.LP +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/MagicEyes/tools/cmake/FindBpfObject.cmake b/MagicEyes/tools/cmake/FindBpfObject.cmake index 3ff2d6276..a667ae89b 100644 --- a/MagicEyes/tools/cmake/FindBpfObject.cmake +++ b/MagicEyes/tools/cmake/FindBpfObject.cmake @@ -142,19 +142,20 @@ else() message(FATAL_ERROR "Failed to determine BPF system includes: ${CLANG_SYSTEM_INCLUDES_error}") endif() -# Get target arch -execute_process(COMMAND uname -m - COMMAND sed -e "s/x86_64/x86/" -e "s/aarch64/arm64/" -e "s/ppc64le/powerpc/" -e "s/mips.*/mips/" -e "s/riscv64/riscv/" - OUTPUT_VARIABLE ARCH_output - ERROR_VARIABLE ARCH_error - RESULT_VARIABLE ARCH_result - OUTPUT_STRIP_TRAILING_WHITESPACE) -if(${ARCH_result} EQUAL 0) - set(ARCH ${ARCH_output}) - message(STATUS "BPF target arch: ${ARCH}") -else() - message(FATAL_ERROR "Failed to determine target architecture: ${ARCH_error}") -endif() +# lht修改:统一使用顶层CMakeLists.txt中设置的ARCH +# execute_process(COMMAND uname -m +# COMMAND sed -e "s/x86_64/x86/" -e "s/aarch64/arm64/" -e "s/ppc64le/powerpc/" -e "s/mips.*/mips/" -e "s/riscv64/riscv/" +# OUTPUT_VARIABLE ARCH_output +# ERROR_VARIABLE ARCH_error +# RESULT_VARIABLE ARCH_result +# OUTPUT_STRIP_TRAILING_WHITESPACE) +# if(${ARCH_result} EQUAL 0) +# # set(ARCH ${ARCH_output}) +# message(STATUS "BPF target arch: ${ARCH}") +# else() +# message(FATAL_ERROR "Failed to determine target architecture: ${ARCH_error}") +# endif() +message(STATUS "BPF target arch: ${ARCH}") # 将 *.bpf.c 使用clang编译成 *.o,然后将 *.o 使用 bpftool 转换为 *.skel.h macro(bpf_object name input src_gen_dir) @@ -198,5 +199,16 @@ macro(bpf_object name input src_gen_dir) # ------------------------------------------------------------------------------------ target_include_directories(${OUTPUT_TARGET} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(${OUTPUT_TARGET} SYSTEM INTERFACE ${LIBBPF_INCLUDE_DIRS}) - target_link_libraries(${OUTPUT_TARGET} INTERFACE ${LIBBPF_LIBRARIES} -lelf -lz) + +#lht增加:修改不同编译环境编译依赖静态库 skel的依赖库 + if(ARCH STREQUAL "x86") + target_link_libraries(${OUTPUT_TARGET} INTERFACE ${LIBBPF_LIBRARIES} -lelf -lz) + elseif(ARCH STREQUAL "arm64") + target_link_libraries(${OUTPUT_TARGET} INTERFACE + ${LIBBPF_LIBRARIES} + ${ZLIB_ARM64_DIR}/libz.a + ${ELF_ARM64_DIR}/libelf.a ) + else() + endif() + endmacro() diff --git a/eBPF_Supermarket/CPU_Subsystem/blazesym b/eBPF_Supermarket/CPU_Subsystem/blazesym index 90eb4e08a..dc343b7e9 160000 --- a/eBPF_Supermarket/CPU_Subsystem/blazesym +++ b/eBPF_Supermarket/CPU_Subsystem/blazesym @@ -1 +1 @@ -Subproject commit 90eb4e08a25d702776f35b6b7fea97900213e3d5 +Subproject commit dc343b7e99f7194f41160a8fc9f6f4a1cf6d4485 diff --git a/eBPF_Supermarket/CPU_Subsystem/bpftool b/eBPF_Supermarket/CPU_Subsystem/bpftool index 06c61eccd..8485b9fba 160000 --- a/eBPF_Supermarket/CPU_Subsystem/bpftool +++ b/eBPF_Supermarket/CPU_Subsystem/bpftool @@ -1 +1 @@ -Subproject commit 06c61eccd3b8a6ff3df3e451a2a93058913124fc +Subproject commit 8485b9fba9b3bb3bd311b00632d2d22c0eee2e13 diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile index efe1a9de9..8b957563a 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile @@ -38,13 +38,15 @@ VMLINUX := ../vmlinux/$(ARCH)/vmlinux.h # Use our own libbpf API headers and Linux UAPI headers distributed with # libbpf to avoid dependency on system-wide headers, which could be missing or # outdated -INCLUDES := -I$(OUTPUT) -I../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC) -I./ +INCLUDES := -I$(OUTPUT) -I../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC) -I./include CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) APPS =cs_delay sar sc_delay preempt schedule_delay mq_delay TARGETS=cpu_watcher +SRC_DIR = ./include + # Get Clang's default includes on this system. We'll explicitly add these dirs # to the includes list when compiling with `-target bpf` because otherwise some @@ -112,7 +114,7 @@ $(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) $(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ # Build BPF code -$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) +$(OUTPUT)/%.bpf.o: bpf/%.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) $(call msg,BPF,$@) $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ @@ -126,6 +128,10 @@ $(APPS): %: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) $(Q)$(BPFTOOL) gen skeleton $< > $(OUTPUT)/$@.skel.h # Build user-space code +$(OUTPUT)/%.o: $(SRC_DIR)/%.c | $(OUTPUT) + $(call msg,CC,$@) + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) $(call msg,CC,$@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ @@ -133,7 +139,7 @@ $(OUTPUT)/$(TARGETS).o: $(TARGETS).c $(APPS) | $(OUTPUT) # Build application binary $(TARGETS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) $(call msg,BINARY,$@) - $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ + $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@ # delete failed targets .DELETE_ON_ERROR: diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md index f64e4a8a8..b981830cd 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/README.md @@ -68,6 +68,9 @@ make clean 清除生成文件 - `sysc/ms`: CPU执行用户程序系统调用(`syscall`)所占用的时间,是所有CPU的叠加。 - ` utime/ms`:CPU执行普通用户进程时,花在用户态的时间,是所有CPU的叠加。 +原理介绍: + +[libbpf_sar工具原理分析](docs/libbpf_sar.md) ### **2.统计抢占调度时间:** ​ 统计系统中发生抢占调度的情况,包括抢占进程的`pid`与进程名,以及被强占进程的`pid`,和本次抢占时间,单位纳秒。 @@ -214,9 +217,11 @@ per_len = 1000 ​ 获取内核全局变量,直接从内核全局变量读取信息。如proc/s就是通过直接读取total_forks内核全局变量来计算每秒产生进程数的。 +## 五、cpu_watcher可视化 +[cpu_watcher可视化指南](docs/cpu_watcher_vis_guide.md) -## 五、未来展望 +## 六、未来展望 目前`cpu_watcher`工具的总体框架已经完成,工具所能满足的功能已覆盖CPU所涉及的大部分性能指标。下一阶段,本工具将从以下几个方向进行开发和优化: diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c similarity index 58% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c index c94c5d1bf..3434d6a8a 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cs_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/cs_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c similarity index 98% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c index 92589afd6..becb4c27c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/mq_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/mq_delay.bpf.c @@ -1,4 +1,4 @@ -// Copyright 2024 The LMP Authors. +// Copyright 2023 The LMP Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: albert_xuu@163.com +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com #include "vmlinux.h" #include //包含了BPF 辅助函数 diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c similarity index 68% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c index 0abbbc781..57043e3bb 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/preempt.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/preempt.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include @@ -33,7 +49,8 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s return 0; } -SEC("kprobe/finish_task_switch") +// SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") int BPF_KPROBE(finish_task_switch, struct task_struct *prev) { u64 end_time = bpf_ktime_get_ns(); pid_t pid = BPF_CORE_READ(prev, pid); diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c similarity index 88% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c index 4e48d49c7..2fe6b43f5 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sar.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sar.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include @@ -36,8 +52,8 @@ BPF_ARRAY(ut_LastTime,u32,u64,1); BPF_ARRAY(tick_user,u32,u64,1); BPF_ARRAY(symAddr,u32,u64,1); // 统计fork数 -//SEC("kprobe/finish_task_switch.isra.0") -SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") +// SEC("kprobe/finish_task_switch") int kprobe__finish_task_switch(struct pt_regs *ctx) { u32 key = 0; @@ -75,8 +91,8 @@ int trace_sched_switch2(struct cswch_args *info) { return 0; } -SEC("kprobe/finish_task_switch") -//SEC("kprobe/finish_task_switch.isra.0") +// SEC("kprobe/finish_task_switch") +SEC("kprobe/finish_task_switch.isra.0") int BPF_KPROBE(finish_task_switch,struct task_struct *prev){ pid_t pid=BPF_CORE_READ(prev,pid); u64 *val, time = bpf_ktime_get_ns(); diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c similarity index 73% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c index ec642bf17..23eaf2200 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/sc_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/sc_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include "vmlinux.h" #include //包含了BPF 辅助函数 #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c similarity index 88% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c index fda48bda6..036d1178c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/schedule_delay.bpf.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/bpf/schedule_delay.bpf.c @@ -1,3 +1,19 @@ +// Copyright 2023 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c index 709b29c74..8d768fc9c 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: zhangziheng0525@163.com +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com #include diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/cpu_wacther_vis_guide.md b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/cpu_wacther_vis_guide.md new file mode 100644 index 000000000..a20f821b9 --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/cpu_wacther_vis_guide.md @@ -0,0 +1,168 @@ +# cpu_wacther的可视化 + +## 1.配置环境 + +在使用cpu_watcher可视化之前,请先配置docker、go的环境,具体配置方法可参考: + +### 1.1 docker + +先参考该链接进行docker-desktop的安装: + +* [在 Ubuntu 上安装 Docker Desktop |Docker 文档](https://docs.docker.com/desktop/install/ubuntu/#install-docker-desktop) + +在准备启动docker-desktop时,可能遇到打不开docker-desktop的情况,如下所示: + +![image1](image/image1.png) + +这是因为虚拟机暂时不支持虚拟化,可以先关闭虚拟机,重新编辑虚拟机设置,开启虚拟化引擎的两个选项,再开机配置kvm; + +* [在 Linux 上安装 Docker Desktop |Docker 文档](https://docs.docker.com/desktop/install/linux-install/) + +![image2](image/image2.png) + +### 1.2 go环境: + +本可视化功能对go的版本有要求,请安装go1.19+版本,具体安装流程可参考如下链接: + +* [go:快速升级Go版本,我几分钟就解决了_go 升级版本-CSDN博客](https://blog.csdn.net/m0_37482190/article/details/128673828) + +## 2.使用cpuwatcher 可视化 + +* 首先先进入lmp目录下的lmp/eBPF_Supermarket/CPU_Subsystem/cpu_watcher文件夹 + + ```BASH + cd lmp/eBPF_Supermarket/CPU_Subsystem/cpu_watcher + ``` + + 在该目录下 进行make编译 + + ```bash + make -j 20 + ``` + +* 在lmp目录下的eBPF_Visualization/eBPF_prometheus文件夹下 + +* 执行`make`指令,编译可视化的go语言工具 + + 在执行make指令时,如果出现如下报错,是因为go包管理代理网址无法访问`proxy.golang.org` + + ```bash + go: golang.org/x/exp@v0.0.0-20190731235908-ec7cb31e5a56: Get "https://proxy.golang.org/golang.org/x/exp/@v/v0.0.0-20190731235908-ec7cb31e5a56.mod": dial tcp 172.217.160.113:443: i/o timeout + ``` + + 只需要换一个国内能访问的2代理地址即可 + + ```bash + go env -w GOPROXY=https://goproxy.cn + ``` + +* 执行`make start_service`指令,配置下载docker镜像并启动grafana和prometheus服务 + +* 执行如下指令开始采集数据以及相关处理: + + ```bash + ./data-visual collect /home/zhang/lmp/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher -s + ``` + +* 在网页打开网址:http://192.168.159.128:8090/metrics 此处为`localhost:8090/metrics`,便可以看到暴露在http网页中的数据; + + ![image3](image/image3.png) + +* 在网页打开网址:http://192.168.159.128:3000/ 即可进入grafana服务,使用初始密码登录(user:admin pswd: admin)进入管理界面: + + - 点击【Home-Connection-Add new connection】,选择Prometheus,建立与Prometheus服务器的连接: + + ![image4](image/image4.png) + + 这个172.17.0.1表示docker0网桥的 IPv4 地址。在 Docker 中,通常会将docker0的第一个 IP 地址分配给Docker主机自身。因此,172.17.0.1是 Docker主机上Docker守护进程的 IP 地址,所以在Grafana数据源这块设置成[http://172.17.0.1:9090](http://172.17.0.1:9090/) ,然后点击下面的【Save & test】按钮 + +- 进入可视化配置界面: + + ![image4.5](image/image4.5.png) + ![image5](image/image5.png) + +- 在下方处进行如图所示的配置,点击Run queries即可以可视化的方式监控avg_delay字段的数据: + + ![image6](image/image6.png) + +## 3.cpu_watcher各子工具可视化输出 + +本次可视化输出样例,是在对比系统正常运行和高负载运行时本工具的使用情况,使用stress加压工具对cpu进行持续5min的加压 + +```bash +stress --cpu 8 --timeout 300s +``` + +### 3.1 cpu_watcher -s + +**【irq Time】可视化输出结果** + +![image7](image/image7.png) + +**【softirq Time】可视化输出结果** + +![image8](image/image8.png) +**【cswch】可视化输出结果** + +![image9](image/image9.png) +**【proc】可视化输出结果** + +![image10](image/image10.png) + +**【Kthread】可视化输出结果** + +![image11](image/image11.png) + +**【idle】可视化输出结果** + +![image12](image/image12.png) + +**【sys】可视化输出结果** + +![image-20240411132742107](image/image-20240411132742107.png) + +**【sysc】可视化输出结果** + +![image-20240411132807253](image/image-20240411132807253.png) + +**【utime】可视化输出结果** + +![image-20240411132842070](image/image-20240411132842070.png) + +**【cpu处于不同状态对比图】可视化输出结果** + +![image-20240411132914396](image/image-20240411132914396.png) + +### 3.2 cpu_watcher -c + +**【cs_delay】可视化输出结果** + +![image-20240411133505763](image/image-20240411133505763.png) + +### 3.3 cpu_watcher -d + +**【schedule_delay】可视化输出结果** + +【max_delay】 + +![image-20240411133841698](image/image-20240411133841698.png) + +【avg_delay】 + +![image-20240411135159178](image/image-20240411135159178.png) + +【min_delay】 + +![image-20240411135335523](image/image-20240411135335523.png) + +### 3.4 cpu_watcher -p + +**【preempt】可视化输出结果** + +![image-20240411142421440](image/image-20240411142421440.png) + +## 3.5 cpu_watcher -S + +**【syscall_delay】可视化输出结果** + +![image-20240411144331888](image/image-20240411144331888.png) \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132742107.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132742107.png new file mode 100644 index 000000000..dcfb6ad1d Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132742107.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132807253.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132807253.png new file mode 100644 index 000000000..941b9006f Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132807253.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132842070.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132842070.png new file mode 100644 index 000000000..1c32506ac Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132842070.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132914396.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132914396.png new file mode 100644 index 000000000..7d156c222 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411132914396.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133505763.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133505763.png new file mode 100644 index 000000000..109b29e59 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133505763.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133841698.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133841698.png new file mode 100644 index 000000000..84279fb8d Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411133841698.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135159178.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135159178.png new file mode 100644 index 000000000..ad7c56591 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135159178.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135335523.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135335523.png new file mode 100644 index 000000000..5c46cc2f1 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411135335523.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411142421440.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411142421440.png new file mode 100644 index 000000000..b308e3268 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411142421440.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411144331888.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411144331888.png new file mode 100644 index 000000000..6e174c2f5 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411144331888.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411160509242.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411160509242.png new file mode 100644 index 000000000..bc7a81d97 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411160509242.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170250839.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170250839.png new file mode 100644 index 000000000..5b6bdc717 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170250839.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170311182.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170311182.png new file mode 100644 index 000000000..a900381ba Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image-20240411170311182.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image1.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image1.png new file mode 100644 index 000000000..b0c02f418 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image1.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image10.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image10.png new file mode 100644 index 000000000..8c4a4bf93 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image10.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image11.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image11.png new file mode 100644 index 000000000..dc04b23f1 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image11.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image12.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image12.png new file mode 100644 index 000000000..bfb87edef Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image12.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image2.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image2.png new file mode 100644 index 000000000..140a97b81 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image2.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image3.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image3.png new file mode 100644 index 000000000..52db1de49 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image3.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.5.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.5.png new file mode 100644 index 000000000..40aef3a11 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.5.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.png new file mode 100644 index 000000000..d186d225c Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image4.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image5.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image5.png new file mode 100644 index 000000000..48f6a4a74 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image5.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image6.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image6.png new file mode 100644 index 000000000..77baa7887 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image6.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image7.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image7.png new file mode 100644 index 000000000..cbf0a5915 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image7.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image8.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image8.png new file mode 100644 index 000000000..23c5d49fd Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image8.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image9.png b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image9.png new file mode 100644 index 000000000..e0b384f07 Binary files /dev/null and b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/image/image9.png differ diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/libbpf_sar.md b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/libbpf_sar.md new file mode 100644 index 000000000..4944fc264 --- /dev/null +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/docs/libbpf_sar.md @@ -0,0 +1,81 @@ +# libbpf_sar功能介绍: + +libbpf_sar是cpu_watcher工具中的一个子工具,通过cpu_watcher -s使用; + +## 1.应用场景及意义 + +libbpf_sar是一个基于eBPF的按照指定时间间隔(默认为1s)来统计特定事件发生次数和特定事件占用CPU时间的工具。使用它可以帮助您查看事件发生速率和CPU资源利用率,并提供CPU负载画像以剖析负载的来源及其占用比例。 + +与传统工具相比,libbpf_sar可提供更为细致的指标,如: + +* 1.可把内核态时间剖析为内核线程执行时间sar和进程系统调用时间 + +* 2.部分linux发行版可能由于内核编译选项确实而不能记录irq时间,本工具可以弥补这一缺陷,并且不需要对内核做出任何更改,可动态检测 + +3.可附加到指定进程上,对该进程占用的CPU资源进行实时监测 + +## 2.性能参数及观测意义 + +在 Linux 中,与 CPU 相关的状态可以分为很多类,如用户态、系统调用、硬中断以及软中断等,同时还有一些内核线程执行的状态,如 kthread,idle 进程。 + +同时,也有一些对 CPU 相当重要的事件,如新进程创建,进程切换计数,运行队 列长度等,对这些细分事件进行准确的监测,有利于我们剖析出 CPU 负载根源, 并定位出性能瓶颈。 + +libbpf_sar主要是对 CPU 上的关键事件提供的具体信息参数与含义如表3-6所示: + +libbpf_sar 实例采集信息及含义 + +| **性能指标** | **含义** | +| ------------ | -------------------------------- | +| Proc | 新创建的进程数 | +| Cswch | 进程切换计数 | +| runqlen | 运行队列长度 | +| irqTime | 硬中断时间 | +| Softirq | 软中断时间 | +| Idle | Idle 进程运行时间 | +| Sysc | 加上内核线程运行时间的系统态时间 | +| Utime | 用户态执行时间 | +| sys | 系统调用执行时间 | + +本实例采集到的信息将系统的 CPU 进行了精准分类,并且也统计了关键事件的触发频率,对于系统的性能分析有重要的意义 + +## 3.输出格式: + +```bash + time proc/s cswch/s irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms +15:55:43 48 1389 1646 8866 6811 3243 688 717 691 +15:55:44 31 1089 1587 7375 6759 1868 659 707 660 +15:55:45 47 1613 1685 8885 6792 3268 796 828 799 +15:55:46 0 2133 5938 7797 7643 8106 8 20 17 +15:55:47 1 3182 5128 14279 6644 4883 314 363 319 +15:55:48 0 1815 1773 11329 6753 4286 282 313 287 +15:55:49 31 1249 1605 9859 6752 4442 545 585 549 +15:55:50 47 1601 1712 11348 6765 6249 210 242 216 +15:55:51 0 1238 10591 12709 6802 13896 238 262 252 +15:55:52 0 1145 1658 10000 6863 4593 308 333 313 +15:55:53 0 1317 1587 9090 6798 4699 383 414 387 +15:55:54 31 1254 1531 9570 6755 4252 381 414 385 +15:55:55 47 1547 1624 10985 6769 6516 344 373 350 +15:55:56 0 1064 2187 9892 6851 4585 189 212 194 +``` + +* proc/s 列的数据表示 CPU 每秒新创建的进程数; +* cswch/s 列的数据表示 CPU 每秒进程切换的数量; +* runqlen 列的数据表示 CPU 运行队列的长度; +* irqTime/us 列的数据表示 CPU 处理硬中断的时间,以 us 计时; +* softirq/s 列的数据表示 CPU 每秒处理软中断的时间,以 us 计时; +* idle/ms 列的数据表示 系统处于空闲态的时间; +* kthread/us 列的数据表示系统中内核线程执行的时间; + +* sysc/ms 表示系统中内核线程外加系统调用处理的总时间; +* utime/ms 表示进程在用户态执行的总时间; +* sys/ms 表示系统调用执行的总时间。 + +事件的统计方式是对每个CPU分开统计然后求和,因此有的项的占用时间可能超过1s。所有事件占用时间的和应当为1s * 总CPU核数。由于技术问题,输出的第一项可能偏差较大,可以不予理会。按Ctrl+C本程序将停止统计,并输出在程序运行的时间段内各表项的平均值按照2s的采样频率显示各事件的CPU占用率。数据是带颜色的,蓝色表示CPU占比小于30%,绿色表示占比大于30%小于60%,红色表示占比大于60%。 + + + +## 4.数据可视化 + +![image-20240411160509242](image/image-20240411160509242.png) +![image-20240411170250839](image/image-20240411170250839.png) +![image-20240411170311182](image/image-20240411170311182.png) \ No newline at end of file diff --git a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h similarity index 98% rename from eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h rename to eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h index 6812096ce..aaf5dfb1d 100644 --- a/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.h +++ b/eBPF_Supermarket/CPU_Subsystem/cpu_watcher/include/cpu_watcher.h @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: zhangziheng0525@163.com -// -// eBPF map for libbpf sar +// author: albert_xuu@163.com zhangxy1016304@163.com zhangziheng0525@163.com + #include #include diff --git a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/proc_image_vis_guide.md b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/proc_image_vis_guide.md index b43b75b16..2ed10bd7e 100644 --- a/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/proc_image_vis_guide.md +++ b/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/docs/proc_image_vis_guide.md @@ -105,7 +105,10 @@ TIME READ/s WRITE/s FSYNC/s OPEN/s CREATE/s - 执行如下指令开始采集数据以及相关处理: ``` - ./data-visual collect /home/zhang/lmp/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image -r -p 16279 + // 终端1:挂载eBPF内核态函数,但是处于失活状态(不进行数据的采集) + ./data-visual collect /home/zhang/lmp/eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image -r + // 终端2:激活eBPF内核态函数 + ./controller -a -r -p 16279 ``` - 个人喜欢在主机上进行可视化设置,这样方便快捷,所以在主机上打开网址http://192.168.109.150:8090/metrics (其中192.168.109.150是虚拟机网络接口的IPv4地址),可以看到暴露在http网页中的数据: diff --git a/eBPF_Supermarket/Memory_Subsystem/README.md b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md similarity index 73% rename from eBPF_Supermarket/Memory_Subsystem/README.md rename to eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md index 2175886a4..404253dbf 100644 --- a/eBPF_Supermarket/Memory_Subsystem/README.md +++ b/eBPF_Supermarket/Memory_Subsystem/mem_watcher/README.md @@ -5,44 +5,55 @@ memwatcher是一款基于eBPF的内存监测工具,其设计的目的就是为了可以让用户能够在主机环境上可以快捷的检测到Linux内存的详细信息。 通过高效的数据收集和精准的监控能力,帮助用户可以有效的监控主机内存情况。 使用了eBPF(Extended Berkeley Packet Filter)来监控内核中的几个关键事件,主要涉及到内存管理方面的几个功能: -第一:`get_page_from_freelist:` -- 监控页面分配过程中的某些关键参数。 -- 捕获了页面分配时的一些重要信息,比如所用的gfp_mask、order、alloc_flags等。 +本项目是内存性能分析工具集合,采用libbpf编写。现有工具procstat(进程内存状态报告),sysstat(系统内存状态报告),paf(内存页面状态报告),pr(内存回收状态报告)和memleak(内存泄漏检测)。 -第二:`shrink_page_list:` +eBPF 提供了一种高效的机制来监控和追踪系统级别的事件,包括内存的分配和释放。通过 eBPF,可以跟踪内存分配和释放的请求,并收集每次分配的调用堆栈。然后,分析这些信息,找出执行了内存分配但未执行释放操作的调用堆栈,这有助于程序员找出导致内存泄漏的源头。 -- 监控页面收缩(shrink)过程中的一些参数。 -- 捕获了页面收缩时的关键参数,如nr_to_reclaim、nr_reclaimed等。 +------ +## 背景意义 -第三:`finish_task_switch:` +内存子系统是Linux内核中是一个相对复杂的模块,内核中几乎所有的数据、缓存、程序指令都有内存模块参与管理。在内存不足的情况下,这些数据就会被存储在磁盘的交换空间中,但是磁盘的处理速度相对与内存非常慢,当内存和磁盘频繁进行数据交换时,缓慢的磁盘读写速度非常影响系统性能。系统可能因内存不足从而终止那些占用内存较大的进程,导致程序运行故障。因此准确的监控分析内存性能状况就变得非常重要。 -- 监控进程切换完成时的内存相关参数。 -- 捕获了进程切换时的一些内存使用情况,如pid、vsize、rss等。 +目前,传统的内存性能分析工具通过读取proc文件系统下的数据,经过简单的处理后呈现给用户,方便管理人员随时了解系统状况。然而这些工具的灵活性非常差,单个工具输出的信息有限。系统维护人员在分析性能问题时常常需要借助多个工具才能进行。步骤繁琐且工具本身对系统性能也有一定影响。随着ebpf技术在系统可观测上的发展,利于ebpf非侵入式的数据获取方式已被大多数企业、高校认可并取得了一定的研究成果。ebpf的可编程性可以让管理人员灵活的获取系统的运行数据,而且在数据的提取粒度上有着传统工具无法比拟的优势。现在,ebpf作为Linux内核顶级子系统,已经成为实现Linux内核可观测性、网络和内核安全的理想技术。 -第四:`get_page_from_freelist:` +## 准备工作 +环境:Ubuntu 20.04, 内核版本 5.13.0-30-generic -- 监控页面分配的另一方面,可能是为了提供更全面的内存分配情况。 -- 捕获了更多与页面分配相关的内存统计信息,如anon_inactive、file_inactive等。 +注:由于 eBPF 的 kprobe 逻辑与内核数据结构定义高度相关,而现在 BTF 的应用(可消除不同内核版本间数据结构的不兼容)还不是很成熟,因此在使用此例程前,需首先适配内核版本。 -通过收集这些信息,可以用于监控系统内存的使用情况、诊断内存相关的性能问题以及进行性能优化。 +软件: -第五: +- go SDK(安装cilium库) -内存泄露是指程序在申请内存后,无法释放或未能及时释放,从而导致系统内存的不断消耗,最终导致程序的崩溃或性能的下降。这种现象一般发生在程序中有大量的动态内存分配和释放操作,如果程序员忘记或者疏忽了释放内存,就有可能导致内存泄露。 +- llvm,clang -eBPF 提供了一种高效的机制来监控和追踪系统级别的事件,包括内存的分配和释放。通过 eBPF,可以跟踪内存分配和释放的请求,并收集每次分配的调用堆栈。然后,分析这些信息,找出执行了内存分配但未执行释放操作的调用堆栈,这有助于程序员找出导致内存泄漏的源头。 +- bpftrace ------- -## 背景意义 +# 工具的使用方法说明 -内存子系统是Linux内核中是一个相对复杂的模块,内核中几乎所有的数据、缓存、程序指令都有内存模块参与管理。在内存不足的情况下,这些数据就会被存储在磁盘的交换空间中,但是磁盘的处理速度相对与内存非常慢,当内存和磁盘频繁进行数据交换时,缓慢的磁盘读写速度非常影响系统性能。系统可能因内存不足从而终止那些占用内存较大的进程,导致程序运行故障。因此准确的监控分析内存性能状况就变得非常重要。 +## 功能介绍 -目前,传统的内存性能分析工具通过读取proc文件系统下的数据,经过简单的处理后呈现给用户,方便管理人员随时了解系统状况。然而这些工具的灵活性非常差,单个工具输出的信息有限。系统维护人员在分析性能问题时常常需要借助多个工具才能进行。步骤繁琐且工具本身对系统性能也有一定影响。随着ebpf技术在系统可观测上的发展,利于ebpf非侵入式的数据获取方式已被大多数企业、高校认可并取得了一定的研究成果。ebpf的可编程性可以让管理人员灵活的获取系统的运行数据,而且在数据的提取粒度上有着传统工具无法比拟的优势。现在,ebpf作为Linux内核顶级子系统,已经成为实现Linux内核可观测性、网络和内核安全的理想技术。 +mem_watcher工具可以通过一系列的命令控制参数来控制其具体的检测行为:我们可以通过sudo ./mem_watcher -h来查看工具支持的功能 + +``` + select function: + -a, --paf print paf (内存页面状态报告) + -p, --pr print pr (页面回收状态报告) + -r, --procstat print procstat (进程内存状态报告) + -s, --sysstat print sysstat (系统内存状态报告) + -l, --memleak=PID print memleak (内存泄漏检测) +``` + +- -a 输出的信息包括时间戳、进程ID、虚拟内存大小、物理内存等。输出的内容根据用户的选择(特定PID、是否显示RSS等)而变化。除了常规的事件信息外,程序还输出了与内存管理相关的详细信息,主要是present(当前内存中可用的页面数量),min(在这个阈值下,系统可能会触发内存压缩),low(在这个阈值下,系统进行内存回收),high(在这个阈值上,认为内存资源充足),flag(用于内存分配的状态)。 +- -p 跟踪内核中页面的回收行为,记录回收的各个阶段,例如要回收的页面,以回收的页面,等待回收的脏页数,要写回的页数(包括交换空间中的页数)以及当前正在写回的页数。 +- -r 主要是用于跟踪用户空间进程的内存使用情况。具体功能是在用户空间进程切换时,记录切换前进程的内存信息。 +- -s 提取各种类型内存的活动和非活动页面数量,以及其他内存回收相关的统计数据,除了常规的事件信息外,程序还输出了与内存管理相关的详细信息,包括了不同类型内存的活动(active)和非活动(inactive)页面,未被驱逐(unevictable)页面,脏(dirty)页面,写回(writeback)页面,映射(mapped)页面,以及各种类型的内存回收相关统计数据。 +- -l 输出了用户态造成内存泄漏的位置,包括内存泄漏指令地址对应符号名、文件名、行号,程序中尚未被释放的内存总量,未被释放的分配次数。 ------ -# mem_watcher据体代码的分析。 +# mem_watcher具体功能分析 ## procstat @@ -59,35 +70,45 @@ eBPF 提供了一种高效的机制来监控和追踪系统级别的事件,包 | vdata | 进程使用的私有数据段大小 | | vpte | 进程页表大小 | | vstk | 进程用户栈大小 | -### 功能 -主要是用于跟踪用户空间进程的内存使用情况。具体功能是在用户空间进程切换时,记录切换前进程的内存信息,并将这些信息写入环形缓冲区中。 - -### 分析 - -`BPF_KPROBE`标记了一个内核探针函数,挂载在`finish_task_switch`结束时,这个函数用于捕获进程切换事件。 -内核探针函数首先通过`bpf_get_current_pid_tgid()`获取当前进程的PID,然后通过prev参数获取切换前的进程结构体指针。 -然后判断当前进程的PID是否是要跟踪的用户进程的PID,如果是则直接返回,不做任何处理。 -接着获取切换前进程的PID,并判断是否是要跟踪的用户进程的PID,如果是则直接返回。 -如果不是要跟踪的进程,则从`last_val`哈希表中查找上一次记录的内存状态。 -如果没有找到,则更新`last_val`哈希表,将该进程的PID作为键,将值设置为1。 -如果找到了上一次的记录,并且上一次的值与当前值相同,则说明内存状态没有变化,直接返回。 -如果上一次的记录与当前值不同,则说明内存状态发生了变化,需要记录内存信息。 -通过`bpf_ringbuf_reserve()`函数在环形缓冲区中分配空间,并填充内存事件信息。 -最后通过`bpf_ringbuf_submit()`函数将填充好的内存事件信息提交到环形缓冲区中。 ### 载点及挂载原因 挂载点:finish_task_switch 挂载原因: -首先,获取进程级别内存使用信息首先需要获取到进程的task_struct结构体,其中在mm_struct成员中存在一个保存进程当前内存使用状态的数组结构,因此有关进程的大部分内存使用信息都可以通过这个数组获得。其次,需要注意函数的插入点,插入点的选取关系到数据准确性是否得到保证,而在进程的内存申请,释放,规整等代码路径上都存在页面状态改变,但是数量信息还没有更新的相关结构中的情况,如果插入点这两者中间,数据就会和实际情况存在差异,所有在确保可以获取到进程PCB的前提下,选择在进程调度代码路径上考虑。而finish_task_switch函数是新一个进程第一个执行的函数,做的事却是给上一个被调度出去的进程做收尾工作,所有这个函数的参数是上一个进程的PCB,从这块获得上一个进程的内存信息就可以确保在它没有再次被调度上CPU执行的这段时间内的内存数据稳定性。因此最后选择将程序挂载到finish_task_switch函数上。以下是调度程序处理过程: - -![](./image/6.png) +首先,获取进程级别内存使用信息首先需要获取到进程的task_struct结构体,其中在mm_struct成员中存在一个保存进程当前内存使用状态的数组结构,因此有关进程的大部分内存使用信息都可以通过这个数组获得。其次,需要注意函数的插入点,插入点的选取关系到数据准确性是否得到保证,而在进程的内存申请,释放,规整等代码路径上都存在页面状态改变,但是数量信息还没有更新的相关结构中的情况,如果插入点这两者中间,数据就会和实际情况存在差异,所有在确保可以获取到进程PCB的前提下,选择在进程调度代码路径上考虑。而finish_task_switch函数是新一个进程第一个执行的函数,做的事却是给上一个被调度出去的进程做收尾工作,所有这个函数的参数是上一个进程的PCB,从这块获得上一个进程的内存信息就可以确保在它没有再次被调度上CPU执行的这段时间内的内存数据稳定性。因此最后选择将程序挂载到finish_task_switch函数上。 -数据来源有两部分,一个是mm_struc结构本身存在的状态信息,另一个是在mm_rss_stat结构中,它总共统计四部分信息,内核定义如下: +### 可以解决的问题 +首先,通过监测这些指标,可以及时发现内存使用异常或泄漏问题,针对性地进行性能优化和内存管理,确保系统运行的高效性和稳定性。其次,了解进程的内存占用情况有助于有效管理系统资源,避免资源浪费和冲突,提高整体资源利用率。此外,当系统出现内存相关的故障或异常时,通过分析这些指标可以快速定位问题所在,有针对性地进行故障排除和修复,缩短系统恢复时间。结合这些指标可以进行性能调优,优化内存分配和释放策略,提升系统的响应速度和整体性能表现。 -![](./image/7.png) +### 使用方法和结果展示 +```c +sudo ./mem_watcher -r +...... +01:08:50 334 0 0 0 0 +01:08:50 2984 13194 10242 2952 0 +01:08:50 0 0 0 0 0 +01:08:50 334 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 2984 13194 10242 2952 0 +01:08:50 0 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 334 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 0 0 0 0 0 +01:08:50 5427 0 0 0 0 +01:08:50 0 0 0 0 0 +...... +``` ## sysstat @@ -119,16 +140,6 @@ eBPF 提供了一种高效的机制来监控和追踪系统级别的事件,包 提取各种类型内存的活动和非活动页面数量,以及其他内存回收相关的统计数据,除了常规的事件信息外,程序还输出了与内存管理相关的详细信息,包括了不同类型内存的活动(active)和非活动(inactive)页面,未被驱逐(unevictable)页面,脏(dirty)页面,写回(writeback)页面,映射(mapped)页面,以及各种类型的内存回收相关统计数据。 -### 分析 - -分别用last_val1、last_val2、last_val3 三个哈希表记录上次统计的值,这里的键是不同类型页面的数量。 -`BPF_KPROBE(get_page_from_freelist_second, ...)` 是一个 Kprobe 函数,用于跟踪从空闲页列表获取页面的情况。 -在函数内部,首先获取当前进程的 PID,并与 `user_pid` 进行比较,如果相同则直接返回。 -通过 `BPF_CORE_READ` 读取内存分配相关的统计信息,包括匿名页面的活动状态和非活动状态下的数量、文件页面的活动状态和非活动状态下的数量、不可驱逐页面的数量等。 -通过三个哈希表 last_val1、last_val2、last_val3 查找上次统计的值,如果不存在则将新的统计值更新到哈希表中,如果存在且与当前值相同,则表示重复统计,直接返回。 -在环形缓冲区中预留空间,用于记录系统统计事件,并将获取的内存分配相关的统计信息填充到事件结构体中。 -最后,提交系统统计事件到环形缓冲区中。 -这个代码的挂载函数和paf代码相同在这里不再进行二次分析。 ### 挂载点及挂载原因 挂载点:get_page_from_freelist @@ -160,9 +171,7 @@ struct mempolicy *get_task_policy(struct task_struct *p) 经过对内存申请的内部结构alloc_context分析(这是内存申请过程中临时保存相关参数的结构),当前内存节点是可以通过:alloc_context——>zoneref——>zone——>pglist_data的路径访问到。 -其次,因为函数执行申请内存的过程对获取内存节点数据的影响不大,所以只要可以获得alloc_context数据结构,在整个申请路径上挂载函数都是可以的。sysstat工具选择的挂载点是get_page_from_freelist函数。这个函数是快速物理内存分配的入口函数。因为内核在进行物理内存分配时,都会进入快速路径分配,只有当失败时才会进入慢速路径,所以get_page_from_freelist函数是必经函数。整个处理过程以及函数关系如下: - -![](./image/1.png) +其次,因为函数执行申请内存的过程对获取内存节点数据的影响不大,所以只要可以获得alloc_context数据结构,在整个申请路径上挂载函数都是可以的。sysstat工具选择的挂载点是get_page_from_freelist函数。这个函数是快速物理内存分配的入口函数。因为内核在进行物理内存分配时,都会进入快速路径分配,只有当失败时才会进入慢速路径,所以get_page_from_freelist函数是必经函数。 但是,经过对proc文件系统的打印函数meminfo_proc_show函数的分析得知,影响内存性能的参数在vm_stat中无法全部获得。一部分数据需要遍历当前内存节点包含的所有内存管理区zone结构中vm_stat数组获得,一部分需要读取全局变量vm_node_stat获得。但是内核的全局变量不会作为函数参数参与数据处理,目前还没具体方法获得这部分数据。 @@ -174,6 +183,21 @@ struct mempolicy *get_task_policy(struct task_struct *p) ■ 当前剩余内存总量的统计需要遍历所有内存管理区来统计,但是由于内存管理区的空闲页面信息存储在数组第一个位置,使用指针指向时,统计到的数据不准确,使用变量统计会出现数据类型错误的报告。 +### 可以解决的问题 +通过提取内存指标,可以及时发现潜在问题,如内存泄漏,从而采取相应措施。此外,了解各种内存类型的使用情况有助于合理分配资源,提高系统效率,并确保数据一致性。 + +### 使用方法和结果展示 +```c +sudo ./mem_watcher -s +...... +ACTIVE INACTVE ANON_ACT ANON_INA FILE_ACT FILE_INA UNEVICT DIRTY WRITEBK ANONPAG MAP SHMEM +327644 2747936 1988 2278752 325656 469184 0 216 0 563728 249116 7832 +327652 2747616 1996 2278432 325656 469184 0 240 0 563844 249164 7832 +327652 2747616 1996 2278432 325656 469184 0 240 0 563864 249164 7832 +327652 2747844 1996 2278656 325656 469188 0 252 0 563864 249164 7832 +327652 2747844 1996 2278656 325656 469188 0 252 0 563884 249164 7832 +...... +``` ## paf ### 采集信息 @@ -190,16 +214,7 @@ struct mempolicy *get_task_policy(struct task_struct *p) 主要是监控内核中的`get_page_from_freelist`函数。这个函数在内核中用于从内存空闲页列表中获取一个页面。 程序主要是输出present(当前内存中可用的页面数量),min(在这个阈值下,系统可能会触发内存压缩),low(在这个阈值下,系统进行内存回收),high(在这个阈值上,认为内存资源充足),flag(用于内存分配的状态)。 -### 分析 - -该程序挂载在内核函数`get_page_from_freelist`的前面。 -首先,获取当前进程的PID,并检查是否等于`user_pid`,如果相等,则直接返回,表示不监控当前进程。 -然后,通过`bpf_map_lookup_elem()`查找last_val哈希表中是否已经存在当前`gfp_mask`的值,如果不存在,则将当前`gfp_mask`的值插入哈希表中。 -如果已经存在,并且与上一次观察到的值相同,则直接返回,表示不需要重复记录相同的`gfp_mask`值。 -接着,通过`bpf_ringbuf_reserve()`尝试在环形缓冲区中预留一段空间,用于存储事件数据。如果预留失败,则直接返回。 -之后,通过`BPF_CORE_READ()`读取给定的内核数据结构`alloc_context`中的一些字段的值,并将这些值存储在定义好的事件结构体e中。 -最后,通过`bpf_ringbuf_submit()`将填充好的事件结构体提交到环形缓冲区中。 - +### 注: 内存申请失败一般集中在申请权限不够或者是权限冲突导致,申请权限不够是当内核申请优先级较低的页面时,虽然内存管理区有足够的页面满足这次申请数量,但是当前剩余空闲页面少于最低警戒水位,因此导致内核无法成功分配页面的情况。权限冲突,例如内核在开启CMA机制下导致的页面页面申请失败的情况,这种情况下管理区空闲页面需要减去CMA机制占用内存才是当前可分配内存。相关权限判断代码如下: 添加CMA权限代码路径mm/page_alloc.c @@ -259,7 +274,21 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, ■ 因为内存管理区的剩余内存空间处在vm_stat数组第一位,经过分析,使用指针提取的数组第一个数据总是存在差异,需要调整。 ■ 对打印的标志位需要进一步解析,方便快速确认当前申请页面类型。 +### 可以解决的问题 +可以帮助监控系统内存的使用情况,预测内存不足的可能性,以及在必要时触发相应的内存回收机制来保证系统的稳定性和性能。 + +### 使用方法和结果展示 +```c +sudo ./mem_watcher -a +MIN LOW HIGH PRESENT FLAG +262144 5100 6120 262144 1100dca +262144 5100 6120 262144 2800 +262144 5100 6120 262144 cc0 +262144 5100 6120 262144 d00 +262144 5100 6120 262144 2dc2 +...... +``` ## pr @@ -278,12 +307,6 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, 整个BPF程序的功能是监控`shrink_page_list`函数的调用,当函数被调用时,记录特定的内核数据(包括`nr_reclaimed`等值),并将这些数据存储在环形缓冲区中,以供用户空间程序使用。 跟踪内核中页面的回收行为,记录回收的各个阶段,例如要回收的页面,以回收的页面,等待回收的脏页数,要写回的页数(包括交换空间中的页数)以及当前正在写回的页数。 -### 分析 - -在这个函数内部,首先通过`bpf_get_current_pid_tgid()`获取当前进程的PID,并与`user_pid`比较,如果相等,则直接返回,表示不监控当前进程。 -通过`BPF_CORE_READ()`读取给定的内核数据结构`scan_control`中的一些字段的值,并将这些值存储在定义好的事件结构体中。 -通过`bpf_ringbuf_reserve()`尝试在环形缓冲区中预留一段空间,用于存储事件数据。如果预留失败,则直接返回。 -通过bpf_ringbuf_submit()将填充好的事件结构体提交到环形缓冲区中。 ### 挂载点与挂载原因 挂载点 @@ -293,69 +316,11 @@ shrink_page_list 挂载原因 shrink_page_list函数是页面回收后期指向函数,主要操作是遍历链表中每一个页面,根据页面的属性确定将页面添加到回收队列、活跃链表还是不活跃链表.这块遍历的链表是在上一级函数 shrink_inactive_list中定义的临时链表,因为一次最多扫描32个页面,所有链表最多含有32个页面。在shrink_page_list这个函数中还有一个重要操作是统计不同状态的页面数量并保存在scan_control结构体中。而工具数据提取的位置就是找到这个结构体并获取有关性能指标。因为这个提取的数据都是内核函数实时更改的,所有具有较高准确性。 - scan_control结构体是每次进行内存回收时都会被回收进程重新定义,所有会看到数据是一个增长状态,之后有回归0,这和挂载点也有一定关系。 -## memleak - -### 功能 - -代码主要用于跟踪内核内存分配和释放的情况,并记录相关的统计信息。 - -### 分析 - -首先定义了几个 BPF 映射: -`sizes`:用于存储与每个进程 ID(PID)关联的内存分配大小。 -`allocs`:用于存储与内存分配相关信息,以分配的返回地址为索引。 -`combined_allocs`:另一个哈希映射,用于根据堆栈跟踪 ID 聚合内存分配信息。 -`stack_traces`:堆栈跟踪映射,用于将堆栈跟踪转换为堆栈跟踪 ID。 - -定义了两个 `uprobes`(用户空间探测点): -`malloc_enter`:此探测点附加到 `malloc` 函数的入口点。它将当前进程 ID(pid)的内存分配大小记录到 `sizes` 映射中。 -`malloc_exit`:此探测点附加到 `malloc` 函数的退出点。它从 `sizes` 映射中检索先前记录的大小,将其与分配的返回地址关联,并使用此信息更新 `allocs` 映射。此外,它根据堆栈跟踪更新 `combined_allocs` 映射以聚合分配信息。 +### 可以解决的问题 +监测系统的页面回收和写回情况,对系统内存使用和性能优化非常重要。整体来说,这些参数可以帮助系统管理员或开发人员了解系统内存管理的情况,包括页面回收的效率、脏页处理情况以及写回操作的进度。 -定义了一个 `uretprobe`(用户空间返回探测点): -`malloc_exit`:此探测点附加到 `malloc` 函数的退出点。它从 sizes 映射中检索先前记录的大小,将其与分配的返回地址关联,并使用此信息更新 `allocs` 映射。此外,它根据堆栈跟踪更新 `combined_allocs` 映射以聚合分配信息。 - -定义了一个 `uprobe`(用户空间探测点): -`free_ente`r:此探测点附加到 `free` 函数的入口点。它从 allocs 映射中检索与正在释放的地址相关的分配信息。然后,它更新 `combined_allocs` 映射以反映释放。 - -# 工具的使用方法说明 - -## 功能介绍 - -mem_watcher工具可以通过一系列的命令控制参数来控制其具体的检测行为:我们可以通过sudo ./mem_watcher -h来查看工具支持的功能 - -``` - select function: - -a, --paf print paf (内存页面状态报告) - -p, --pr print pr (页面回收状态报告) - -r, --procstat print procstat (进程内存状态报告) - -s, --sysstat print sysstat (系统内存状态报告) - -l, --memleak=PID print memleak (内存泄漏检测) -``` - -- -a 输出的信息包括时间戳、进程ID、虚拟内存大小、物理内存等。输出的内容根据用户的选择(特定PID、是否显示RSS等)而变化。除了常规的事件信息外,程序还输出了与内存管理相关的详细信息,主要是present(当前内存中可用的页面数量),min(在这个阈值下,系统可能会触发内存压缩),low(在这个阈值下,系统进行内存回收),high(在这个阈值上,认为内存资源充足),flag(用于内存分配的状态)。 -- -p 跟踪内核中页面的回收行为,记录回收的各个阶段,例如要回收的页面,以回收的页面,等待回收的脏页数,要写回的页数(包括交换空间中的页数)以及当前正在写回的页数。 -- -r 主要是用于跟踪用户空间进程的内存使用情况。具体功能是在用户空间进程切换时,记录切换前进程的内存信息。 -- -s 提取各种类型内存的活动和非活动页面数量,以及其他内存回收相关的统计数据,除了常规的事件信息外,程序还输出了与内存管理相关的详细信息,包括了不同类型内存的活动(active)和非活动(inactive)页面,未被驱逐(unevictable)页面,脏(dirty)页面,写回(writeback)页面,映射(mapped)页面,以及各种类型的内存回收相关统计数据。 -- -l 输出了用户态造成内存泄漏的位置,包括内存泄漏指令地址对应符号名、文件名、行号,程序中尚未被释放的内存总量,未被释放的分配次数。 - -## 使用方法和结果展示 - -## paf - -```c -sudo ./mem_watcher -a -MIN LOW HIGH PRESENT FLAG -262144 5100 6120 262144 1100dca -262144 5100 6120 262144 2800 -262144 5100 6120 262144 cc0 -262144 5100 6120 262144 d00 -262144 5100 6120 262144 2dc2 -...... -``` - -## pr +### 使用方法和结果展示 ```c sudo ./mem_watcher -p @@ -370,50 +335,16 @@ RECLAIM RECLAIMED UNQUEUE CONGESTED WRITEBACK ...... ``` -## procstat +## memleak -```c -sudo ./mem_watcher -r -...... -01:08:50 334 0 0 0 0 -01:08:50 2984 13194 10242 2952 0 -01:08:50 0 0 0 0 0 -01:08:50 334 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 2984 13194 10242 2952 0 -01:08:50 0 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 334 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 0 0 0 0 0 -01:08:50 5427 0 0 0 0 -01:08:50 0 0 0 0 0 -...... -``` +### 功能 -## sysstat +代码主要用于跟踪内核内存分配和释放的情况,并记录相关的统计信息。 -```c -sudo ./mem_watcher -s -...... -ACTIVE INACTVE ANON_ACT ANON_INA FILE_ACT FILE_INA UNEVICT DIRTY WRITEBK ANONPAG MAP SHMEM -327644 2747936 1988 2278752 325656 469184 0 216 0 563728 249116 7832 -327652 2747616 1996 2278432 325656 469184 0 240 0 563844 249164 7832 -327652 2747616 1996 2278432 325656 469184 0 240 0 563864 249164 7832 -327652 2747844 1996 2278656 325656 469188 0 252 0 563864 249164 7832 -327652 2747844 1996 2278656 325656 469188 0 252 0 563884 249164 7832 -...... -``` +### 可以解决的问题 +可以帮助用户准确的找出内存泄露的位置,更好的排查出所存在的问题。 -## memleak +### 使用方法和结果展示 ``` sudo ./mem_watcher -l 2429 @@ -434,9 +365,4 @@ stack_id=0x3c14 with outstanding allocations: total_size=8 nr_allocs=2 ``` ------ -## 测试环境 - -deepin20.6,Linux-5.17; - -libbpf:[libbpf-bootstrap](https://github.com/libbpf/libbpf-bootstrap) diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.bpf.c b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.bpf.c deleted file mode 100644 index dd18dd50c..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.bpf.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "vmlinux.h" -#include -#include -#include -#include "cma_monitor.h" - -#define INTERVAL_MAX 6U -char LICENSE[] SEC("license") = "Dual BSD/GPL"; -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 8192); - __type(key, unsigned); - __type(value, u64); -} count_map SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 8192); - __type(key, u32); - __type(value, u64); -} time_map SEC(".maps"); - - -SEC("kretprobe/cma_alloc") -int BPF_KRETPROBE(cma_alloc) -{ - u32 pid = bpf_get_current_pid_tgid(); - u64 ts = bpf_ktime_get_ns(); - - bpf_map_update_elem(&time_map, &pid, &ts, BPF_ANY); - - return 0; -} - -SEC("kprobe/alloc_contig_range") -int BPF_KRETPROBE(alloc_contig_range) -{ - u32 pid = bpf_get_current_pid_tgid(); - u64 tm = bpf_ktime_get_ns(); - u64 *tsp = bpf_map_lookup_elem(&time_map, &pid); - - if (tsp) - tm -= *tsp; - else - return 1; - - unsigned key = tm / 10000000; - if (key > INTERVAL_MAX - 1) - key = INTERVAL_MAX - 1; - - u64 *value = bpf_map_lookup_elem(&count_map, &key); - if (value) - *value += 1; - else { - u64 init_value = 1; - bpf_map_update_elem(&count_map, &key, &init_value, BPF_ANY); - } - - bpf_map_delete_elem(&time_map, &pid); - - return 0; -} diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.c b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.c deleted file mode 100644 index cecf5bc82..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -//#include -#include "cma_monitor.h" -#include "cma_monitor.skel.h" - -#define INTERVAL_MAX 6U - -int main(int argc, char **argv) -{ - /* - char file_name[200]; - - snprintf(file_name, sizeof(file_name), "%s_kern.o", argv[0]); - if (load_bpf_file(file_name)) { - printf("%s", bpf_log_buf); - - return 1; - }*/ - struct cma_monitor_bpf *skel = cma_monitor_bpf__open_and_load(); - if (!skel) { - fprintf(stderr, "Failed to open BPF skeleton\n"); - return 1; - } - int fd = bpf_map__fd(skel->maps.time_map); - int key; - - for (;;) { - sleep(5); - - for (key = 0; key < INTERVAL_MAX; key++) { - unsigned long long value = 0; - bpf_map_lookup_elem(fd, &key, &value); - - if (key < INTERVAL_MAX - 1) - printf("Range %dms - %dms\tCount:%llu\n", - key * 10, (key + 1) * 10, value); - else - printf("Over 50ms\t\tCount:%llu\n", value); - } - - printf("=========================================\n"); - } - - return 0; -} diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.h b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.h deleted file mode 100644 index b9b3eddb1..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/cma/cma_monitor.h +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2022 Jacky Yin */ -#ifndef __CMA_MONITOR_H -#define __CMA_MONTOR_H - - - - - -#endif /* __CMA_MONTOR_H */ diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/Makefile b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/Makefile deleted file mode 100644 index e9e8ef726..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -OUTPUT := .output -CLANG ?= clang -LIBBPF_SRC := $(abspath ../libbpf-bootstrap/libbpf/src) -BPFTOOL_SRC := $(abspath ../libbpf-bootstrap/bpftool/src) -LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) -BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) -BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool - -ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ - | sed 's/arm.*/arm/' \ - | sed 's/aarch64/arm64/' \ - | sed 's/ppc64le/powerpc/' \ - | sed 's/mips.*/mips/' \ - | sed 's/riscv64/riscv/' \ - | sed 's/loongarch64/loongarch/') -VMLINUX := ../libbpf-bootstrap/vmlinux/$(ARCH)/vmlinux.h -# Use our own libbpf API headers and Linux UAPI headers distributed with -# libbpf to avoid dependency on system-wide headers, which could be missing or -# outdated -INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX)) -CFLAGS := -g -Wall -ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) - -APPS = ion_monitor - -# Get Clang's default includes on this system. We'll explicitly add these dirs -# to the includes list when compiling with `-target bpf` because otherwise some -# architecture-specific dirs will be "missing" on some architectures/distros - -# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, -# sys/cdefs.h etc. might be missing. -# -# Use '-idirafter': Don't interfere with include mechanics except where the -# build would have failed anyways. -CLANG_BPF_SYS_INCLUDES = $(shell $(CLANG) -v -E - &1 \ - | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') - -ifeq ($(V),1) - Q = - msg = -else - Q = @ - msg = @printf ' %-8s %s%s\n' \ - "$(1)" \ - "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ - "$(if $(3), $(3))"; - MAKEFLAGS += --no-print-directory -endif - -define allow-override - $(if $(or $(findstring environment,$(origin $(1))),\ - $(findstring command line,$(origin $(1)))),,\ - $(eval $(1) = $(2))) -endef - -$(call allow-override,CC,$(CROSS_COMPILE)cc) -$(call allow-override,LD,$(CROSS_COMPILE)ld) - -.PHONY: all -all: $(APPS) - -.PHONY: clean -clean: - $(call msg,CLEAN) - $(Q)rm -rf $(OUTPUT) $(APPS) - -$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): - $(call msg,MKDIR,$@) - $(Q)mkdir -p $@ - -# Build libbpf -$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf - $(call msg,LIB,$@) - $(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ - OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ - INCLUDEDIR= LIBDIR= UAPIDIR= \ - install - -# Build bpftool -$(BPFTOOL): | $(BPFTOOL_OUTPUT) - $(call msg,BPFTOOL,$@) - $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap - -# Build BPF code -$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) - $(call msg,BPF,$@) - $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ - $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ - -c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) - $(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) - -# Generate BPF skeletons -$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) - $(call msg,GEN-SKEL,$@) - $(Q)$(BPFTOOL) gen skeleton $< > $@ - -# Build user-space code -$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h - -$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) - $(call msg,CC,$@) - $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ - -# Build application binary -$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) - $(call msg,BINARY,$@) - $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ - -# delete failed targets -.DELETE_ON_ERROR: - -# keep intermediate (.skel.h, .bpf.o, etc) targets -.SECONDARY: - diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.bpf.c b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.bpf.c deleted file mode 100644 index e91936618..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.bpf.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "vmlinux.h" -#include -#include -#include -#include "ion_monitor.h" - -#define INTERVAL_MAX 6U - -char LICENSE[] SEC("license") = "Dual BSD/GPL"; -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 8192); - __type(key, unsigned); - __type(value, u64); -} count_map SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 8192); - __type(key, u32); - __type(value, u64); -} time_map SEC(".maps"); - -SEC("kprobe/ion_alloc") -int bpf_prog1(void *ctx) -{ - u32 pid = bpf_get_current_pid_tgid() >> 32; - u64 time = bpf_ktime_get_ns(); - u64 ts = bpf_ktime_get_ns(); - bpf_map_update_elem(&time_map, &pid, &ts, BPF_ANY); - - return 0; -} - -SEC("kprobe/ion_ioctl") -int bpf_prog2(void *ctx) -{ - u32 pid = bpf_get_current_pid_tgid() >> 32; - u64 tm = bpf_ktime_get_ns(); - - u64 *tsp = bpf_map_lookup_elem(&time_map, &pid); - if (tsp) - tm -= *tsp; - else - return -1; - - unsigned key = tm / 10000000;//10ms为区间单位 - if (key > INTERVAL_MAX - 1) - key = INTERVAL_MAX - 1; - u64 *value = bpf_map_lookup_elem(&count_map,&key); - if (value) { - *value += 1; - } else { - u64 init_value = 1; - bpf_map_update_elem(&count_map, &key, &init_value, BPF_ANY); - } - - bpf_map_delete_elem(&time_map, &pid); - - return 0; -} - -char _license[] SEC("license") = "GPL"; diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.c b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.c deleted file mode 100644 index d22a7e004..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -//#include -#include "ion_monitor.h" -#include "ion_monitor.skel.h" -#include - - - -#define INTERVAL_MAX 6U -int main(int argc, char **argv) -{ - /* - char file_name[200]; - - snprintf(file_name, sizeof(file_name), "%s_kern.o", argv[0]); - if (load_bpf_file(file_name)) { - printf("%s", bpf_log_buf); - - return 1; - }*/ - struct ion_monitor_bpf *skel = ion_monitor_bpf__open_and_load(); - if (!skel) { - fprintf(stderr, "Failed to open BPF skeleton\n"); - return 1; - } - - int fd = bpf_map__fd(skel->maps.time_map); - int key; - - for(;;) { - sleep(10); - - for (key = 0; key < INTERVAL_MAX; key++) { - unsigned long long value = 0; - bpf_map_lookup_elem(fd, &key, &value); - if (key < INTERVAL_MAX - 1) - printf("Range %dms - %dms\tCount:%llu\n", - key * 10, (key + 1) * 10, value); - else - printf("Over 50ms\t\tCount:%llu\n", value); - } - - printf("==========================================\n"); - } - - return 0; -} - - - - diff --git a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.h b/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.h deleted file mode 100644 index e6712713e..000000000 --- a/eBPF_Supermarket/Memory_Subsystem/old_project/mem_watcher/page_fault/ion/ion_monitor.h +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2022 Jacky Yin */ -#ifndef __ION_MONITOR_H -#define __ION_MONITOR_H - - - - - -#endif /* __ION_MONTOR_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.mod b/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.mod index 7eb67acb7..2c47343f5 100644 --- a/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.mod +++ b/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.mod @@ -68,11 +68,11 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.sum b/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.sum index eca8135ef..101946f56 100644 --- a/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.sum +++ b/eBPF_Supermarket/Network_Subsystem/TrafficManager/go.sum @@ -468,8 +468,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -544,11 +544,11 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.1-0.20230616193735-e0c3b6e6ae3b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h index 8ea57deb1..1c8ab5303 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h @@ -202,7 +202,7 @@ struct { const volatile int filter_dport = 0; const volatile int filter_sport = 0; const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0, - layer_time = 0, http_info = 0, retrans_info = 0, udp_info =0,net_filter = 0,kfree_info = 0,icmp_info = 0 ,tcp_info = 0; + layer_time = 0, http_info = 0, retrans_info = 0, udp_info =0,net_filter = 0,drop_reason = 0,icmp_info = 0 ,tcp_info = 0; /* help macro */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h index 1eb219c06..6d149791d 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/drop.bpf.h @@ -18,7 +18,7 @@ static __always_inline int __tp_kfree(struct trace_event_raw_kfree_skb *ctx) { - if(!kfree_info) + if(!drop_reason) return 0; struct sk_buff *skb=ctx->skbaddr; if (skb == NULL) // 判断是否为空 diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c index c5fca5b48..ca85fa5cd 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.c @@ -16,6 +16,7 @@ // // netwatcher libbpf 用户态代码 + #include "netwatcher.h" #include "netwatcher.skel.h" #include @@ -29,6 +30,7 @@ #include #include #include +#include #include "dropreason.h" static volatile bool exiting = false; @@ -40,7 +42,7 @@ static char udp_file_path[1024]; static int sport = 0, dport = 0; // for filter static int all_conn = 0, err_packet = 0, extra_conn_info = 0, layer_time = 0, - http_info = 0, retrans_info = 0, udp_info = 0,net_filter = 0,kfree_info = 0,addr_to_func=0 ,icmp_info = 0 , tcp_info = 0; // flag + http_info = 0, retrans_info = 0, udp_info = 0,net_filter = 0,drop_reason = 0,addr_to_func=0 ,icmp_info = 0 , tcp_info = 0; // flag static const char* tcp_states[] = { [1] = "ESTABLISHED", [2] = "SYN_SENT", [3] = "SYN_RECV", @@ -63,10 +65,11 @@ static const struct argp_option opts[] = { {"dport", 'd', "DPORT", 0, "trace this destination port only"}, {"udp", 'u', 0, 0, "trace the udp message"}, {"net_filter",'n',0,0,"trace ipv4 packget filter "}, - {"kfree_info",'k',0,0,"trace kfree "}, + {"drop_reason",'k',0,0,"trace kfree "}, {"addr_to_func",'T',0,0,"translation addr to func and offset"}, {"icmptime", 'I', 0, 0, "set to trace layer time of icmp"}, {"tcpstate", 'S', 0, 0, "set to trace tcpstate"}, + {}}; static error_t parse_arg(int key, char *arg, struct argp_state *state) { @@ -103,7 +106,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { net_filter = 1; break; case 'k': - kfree_info = 1; + drop_reason = 1; break; case 'T': addr_to_func = 1; @@ -130,12 +133,62 @@ struct SymbolEntry{ unsigned long addr; char name[30]; }; + struct SymbolEntry symbols[300000]; int num_symbols = 0; +//定义快表 +#define CACHEMAXSIZE 5 +struct SymbolEntry cache[CACHEMAXSIZE]; +int cache_size = 0; +//LRU算法查找函数 +struct SymbolEntry find_in_cache(unsigned long int addr) +{ + // 查找地址是否在快表中 + for (int i = 0; i < cache_size; i++) { + if (cache[i].addr == addr) { + // 更新访问时间 + struct SymbolEntry temp = cache[i]; + // 将访问的元素移动到快表的最前面,即最近使用的位置 + for (int j = i; j > 0; j--) { + cache[j] = cache[j - 1]; + } + cache[0] = temp; + return temp; + } + } + // 如果地址不在快表中,则返回空 + struct SymbolEntry empty_entry; + empty_entry.addr = 0; + return empty_entry; +} + +// 将新的符号条目加入快表 +void add_to_cache(struct SymbolEntry entry) { + // 如果快表已满,则移除最久未使用的条目 + if (cache_size == CACHEMAXSIZE) { + for (int i = cache_size - 1; i > 0; i--) { + cache[i] = cache[i - 1]; + } + cache[0] = entry; + } else { + // 否则,直接加入快表 + for (int i = cache_size; i > 0; i--) { + cache[i] = cache[i - 1]; + } + cache[0] = entry; + cache_size++; + } +} + struct SymbolEntry findfunc(unsigned long int addr) { - int low = 0, high = num_symbols - 1; - int result = -1; + // 先在快表中查找 + struct SymbolEntry entry = find_in_cache(addr); + if (entry.addr != 0) { + return entry; + } + unsigned long long low = 0, high = num_symbols - 1; + unsigned long long result = -1; while (low <= high) { int mid = low + (high - low) / 2; @@ -146,9 +199,10 @@ struct SymbolEntry findfunc(unsigned long int addr) high = mid - 1; } } - + add_to_cache(symbols[result]); return symbols[result]; }; + void readallsym() { FILE *file = fopen("/proc/kallsyms", "r"); @@ -170,6 +224,7 @@ void readallsym() fclose(file); } + static void sig_handler(int signo) { exiting = true; } static void bytes_to_str(char *str, unsigned long long num) { @@ -212,7 +267,8 @@ static int print_conns(struct netwatcher_bpf *skel) { char s_ip_port_str[INET6_ADDRSTRLEN + 6]; char d_ip_port_str[INET6_ADDRSTRLEN + 6]; - + if((d.saddr & 0x0000FFFF) == 0x0000007F || (d.daddr & 0x0000FFFF) == 0x0000007F) + return 0; if (d.family == AF_INET) { sprintf(s_ip_port_str, "%s:%d", inet_ntop(AF_INET, &d.saddr, s_str, sizeof(s_str)), @@ -274,9 +330,23 @@ static int print_conns(struct netwatcher_bpf *skel) { } static int print_packet(void *ctx, void *packet_info, size_t size) { - if (udp_info || net_filter || kfree_info || icmp_info || tcp_info) + if (udp_info || net_filter || drop_reason || icmp_info || tcp_info) return 0; const struct pack_t *pack_info = packet_info; + char d_str[INET_ADDRSTRLEN]; + char s_str[INET_ADDRSTRLEN]; + unsigned int saddr = pack_info->saddr; + unsigned int daddr = pack_info->daddr; + if((daddr & 0x0000FFFF) == 0x0000007F || (saddr & 0x0000FFFF) == 0x0000007F) + return 0; + if (dport) + if (pack_info->dport != dport) + return 0; + + if (sport) + if (pack_info->sport!= sport) + return 0; + if (pack_info->err) { FILE *file = fopen(err_file_path, "a"); char reason[20]; @@ -314,28 +384,33 @@ static int print_packet(void *ctx, void *packet_info, size_t size) { sprintf(http_data, "-"); } if (layer_time) { - printf("%-22p %-10u %-10u %-10llu %-10llu %-10llu %-5d %s\n", - pack_info->sock, pack_info->seq, pack_info->ack, + printf("%-22p %-20s %-8d %-20s %-8d %-10llu %-10llu %-10llu %-5d %-10s\n", + pack_info->sock,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),pack_info->sport, + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),pack_info->dport, pack_info->mac_time, pack_info->ip_time, pack_info->tran_time, pack_info->rx, http_data); fprintf( file, - "packet{sock=\"%p\",seq=\"%u\",ack=\"%u\"," + "packet{sock=\"%p\",saddr=\"%s\",sport=\"%d\",daddr=\"%s\",dport=\"%d\",seq=\"%u\",ack=\"%u\"," "mac_time=\"%llu\",ip_time=\"%llu\",tran_time=\"%llu\",http_" "info=\"%s\",rx=\"%d\"} \n", - pack_info->sock, pack_info->seq, pack_info->ack, - pack_info->mac_time, pack_info->ip_time, pack_info->tran_time, - http_data, pack_info->rx); + pack_info->sock,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),pack_info->sport, + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),pack_info->dport, + pack_info->seq, pack_info->ack, + pack_info->mac_time, pack_info->ip_time, + pack_info->tran_time,http_data, pack_info->rx); } else { - printf("%-22p %-10u %-10u %-10d %-10d %-10d %-5d %s\n", - pack_info->sock, pack_info->seq, pack_info->ack, 0, 0, 0, - pack_info->rx, http_data); - fprintf(file, - "packet{sock=\"%p\",seq=\"%u\",ack=\"%u\"," - "mac_time=\"%d\",ip_time=\"%d\",tran_time=\"%d\",http_" - "info=\"%s\",rx=\"%d\"} \n", - pack_info->sock, pack_info->seq, pack_info->ack, 0, 0, 0, - http_data, pack_info->rx); + printf("%-22p %-20s %-8d %-20s %-8d %-10d %-10d %-10d %-5d %-10s\n", + pack_info->sock,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),pack_info->sport, + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),pack_info->dport,0,0,0, pack_info->rx, http_data); + fprintf( + file, + "packet{sock=\"%p\",saddr=\"%s\",sport=\"%d\",daddr=\"%s\",dport=\"%d\",seq=\"%u\",ack=\"%u\"," + "mac_time=\"%d\",ip_time=\"%d\",tran_time=\"%d\",http_" + "info=\"%s\",rx=\"%d\"} \n", + pack_info->sock,inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)),pack_info->sport, + inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)),pack_info->dport, + pack_info->seq, pack_info->ack,0,0,0,http_data, pack_info->rx); } fclose(file); } @@ -354,7 +429,10 @@ static int print_udp(void *ctx, void *packet_info, size_t size) { const struct udp_message *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - printf("%-20s %-20s %-20u %-20u %-20llu %-20d %-20d\n", + if((daddr & 0x0000FFFF) == 0x0000007F || (saddr & 0x0000FFFF) == 0x0000007F) + return 0; + + printf("%-20s %-20s %-20u %-20u %-20llu %-20d %-20d", inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, pack_info->dport, pack_info->tran_time,pack_info->rx,pack_info->len); @@ -365,8 +443,9 @@ static int print_udp(void *ctx, void *packet_info, size_t size) { inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport, pack_info->dport, pack_info->tran_time,pack_info->rx,pack_info->len); - fclose(file); + printf("\n"); + return 0; } @@ -378,7 +457,9 @@ static int print_netfilter(void *ctx, void *packet_info, size_t size) { const struct netfilter *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - printf("%-20s %-20s %-20d %-20d %-20lld %-20lld %-20lld %-20lld %-20lld %-20d\n", + if((daddr & 0x0000FFFF) == 0x0000007F || (saddr & 0x0000FFFF) == 0x0000007F) + return 0; + printf("%-20s %-20s %-12d %-12d %-8lld %-8lld% -8lld %-8lld %-8lld %-8d\n", inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport,pack_info->dport, @@ -388,11 +469,9 @@ static int print_netfilter(void *ctx, void *packet_info, size_t size) { pack_info->post_routing_time, pack_info->local_out_time, pack_info->rx); - return 0; } - static int print_tcpstate(void *ctx, void *packet_info, size_t size) { if(!tcp_info) return 0; @@ -410,7 +489,7 @@ static int print_tcpstate(void *ctx, void *packet_info, size_t size) { } static int print_kfree(void *ctx, void *packet_info, size_t size) { - if(!kfree_info) + if(!drop_reason) return 0; char d_str[INET_ADDRSTRLEN]; char s_str[INET_ADDRSTRLEN]; @@ -434,14 +513,19 @@ static int print_kfree(void *ctx, void *packet_info, size_t size) { // 其他协议 strcpy(prot, "other"); } - printf("%-20s %-20s %-10u %-10u %-10s", + time_t now = time(NULL); + struct tm *localTime = localtime(&now); + printf("%02d:%02d:%02d %-17s %-17s %-10u %-10u %-10s", + localTime->tm_hour, localTime->tm_min, localTime->tm_sec, inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->sport,pack_info->dport,prot); if(!addr_to_func) - printf("%-20lx",pack_info->location); + printf("%-34lx",pack_info->location); else { struct SymbolEntry data= findfunc(pack_info->location); - printf("%s+0x%-10lx",data.name,pack_info->location-data.addr); + char result[40]; + sprintf(result, "%s+0x%lx", data.name, pack_info->location - data.addr); + printf("%-34s",result); } printf("%s\n", SKB_Drop_Reason_Strings[pack_info->drop_reason]); return 0; @@ -455,13 +539,14 @@ static int print_icmptime(void *ctx, void *packet_info, size_t size) { const struct icmptime *pack_info = packet_info; unsigned int saddr = pack_info->saddr; unsigned int daddr = pack_info->daddr; - printf("%-20s %-20s %-10lld %-10d\n", + printf("%-20s %-20s %-12lld %-12d\n", inet_ntop(AF_INET, &saddr, s_str, sizeof(s_str)), inet_ntop(AF_INET, &daddr, d_str, sizeof(d_str)), pack_info->icmp_tran_time, pack_info->flag); return 0; } + int main(int argc, char **argv) { char *last_slash = strrchr(argv[0], '/'); if (last_slash) { @@ -512,9 +597,9 @@ int main(int argc, char **argv) { skel->rodata->retrans_info = retrans_info; skel->rodata->udp_info = udp_info; skel->rodata->net_filter = net_filter; - skel->rodata->kfree_info = kfree_info; skel->rodata->tcp_info = tcp_info; skel->rodata->icmp_info = icmp_info; + skel->rodata->drop_reason = drop_reason; if(addr_to_func) readallsym(); @@ -537,24 +622,24 @@ int main(int argc, char **argv) { } else if(net_filter) { - printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s\n", "saddr", "daddr","dprot", "sprot", + printf("%-20s %-20s %-12s %-12s %-8s %-8s %-7s %-8s %-8s %-8s\n", "saddr", "daddr","dprot", "sprot", "PreRT","L_IN","FW","PostRT","L_OUT","rx"); } - else if(kfree_info) + else if(drop_reason) { - printf("%-20s %-20s %-10s %-10s %-9s %-24s %-25s\n", "saddr", "daddr","sprot", "dprot","prot","addr","reason"); + printf("%-13s %-17s %-17s %-10s %-10s %-9s %-33s %-30s\n", "time","saddr", "daddr","sprot", "dprot","prot","addr","reason"); } else if(icmp_info) { - printf("%-20s %-20s %-10s %-10s\n", "saddr", "daddr","time","flag"); + printf("%-20s %-20s %-12s %-12s\n", "saddr", "daddr","time","flag"); } else if(tcp_info) { printf("%-20s %-20s %-20s %-20s %-20s %-20s %-20s \n", "saddr", "daddr","sport","dport","oldstate","newstate","time"); } else{ - printf("%-22s %-10s %-10s %-10s %-10s %-10s %-5s %s\n", "SOCK", "SEQ", - "ACK", "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); + printf("%-22s %-20s %-8s %-20s %-8s %-10s %-10s %-10s %-5s %-10s \n", "SOCK","Saddr","Sport","Daddr","Dport", + "MAC_TIME", "IP_TIME", "TRAN_TIME", "RX", "HTTP"); } udp_rb =ring_buffer__new(bpf_map__fd(skel->maps.udp_rb), print_udp, NULL, NULL); if (!udp_rb) { @@ -586,12 +671,6 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to create ring buffer(tcp)\n"); goto cleanup; } - icmp_rb =ring_buffer__new(bpf_map__fd(skel->maps.icmp_rb), print_icmptime, NULL, NULL); - if (!icmp_rb) { - err = -1; - fprintf(stderr, "Failed to create ring buffer(icmp)\n"); - goto cleanup; - } /* Set up ring buffer polling */ rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), print_packet, NULL, NULL); if (!rb) { diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h index c0955a298..9b5de4e0e 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/netwatcher.h @@ -88,6 +88,13 @@ struct pack_t { u8 data[MAX_HTTP_HEADER]; // 用户层数据 const void *sock; // 此包tcp连接的 socket 指针 int rx; // rx packet(1) or tx packet(0) + u32 saddr; + u32 daddr; + unsigned __int128 saddr_v6; + unsigned __int128 daddr_v6; + u16 sport; + u16 dport; + }; struct udp_message { diff --git a/eBPF_Supermarket/Network_Subsystem/net_watcher/packet.bpf.h b/eBPF_Supermarket/Network_Subsystem/net_watcher/packet.bpf.h index e3adf22a4..5808a2c66 100644 --- a/eBPF_Supermarket/Network_Subsystem/net_watcher/packet.bpf.h +++ b/eBPF_Supermarket/Network_Subsystem/net_watcher/packet.bpf.h @@ -276,6 +276,10 @@ int __skb_copy_datagram_iter(struct sk_buff *skb) // bpf_printk("rx enter app layer.\n"); PACKET_INIT_WITH_COMMON_INFO + packet->saddr = pkt_tuple.saddr; + packet->daddr = pkt_tuple.daddr; + packet->sport = pkt_tuple.sport; + packet->dport = pkt_tuple.dport; if (layer_time) { packet->mac_time = tinfo->ip_time - tinfo->mac_time; @@ -545,7 +549,12 @@ int __dev_hard_start_xmit(struct sk_buff *skb) if (!sk) { return 0; } + PACKET_INIT_WITH_COMMON_INFO + packet->saddr = pkt_tuple.saddr; + packet->daddr = pkt_tuple.daddr; + packet->sport = pkt_tuple.sport; + packet->dport = pkt_tuple.dport; // 记录各层的时间差值 if (layer_time) { packet->tran_time = tinfo->ip_time - tinfo->tran_time; diff --git a/eBPF_Supermarket/Stack_Analyser/Makefile b/eBPF_Supermarket/Stack_Analyser/Makefile index 132bb1c85..37cbf813e 100644 --- a/eBPF_Supermarket/Stack_Analyser/Makefile +++ b/eBPF_Supermarket/Stack_Analyser/Makefile @@ -115,18 +115,16 @@ $(BPF_SKEL)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) $(BPF_SKEL) $(call msg,GEN-SKEL,$@) $(Q)$(BPFTOOL) gen skeleton $< > $@ -$(patsubst %,include/bpf_wapper/%.h,$(BPF)): include/bpf_wapper/%.h: $(BPF_SKEL)/%.skel.h - -$(patsubst %,$(OUTPUT)/%.o,$(BPF)): $(OUTPUT)/%.o: src/bpf_wapper/%.cpp include/bpf_wapper/%.h $(OUTPUT)/eBPFStackCollector.o +$(patsubst %,$(OUTPUT)/%.o,$(BPF)): $(OUTPUT)/%.o: src/bpf_wapper/%.cpp include/bpf_wapper/%.h $(BPF_SKEL)/%.skel.h $(OUTPUT)/eBPFStackCollector.o $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ # Build depending library -$(patsubst %,$(OUTPUT)/%.o,$(BIN)): $(OUTPUT)/%.o: src/%.cpp $(patsubst %,include/bpf_wapper/%.h,$(BPF)) +$(patsubst %,$(OUTPUT)/%.o,$(BIN)): $(OUTPUT)/%.o: src/%.cpp $(patsubst %,$(BPF_SKEL)/%.skel.h,$(BPF)) $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ -$(OUTPUT)/eBPFStackCollector.o: src/bpf_wapper/eBPFStackCollector.cpp | $(LIBBPF_OBJ) +$(OUTPUT)/eBPFStackCollector.o: src/bpf_wapper/eBPFStackCollector.cpp include/bpf_wapper/eBPFStackCollector.h | $(LIBBPF_OBJ) $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c index 65a9a60a7..328c9c448 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c @@ -27,20 +27,27 @@ COMMON_MAPS(io_tuple); COMMON_VALS; -const volatile int target_pid = 0; const char LICENSE[] SEC("license") = "GPL"; static int do_stack(struct trace_event_raw_sys_enter *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk - RET_IF_KERN(curr); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); // record time delta psid apsid = GET_COUNT_KEY(pid, ctx); diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c index 89c444690..d14f8922f 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c @@ -31,12 +31,21 @@ COMMON_VALS; static __always_inline int trace_event(__u64 sample_period, bool miss, struct bpf_perf_event_data *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid - if (!pid || pid == self_pid) + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) return 0; - SAVE_TASK_INFO(pid, curr); + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + return 0; + + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); llc_stat *infop = bpf_map_lookup_elem(&psid_count_map, &apsid); if (!infop) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c index 239a7edba..edf090a41 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c @@ -27,7 +27,6 @@ COMMON_MAPS(union combined_alloc_info); COMMON_VALS; -const volatile __u64 sample_rate = 1; const volatile bool wa_missing_free = false; const volatile size_t page_size = 4096; const volatile bool trace_all = false; @@ -41,21 +40,24 @@ const char LICENSE[] SEC("license") = "GPL"; static int gen_alloc_enter(size_t size) { CHECK_ACTIVE; - if (!size) + CHECK_FREQ; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) return 0; - if (sample_rate > 1) { - if (bpf_ktime_get_ns() % sample_rate != 0) + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) return 0; } - struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); - // update group - // group share memory u32 tgid = BPF_CORE_READ(curr, tgid); - if (tgid == self_pid) + if (target_tgid > 0 && tgid != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(tgid, curr); + + SAVE_TASK_INFO(tgid, curr, knode); if (trace_all) bpf_printk("alloc entered, size = %lu\n", size); // record size diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c index 10445e9db..b79e894fb 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c @@ -27,7 +27,6 @@ COMMON_MAPS(u32); COMMON_VALS; -const volatile int target_pid = 0; BPF_HASH(pid_offTs_map, u32, u64); // 记录进程运行的起始时间 const char LICENSE[] SEC("license") = "GPL"; @@ -36,18 +35,42 @@ SEC("kprobe/finish_task_switch") // 动态挂载点finish_task_switch.isra.0 int BPF_KPROBE(do_stack, struct task_struct *curr) { CHECK_ACTIVE; - u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获取换出进程tsk的pid - RET_IF_KERN(curr); - if ((target_pid >= 0 && pid == target_pid) || (target_pid < 0 && pid && pid != self_pid)) + do { + if (freq) + { + __next_n = ((bpf_ktime_get_ns() & ((1ul << 30) - 1)) * freq) >> 30; + if (__last_n == __next_n) + { + if (__recorded) + break; + } + else + __last_n = __next_n; + } + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + break; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + break; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + break; + { + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + break; + } + // record curr block time u64 ts = bpf_ktime_get_ns(); // ts=当前的时间戳(ns) bpf_map_update_elem(&pid_offTs_map, &pid, &ts, BPF_NOEXIST); // 如果start表中不存在pid对应的时间,则就创建pid-->ts - } + __recorded = true; + } while (false); // calculate time delta, next ready to run struct task_struct *next = (struct task_struct *)bpf_get_current_task(); // next指向换入进程结构体 - pid = BPF_CORE_READ(next, pid); // 利用帮助函数获取next指向的tsk的pid + u32 pid = BPF_CORE_READ(next, pid); // 利用帮助函数获取next指向的tsk的pid u64 *tsp = bpf_map_lookup_elem(&pid_offTs_map, &pid); // tsp指向start表中的pid的值 if (!tsp) return 0; @@ -57,7 +80,10 @@ int BPF_KPROBE(do_stack, struct task_struct *curr) return 0; // record data - SAVE_TASK_INFO(pid, next); + { + SET_KNODE(next, knode); + SAVE_TASK_INFO(pid, next, knode); + } psid apsid = GET_COUNT_KEY(pid, ctx); // record time delta diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c index 7830850ad..642965b45 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c @@ -34,11 +34,17 @@ int do_stack(void *ctx) { CHECK_ACTIVE; struct task_struct *curr = (void *)bpf_get_current_task(); // curr指向当前进程的tsk - RET_IF_KERN(curr); // 忽略内核线程 - u32 pid = BPF_CORE_READ(curr, pid); // pid保存当前进程的pid,是cgroup pid 对应的level 0 pid - if (!pid || pid == self_pid) + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) return 0; - SAVE_TASK_INFO(pid, curr); + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + return 0; + + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); // add cosunt diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index 65706ad64..258f4158f 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: GaoYixiang +// author: luiyanbing@foxmail.com // -// 内核态eBPF的通用的调用栈计数代码 +// 内核态bpf程序的模板代码 #include "vmlinux.h" #include @@ -23,53 +23,97 @@ #include #include "sa_ebpf.h" +#include "bpf_wapper/probe.h" #include "task.h" -COMMON_MAPS(u32); +COMMON_MAPS(time_tuple); COMMON_VALS; -const volatile int target_pid = 0; +BPF_HASH(starts, u32, u64); -const char LICENSE[] SEC("license") = "GPL"; - -static int handle_func(void *ctx) +static int entry(void *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk - RET_IF_KERN(curr); - u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); + + u64 nsec = bpf_ktime_get_ns(); + bpf_map_update_elem(&starts, &pid, &nsec, BPF_ANY); + return 0; +} + +SEC("kprobe/dummy_kprobe") +int BPF_KPROBE(dummy_kprobe) +{ + entry(ctx); + return 0; +} +SEC("tp/sched/dummy_tp") +int tp_entry(void *ctx) +{ + entry(ctx); + return 0; +} +SEC("usdt") +int usdt_entry(void *ctx) +{ + entry(ctx); + return 0; +} +static int exit(void *ctx) +{ + CHECK_ACTIVE; + u32 pid = bpf_get_current_pid_tgid() >> 32; + + u64 *start = bpf_map_lookup_elem(&starts, &pid); + if (!start) + return 0; + + u64 delta = bpf_ktime_get_ns() - *start; psid a_psid = GET_COUNT_KEY(pid, ctx); - u32 *cnt = bpf_map_lookup_elem(&psid_count_map, &a_psid); - if (!cnt) + time_tuple *d = bpf_map_lookup_elem(&psid_count_map, &a_psid); + if (!d) { - u32 ONE = 1; - bpf_map_update_elem(&psid_count_map, &a_psid, &ONE, BPF_NOEXIST); + time_tuple tmp = {.lat = delta, .count = 1}; + bpf_map_update_elem(&psid_count_map, &a_psid, &tmp, BPF_NOEXIST); } else - (*cnt)++; - + { + d->lat += delta; + d->count++; + } return 0; } -SEC("kprobe/dummy_kprobe") -int BPF_KPROBE(handle) +SEC("kretprobe/dummy_kretprobe") +int BPF_KRETPROBE(dummy_kretprobe) { - handle_func(ctx); + exit(ctx); return 0; } SEC("tp/sched/dummy_tp") -int handle_tp(void *ctx) +int tp_exit(void *ctx) { - handle_func(ctx); + exit(ctx); return 0; } SEC("usdt") -int handle_usdt(void *ctx) +int usdt_exit(void *ctx) { - return handle_func(ctx); -} \ No newline at end of file + exit(ctx); + return 0; +} +const char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c index 59c390076..c9fc3c3c3 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c @@ -31,7 +31,6 @@ COMMON_MAPS(ra_tuple); COMMON_VALS; -int target_pid = 0; BPF_HASH(in_ra_map, u32, psid); BPF_HASH(page_psid_map, struct page *, psid); @@ -39,14 +38,21 @@ SEC("fentry/page_cache_ra_unbounded") // fentry在内核函数page_cache_ra_unbo int BPF_PROG(page_cache_ra_unbounded) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); - u32 pid = get_task_ns_pid(curr); // 获取当前进程tgid,用户空间的pid即是tgid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); ra_tuple *d = bpf_map_lookup_elem(&psid_count_map, &apsid); // d指向psid_count表中的apsid对应的类型为tuple的值 diff --git a/eBPF_Supermarket/Stack_Analyser/exporter/go.mod b/eBPF_Supermarket/Stack_Analyser/exporter/go.mod index f60204a30..f88156d40 100644 --- a/eBPF_Supermarket/Stack_Analyser/exporter/go.mod +++ b/eBPF_Supermarket/Stack_Analyser/exporter/go.mod @@ -9,6 +9,7 @@ require ( github.com/grafana/pyroscope/api v0.3.0 github.com/grafana/pyroscope/ebpf v0.4.1 github.com/prometheus/common v0.46.0 + github.com/prometheus/prometheus v0.48.0 github.com/samber/lo v1.39.0 ) @@ -27,11 +28,10 @@ require ( github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/prometheus/prometheus v0.48.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/net v0.20.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect diff --git a/eBPF_Supermarket/Stack_Analyser/exporter/go.sum b/eBPF_Supermarket/Stack_Analyser/exporter/go.sum index 6a152515a..e94fad505 100644 --- a/eBPF_Supermarket/Stack_Analyser/exporter/go.sum +++ b/eBPF_Supermarket/Stack_Analyser/exporter/go.sum @@ -62,13 +62,13 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/eBPF_Supermarket/Stack_Analyser/exporter/main.go b/eBPF_Supermarket/Stack_Analyser/exporter/main.go index 66a074f54..f81dbb098 100644 --- a/eBPF_Supermarket/Stack_Analyser/exporter/main.go +++ b/eBPF_Supermarket/Stack_Analyser/exporter/main.go @@ -292,6 +292,7 @@ func CollectProfiles(cb CollectProfilesCallback) error { for i, s := range scales { target := sd.NewTarget("", k.pid, sd.DiscoveryTarget{ "__container_id__": info[k.pid].cid, + "service_name": "Stack_Analyzer", labels.MetricName: s.Type, }) cb(target, group_trace, v[i], s, true) diff --git "a/eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" b/eBPF_Supermarket/Stack_Analyser/frame-use-guide.md similarity index 87% rename from "eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" rename to eBPF_Supermarket/Stack_Analyser/frame-use-guide.md index 2f393cbd5..8d829a678 100644 --- "a/eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" +++ b/eBPF_Supermarket/Stack_Analyser/frame-use-guide.md @@ -32,18 +32,18 @@ new_ebpf.sh 1. 实现包装类初始化函数,若数据标度`scale`的值可以确定,请在此初始化 2. 若标度无法确定,则实现`setScale`,对标度及包装类参数进行设置 -3. 实现一系列虚函数:`count_value, load, attach, detach, unload` +3. 实现一系列虚函数:`count_values, load, attach, detach, unload` 4. 可实现一些辅助函数 ## src/bpf/.bpf.c -1. 通过修改`DeclareCommonMaps(__u32)`中的`__u32`设置计数变量类型 +1. 通过修改`COMMON_MAPS(__u32)`中的`__u32`设置计数变量类型 2. 可声明额外的map和全局变量在eBPF程序内部使用,但不会被框架输出。 3. 实现eBPF程序,请使用通用的`eBPF map`进行数据存储,使用通用的全局变量进行进程和数据过滤,否则无法正确输出数据 通用的map分别为: - 1. psid_count:键为psid类型,值为 1. 中设置的计数变量类型 - 2. stack_trace:键为uint32类型,标识唯一的栈嗲用路径,值为void*[]类型,存储栈上的调用地址 + 1. psid_count_map:键为psid类型,值为 1. 中设置的计数变量类型 + 2. sid_trace_map:键为uint32类型,标识唯一的栈嗲用路径,值为void*[]类型,存储栈上的调用地址 3. pid_tgid:键为uint32类型,表示pid,值为uint32类型,表示tgid 4. pid_comm:键为uint32类型,表示pid,值为comm类型,表示进程名 diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h index 08bf2cb04..01d989367 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h @@ -58,8 +58,12 @@ class StackCollector public: Scale *scales; - int pid = -1; // 用于设置ebpf程序跟踪的pid - int err = 0; // 用于保存错误代码 + uint32_t top = 10; + uint32_t freq = 49; + uint64_t cgroup = 0; + uint32_t tgid = 0; + uint32_t pid = 0; // 用于设置ebpf程序跟踪的pid + int err = 0; // 用于保存错误代码 bool ustack = false; // 是否跟踪用户栈 bool kstack = false; // 是否跟踪内核栈 @@ -114,6 +118,10 @@ class StackCollector skel->rodata->trace_user = ustack; \ skel->rodata->trace_kernel = kstack; \ skel->rodata->self_pid = self_pid; \ + skel->rodata->target_pid = pid; \ + skel->rodata->target_tgid = tgid; \ + skel->rodata->target_cgroupid = cgroup; \ + skel->rodata->freq = freq; \ err = skel->load(skel); \ CHECK_ERR(err, "Fail to load BPF skeleton"); \ obj = skel->obj; \ diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h index 08afd79fb..544b3b7c6 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h @@ -60,7 +60,6 @@ class MemleakStackCollector : public StackCollector public: char *object = (char *)"libc.so.6"; bool percpu = false; - __u64 sample_rate = 1; bool wa_missing_free = false; protected: diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h index cd79dfccc..34f66be85 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h @@ -31,7 +31,6 @@ class OnCPUStackCollector : public StackCollector int *pefds = NULL; int num_cpus = 0; struct bpf_link **links = NULL; - unsigned long long freq = 49; protected: virtual uint64_t *count_values(void *); diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/probe.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/probe.h index 86e0b6182..78776dd28 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/probe.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/probe.h @@ -14,16 +14,29 @@ // // author: luiyanbing@foxmail.com // -// probe ebpf程序的包装类,声明接口和一些自定义方法 +// ebpf程序的包装类的模板,声明接口和一些自定义方法,以及辅助结构 -#include "bpf_wapper/eBPFStackCollector.h" +#ifndef _SA_PROBE_H__ +#define _SA_PROBE_H__ + +// ========== C code part ========== +#include +typedef struct +{ + __u64 lat; + __u64 count; +} time_tuple; +// ========== C code end ========== + +#ifdef __cplusplus +// ========== C++ code part ========== #include "probe.skel.h" +#include "bpf_wapper/eBPFStackCollector.h" class ProbeStackCollector : public StackCollector { private: - struct probe_bpf *skel = __null; - + DECL_SKEL(probe); public: std::string probe; @@ -40,3 +53,7 @@ class ProbeStackCollector : public StackCollector virtual void activate(bool tf); virtual const char *getName(void); }; +// ========== C++ code end ========== +#endif + +#endif \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_common.h b/eBPF_Supermarket/Stack_Analyser/include/sa_common.h index b5707d644..449f2f6c3 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_common.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_common.h @@ -35,7 +35,6 @@ typedef struct { typedef struct { __u32 pid; __u32 tgid; - char cid[CONTAINER_ID_LEN]; char comm[COMM_LEN]; } task_info; diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h index 433068353..925844796 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h @@ -22,13 +22,6 @@ #include "sa_common.h" #define PF_KTHREAD 0x00200000 -#define RET_IF_KERN(task) \ - do \ - { \ - int flags = BPF_CORE_READ(task, flags); \ - if (flags & PF_KTHREAD) \ - return 0; \ - } while (false) /// @brief 创建一个指定名字的ebpf调用栈表 /// @param 新栈表的名字 @@ -65,32 +58,61 @@ #define COMMON_MAPS(count_type) \ BPF_HASH(psid_count_map, psid, count_type); \ BPF_STACK_TRACE(sid_trace_map); \ + BPF_HASH(tgid_cgroup_map, __u32, \ + char[CONTAINER_ID_LEN]); \ BPF_HASH(pid_info_map, u32, task_info); #define COMMON_VALS \ const volatile bool trace_user = false; \ const volatile bool trace_kernel = false; \ - const volatile int self_pid = 0; \ - bool __active = false; + const volatile __u64 target_cgroupid = 0; \ + const volatile __u32 target_tgid = 0; \ + const volatile __u32 target_pid = 0; \ + const volatile __u32 self_pid = 0; \ + const volatile __u32 freq = 0; \ + bool __active = false; \ + __u32 __last_n = 0; \ + __u32 __next_n = 0; \ + bool __recorded = false; -#define CHECK_ACTIVE if(!__active) return 0; +#define CHECK_ACTIVE \ + if (!__active) \ + return 0; -#define SAVE_TASK_INFO(_pid, _task) \ +#define CHECK_FREQ \ + if (freq) \ + { \ + __next_n = ((bpf_ktime_get_ns() & ((1ul << 30) - 1)) * freq) >> 30; \ + if ((__last_n == __next_n) && __recorded) \ + return 0; \ + else \ + __last_n = __next_n; \ + } + +#define SET_KNODE(_task, _knode) \ + struct kernfs_node *_knode = BPF_CORE_READ(_task, cgroups, dfl_cgrp, kn); + +#define SAVE_TASK_INFO(_pid, _task, _knode) \ if (!bpf_map_lookup_elem(&pid_info_map, &_pid)) \ { \ - task_info info; \ + task_info info = {0}; \ info.pid = get_task_ns_pid(_task); \ bpf_get_current_comm(info.comm, COMM_LEN); \ - info.tgid = get_task_ns_tgid(_task); \ - fill_container_id(_task, info.cid); \ + info.tgid = BPF_CORE_READ(_task, tgid); \ bpf_map_update_elem(&pid_info_map, &_pid, &info, BPF_NOEXIST); \ + \ + char cgroup_name[CONTAINER_ID_LEN] = {0}; \ + fill_container_id(_knode, cgroup_name); \ + bpf_map_update_elem(&tgid_cgroup_map, &(info.tgid), \ + &cgroup_name, BPF_NOEXIST); \ } -#define GET_COUNT_KEY(_pid, _ctx) \ - ((psid){ \ - .pid = _pid, \ - .usid = trace_user ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) : -1, \ - .ksid = trace_kernel ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP) : -1, \ - }) +#define GET_COUNT_KEY(_pid, _ctx) \ + (__recorded == true, \ + (psid){ \ + .pid = _pid, \ + .usid = trace_user ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) : -1, \ + .ksid = trace_kernel ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP) : -1, \ + }) #endif \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/include/task.h b/eBPF_Supermarket/Stack_Analyser/include/task.h index 79f532543..db2e9b388 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/task.h +++ b/eBPF_Supermarket/Stack_Analyser/include/task.h @@ -71,13 +71,12 @@ statfunc u32 get_task_ns_ppid(struct task_struct *task) return get_task_pid_vnr(real_parent); } -static void fill_container_id(struct task_struct *task, char *container_id) +static void fill_container_id(struct kernfs_node *knode, char *container_id) { - struct kernfs_node *knode = BPF_CORE_READ(task, cgroups, subsys[0], cgroup, kn); if (BPF_CORE_READ(knode, parent) != NULL) { char *aus; - bpf_probe_read(&aus, sizeof(void *), &knode->name); + bpf_probe_read(&aus, sizeof(void *), &(knode->name)); bpf_probe_read_str(container_id, CONTAINER_ID_LEN, aus); } } diff --git a/eBPF_Supermarket/Stack_Analyser/new_bpf.sh b/eBPF_Supermarket/Stack_Analyser/new_bpf.sh index 8ed45cdb9..8aa1507a2 100755 --- a/eBPF_Supermarket/Stack_Analyser/new_bpf.sh +++ b/eBPF_Supermarket/Stack_Analyser/new_bpf.sh @@ -27,6 +27,6 @@ sed -i 's/template/'$origin_name'/g' bpf/$origin_name.bpf.c sed -i '/#include "bpf_wapper\/on_cpu.h"/a#include "bpf_wapper\/'$origin_name'.h"' src/main.cpp -sed -i '/auto MainOption = _GREEN "Some overall options" _RE %/iauto '$name'Option = clipp::option("'$origin_name'").call([]{ StackCollectorList.push_back(new '$class_name'()); }) % COLLECTOR_INFO("'$origin_name'") & (TraceOption);' src/main.cpp +sed -i '/auto MainOption = _GREEN "Some overall options" _RE %/iauto '$name'Option = clipp::option("'$origin_name'").call([]{ StackCollectorList.push_back(new '$class_name'()); }) % COLLECTOR_INFO("'$origin_name'");' src/main.cpp sed -i '/MainOption,/i'$name'Option,' src/main.cpp \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp index f69a509f1..d4f95de50 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp @@ -87,12 +87,21 @@ StackCollector::operator std::string() std::ostringstream oss; oss << _RED "time:" << getLocalDateTime() << _RE "\n"; std::map> traces; + std::map infos; oss << _BLUE "counts:" _RE "\n"; { auto D = sortedCountList(); if (!D) return oss.str(); + if ((*D).size() > top) + { + auto end = (*D).end(); + auto begin = end - top; + for (auto i = (*D).begin(); i < begin; i++) + delete i->v; + (*D).assign(begin, end); + } oss << _GREEN "pid\tusid\tksid"; for (int i = 0; i < scale_num; i++) oss << '\t' << scales[i].Type << "/" << scales[i].Period << scales[i].Unit; @@ -112,11 +121,11 @@ StackCollector::operator std::string() auto trace_fd = bpf_object__find_map_fd_by_name(obj, "sid_trace_map"); if (id.usid > 0 && traces.find(id.usid) == traces.end()) { - std::vector sym_trace; bpf_map_lookup_elem(trace_fd, &id.usid, trace); for (p = trace + MAX_STACKS - 1; !*p; p--) ; - for (; p >= trace; p--) + std::vector sym_trace(p - trace + 1); + for (int i = 0; p >= trace; p--) { uint64_t &addr = *p; symbol sym; @@ -127,52 +136,57 @@ StackCollector::operator std::string() else if (g_symbol_parser.get_symbol_info(id.pid, sym, file) && g_symbol_parser.find_elf_symbol(sym, file, id.pid, id.pid)) { if (sym.name[0] == '_' && sym.name[1] == 'Z') - // 代表是C++符号,则调用demangle解析 - { + // 代表是C++符号,则调用demangle解析 sym.name = demangleCppSym(sym.name); - } std::stringstream ss(""); - ss << "+0x" << std::hex << (addr - sym.start); + ss << "+0x" << std::hex << (sym.ip - sym.start); sym.name += ss.str(); g_symbol_parser.putin_symbol_cache(id.pid, addr, sym.name); } else { std::stringstream ss(""); - ss << "0x" << std::hex << addr; + ss << "0x" << std::hex << sym.ip; sym.name = ss.str(); g_symbol_parser.putin_symbol_cache(id.pid, addr, sym.name); } clearSpace(sym.name); - sym_trace.push_back(sym.name); + sym_trace[i++] = sym.name; } traces[id.usid] = sym_trace; } if (id.ksid > 0 && traces.find(id.ksid) == traces.end()) { - std::vector sym_trace; bpf_map_lookup_elem(trace_fd, &id.ksid, trace); for (p = trace + MAX_STACKS - 1; !*p; p--) ; - for (; p >= trace; p--) + std::vector sym_trace(p - trace + 1); + for (int i = 0; p >= trace; p--) { uint64_t &addr = *p; symbol sym; sym.reset(addr); + std::stringstream ss(""); if (g_symbol_parser.find_kernel_symbol(sym)) - ; + { + ss << "+0x" << std::hex << (sym.ip - sym.start); + sym.name += ss.str(); + } else { - std::stringstream ss(""); ss << "0x" << std::hex << addr; sym.name = ss.str(); g_symbol_parser.putin_symbol_cache(pid, addr, sym.name); } clearSpace(sym.name); - sym_trace.push_back(sym.name); + sym_trace[i++] = sym.name; } traces[id.ksid] = sym_trace; } + auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); + task_info info; + bpf_map_lookup_elem(info_fd, &id.pid, &info); + infos[id.pid] = info; } delete D; } @@ -191,37 +205,20 @@ StackCollector::operator std::string() oss << _BLUE "info:" _RE "\n"; { - auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); - if (info_fd < 0) - { - return oss.str(); - } - auto keys = new uint32_t[MAX_ENTRIES]; - auto vals = new task_info[MAX_ENTRIES]; - uint32_t count = MAX_ENTRIES; - uint32_t next_key; + oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup\t" _RE "\n"; + for (auto i : infos) { - int err; - if (showDelta) - err = bpf_map_lookup_and_delete_batch(info_fd, NULL, &next_key, - keys, vals, &count, NULL); - else - err = bpf_map_lookup_batch(info_fd, NULL, &next_key, - keys, vals, &count, NULL); - if (err == EFAULT) - return oss.str(); + auto cgroup_fd = bpf_object__find_map_fd_by_name(obj, "tgid_cgroup_map"); + char group[CONTAINER_ID_LEN]; + bpf_map_lookup_elem(cgroup_fd, &(i.second.tgid), &group); + oss << i.first << '\t' + << i.second.pid << '\t' + << i.second.comm << '\t' + << i.second.tgid << '\t' + << group << '\n'; } - oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup" _RE "\n"; - for (uint32_t i = 0; i < count; i++) - oss << keys[i] << '\t' - << vals[i].pid << '\t' - << vals[i].comm << '\t' - << vals[i].tgid << '\t' - << vals[i].cid << '\n'; - delete[] keys; - delete[] vals; } oss << _BLUE "OK" _RE "\n"; return oss.str(); -} \ No newline at end of file +} diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp index a6bdc3986..ecedcc450 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp @@ -78,7 +78,7 @@ int LlcStatStackCollector::attach(void) } /* Set up performance monitoring on a CPU/Core */ attr.config = PERF_COUNT_HW_CACHE_MISSES; - int pefd = syscall(SYS_perf_event_open, &attr, pid, cpu, -1, 0); + int pefd = syscall(SYS_perf_event_open, &attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); mpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -86,7 +86,7 @@ int LlcStatStackCollector::attach(void) CHECK_ERR(!mlinks[cpu], "Fail to attach bpf program"); attr.config = PERF_COUNT_HW_CACHE_REFERENCES; - pefd = syscall(SYS_perf_event_open, &attr, pid, cpu, -1, 0); + pefd = syscall(SYS_perf_event_open, &attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); rpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -141,6 +141,7 @@ LlcStatStackCollector::LlcStatStackCollector() }; }; -void LlcStatStackCollector::setScale(uint64_t p) { +void LlcStatStackCollector::setScale(uint64_t p) +{ scales[0].Period = scales[1].Period = p; } \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp index e0edb6cda..b7603036f 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp @@ -119,10 +119,7 @@ int MemleakStackCollector::load(void) disable_kernel_node_tracepoints(skel); if (!percpu) disable_kernel_percpu_tracepoints(skel); - } else { - disable_kernel_tracepoints(skel); - }; - skel->rodata->sample_rate = sample_rate; + } else disable_kernel_tracepoints(skel); skel->rodata->wa_missing_free = wa_missing_free; skel->rodata->page_size = sysconf(_SC_PAGE_SIZE);); return 0; @@ -152,6 +149,7 @@ void MemleakStackCollector::activate(bool tf) ACTIVE_SET(tf); } -const char *MemleakStackCollector::getName(void) { +const char *MemleakStackCollector::getName(void) +{ return "MemleakStackCollector"; -} \ No newline at end of file +} diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp index 8e4e1cf4a..287bec493 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp @@ -62,7 +62,6 @@ uint64_t *OnCPUStackCollector::count_values(void *data) int OnCPUStackCollector::load(void) { EBPF_LOAD_OPEN_INIT(); - return 0; }; @@ -99,7 +98,7 @@ int OnCPUStackCollector::attach(void) continue; } /* Set up performance monitoring on a CPU/Core */ - int pefd = perf_event_open(&attr, pid, cpu, -1, 0); + int pefd = perf_event_open(&attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); pefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -144,6 +143,7 @@ void OnCPUStackCollector::activate(bool tf) ACTIVE_SET(tf); } -const char *OnCPUStackCollector::getName(void) { +const char *OnCPUStackCollector::getName(void) +{ return "OnCPUStackCollector"; } \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp index 3c82035a2..e77008f60 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp @@ -12,29 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// author: GaoYixiang +// author: luiyanbing@foxmail.com // -// probe ebpf 程序的包装类,实现接口和一些自定义方法 +// ebpf程序包装类的模板,实现接口和一些自定义方法 #include "bpf_wapper/probe.h" +#include "trace_helpers.h" #include "uprobe_helpers.h" +// ========== implement virtual func ========== + uint64_t *ProbeStackCollector::count_values(void *data) { + time_tuple *p = (time_tuple *)data; return new uint64_t[scale_num]{ - *(uint32_t *)data, + p->lat, + p->count, }; -} +}; -ProbeStackCollector::ProbeStackCollector() +void ProbeStackCollector::setScale(std::string probe) { - scale_num = 1; - scales = new Scale[scale_num]{ - {"", 1, "counts"}, - }; + this->probe = probe; + for (int i = 0; i < scale_num; i++) + scales[i].Type = probe + scales[i].Type; +}; + +int ProbeStackCollector::load(void) +{ + EBPF_LOAD_OPEN_INIT(); + return 0; }; -void splitString(std::string symbol, const char split, std::vector &res) +void splitStr(std::string symbol, const char split, std::vector &res) { if (symbol == "") return; @@ -49,7 +59,7 @@ void splitString(std::string symbol, const char split, std::vector } } -static int get_path(char *path,int pid) +static int get_binpath(char *path, int pid) { char mode[16], line[128], buf[64]; size_t seg_start, seg_end, seg_off; @@ -62,11 +72,13 @@ static int get_path(char *path,int pid) return -1; while (fscanf(f, "%zx-%zx %s %zx %*s %*d%[^\n]\n", - &seg_start, &seg_end, mode, &seg_off, line) == 5) { + &seg_start, &seg_end, mode, &seg_off, line) == 5) + { i = 0; while (isblank(line[i])) i++; - if (strstr(line + i, "libc.so.6")) { + if (strstr(line + i, "libc.so.6")) + { break; } } @@ -75,86 +87,106 @@ static int get_path(char *path,int pid) fclose(f); return 0; } -void ProbeStackCollector::setScale(std::string probe) +static int attach_kprobes(struct probe_bpf *skel, std::string func) { - this->probe = probe; - scales->Type = probe + "Counts"; -}; + skel->links.dummy_kprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kprobe, false, func.c_str()); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach kprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kretprobe, true, func.c_str()); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach ketprobe"); + return 0; +} +static int attach_uprobes(struct probe_bpf *skel, std::string probe, int pid) +{ + char *binary, *function; + char bin_path[128]; + std::string func = probe; + off_t func_off; + + binary = strdup(func.c_str()); + function = strchr(binary, ':'); // 查找:首次出现的位置 + *function = '\0'; + function++; + + if (resolve_binary_path(binary, pid, bin_path, sizeof(bin_path))) + free(binary); + + func_off = get_elf_func_offset(bin_path, function); + if (func_off < 0) + free(binary); + skel->links.dummy_kprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kprobe, false, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach uprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kretprobe, true, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach uprobe"); + return 0; +} -int ProbeStackCollector::load(void) +static int attach_tp(struct probe_bpf *skel, std::string tp_class, std::string func) { - EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); + + skel->links.tp_entry = + bpf_program__attach_tracepoint(skel->progs.tp_entry, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_entry, "Fail to attach tracepoint"); + skel->links.tp_exit = + bpf_program__attach_tracepoint(skel->progs.tp_exit, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_exit, "Fail to attach tracepoint"); return 0; -}; +} + +static int attach_usdt(struct probe_bpf *skel, std::string func, int pid) +{ + char bin_path[128]; + int err = get_binpath(bin_path, pid); + CHECK_ERR(err, "Fail to get lib path"); + skel->links.usdt_entry = + bpf_program__attach_usdt(skel->progs.usdt_entry, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_entry, "Fail to attach usdt"); + skel->links.usdt_exit = + bpf_program__attach_usdt(skel->progs.usdt_exit, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_exit, "Fail to attach usdt"); + return 0; +} int ProbeStackCollector::attach(void) { + // dynamic mounting std::vector strList; - splitString(probe, ':', strList); + splitStr(probe, ':', strList); + std::string func = probe; + int err = 0; + if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") + func = strList[2]; if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")) { - // probe a kernel function - std::string func = probe; - if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") - func = strList[2]; - skel->links.handle = - bpf_program__attach_kprobe(skel->progs.handle, false, func.c_str()); - CHECK_ERR(!skel->links.handle, "Fail to attach kprobe"); - return 0; + err = attach_kprobes(skel, func); } else if (strList.size() == 3 && strList[0] == "t") { - // probe a kernel tracepoint - skel->links.handle_tp = - bpf_program__attach_tracepoint(skel->progs.handle_tp, strList[1].c_str(), strList[2].c_str()); - CHECK_ERR(!skel->links.handle_tp, "Fail to attach tracepoint"); - return 0; + err = attach_tp(skel, strList[1], strList[2]); } else if (strList.size() == 2 || (strList.size() == 3 && strList[0] == "p" && strList[1] != "")) { - // probe a user-space function in the library 'lib' - char *binary, *function; - char bin_path[128]; - std::string func = probe; - off_t func_off; if (strList.size() == 3) func = strList[1] + ":" + strList[2]; - - binary = strdup(func.c_str()); - function = strchr(binary, ':'); // 查找:首次出现的位置 - *function = '\0'; - function++; - - if (resolve_binary_path(binary, pid, bin_path, sizeof(bin_path))) - free(binary); - - func_off = get_elf_func_offset(bin_path, function); - if (func_off < 0) - free(binary); - skel->links.handle = - bpf_program__attach_uprobe(skel->progs.handle, false, pid, - bin_path, func_off); - CHECK_ERR(!skel->links.handle, "Fail to attach uprobe"); - return 0; + err = attach_uprobes(skel, func, pid); } else if (strList.size() == 3 && strList[0] == "u") { - // probe a USDT tracepoint - char bin_path[128]; - std::string func = probe; - int err = get_path(bin_path,pid); - CHECK_ERR(err, "Fail to get lib path"); - skel->links.handle_usdt = - bpf_program__attach_usdt(skel->progs.handle_usdt,pid,bin_path,"libc",strList[2].c_str(),NULL); - CHECK_ERR(!skel->links.handle_usdt, "Fail to attach usdt"); - return 0; + err = attach_usdt(skel, strList[2], pid); } else { printf("Type must be 'p', 't', or 'u' or too any args"); } + CHECK_ERR(err, "Fail to attach"); + return 0; }; @@ -173,6 +205,18 @@ void ProbeStackCollector::activate(bool tf) ACTIVE_SET(tf); } -const char *ProbeStackCollector::getName(void) { +const char *ProbeStackCollector::getName(void) +{ return "ProbeStackCollector"; -} \ No newline at end of file +} + +// ========== other implementations ========== + +ProbeStackCollector::ProbeStackCollector() +{ + scale_num = 2; + scales = new Scale[scale_num]{ + {"Time", 1, "nanoseconds"}, + {"Count", 1, "counts"}, + }; +}; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp b/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp index 92feb0d7b..d3c848fbc 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp @@ -49,7 +49,7 @@ bool symbol_parser::load_pid_maps(int pid) } proc_vma proc; - char fn[256]; + char fn[23]; sprintf(fn, "/proc/%d/maps", pid); FILE *fp = fopen(fn, "r"); if (!fp) { @@ -335,6 +335,11 @@ bool symbol_parser::putin_symbol_cache(int tgid, unsigned long addr, std::string return false; } +/// @brief 找到指定进程中的虚拟地址对应的在可执行文件中相对于文件开始的偏移,赋给sym.ip +/// @param pid 指定进程的pid +/// @param sym 提供进程虚拟地址 +/// @param file 文件信息 +/// @return 成功找到返回true bool symbol_parser::get_symbol_info(int pid, symbol &sym, elf_file &file) { std::map::iterator proc_vma_info; diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 842363627..c3c38e81d 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -23,6 +23,7 @@ #include #include "bpf_wapper/on_cpu.h" +#include "bpf_wapper/probe.h" #include "bpf_wapper/llc_stat.h" #include "bpf_wapper/off_cpu.h" #include "bpf_wapper/memleak.h" @@ -37,18 +38,83 @@ bool timeout = false; uint64_t IntTmp; std::string StrTmp; clipp::man_page *man_page; +std::vector StackCollectorList; namespace MainConfig { uint64_t run_time = -1; // 运行时间 unsigned delay = 5; // 设置输出间隔 std::string command = ""; - int32_t target_pid = -1; + uint32_t target_pid = 0; + uint32_t target_tgid = 0; + uint64_t target_cgroup = 0; std::string trigger = ""; // 触发器 std::string trig_event = ""; // 触发事件 + uint32_t top = 10; + uint32_t freq = 49; + bool trace_user = false; + bool trace_kernel = false; } -std::vector StackCollectorList; +namespace helper +{ +#include +#include + struct cgid_file_handle + { + // struct file_handle handle; + unsigned int handle_bytes; + int handle_type; + uint64_t cgid; + }; + uint64_t get_cgroupid(const char *pathname) + { + struct statfs fs; + int err; + struct cgid_file_handle *h; + int mount_id; + uint64_t ret; + + err = statfs(pathname, &fs); + if (err != 0) + { + fprintf(stderr, "statfs on %s failed: %s\n", pathname, strerror(errno)); + exit(1); + } + + if ((fs.f_type != (typeof(fs.f_type))CGROUP2_SUPER_MAGIC)) + { + fprintf(stderr, "File %s is not on a cgroup2 mount.\n", pathname); + exit(1); + } + + h = (cgid_file_handle *)malloc(sizeof(struct cgid_file_handle)); + if (!h) + { + fprintf(stderr, "Cannot allocate memory.\n"); + exit(1); + } + + h->handle_bytes = 8; + err = name_to_handle_at(AT_FDCWD, pathname, (struct file_handle *)h, &mount_id, 0); + if (err != 0) + { + fprintf(stderr, "name_to_handle_at failed: %s\n", strerror(errno)); + exit(1); + } + + if (h->handle_bytes != 8) + { + fprintf(stderr, "Unexpected handle size: %d. \n", h->handle_bytes); + exit(1); + } + + ret = h->cgid; + free(h); + + return ret; + } +} void end_handle(void) { @@ -74,100 +140,98 @@ int main(int argc, char *argv[]) man_page = new clipp::man_page(); clipp::group cli; { - auto TraceOption = (clipp::option("-u") - .call([] - { StackCollectorList.back()->ustack = true; }) % - "Sample user stacks", - clipp::option("-k") - .call([] - { StackCollectorList.back()->kstack = true; }) % - "Sample kernel stacks\n"); - auto OnCpuOption = (clipp::option("on_cpu") .call([] { StackCollectorList.push_back(new OnCPUStackCollector()); }) % - COLLECTOR_INFO("on-cpu")) & - ((clipp::option("-f") & - clipp::value("freq", IntTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->setScale(IntTmp); })) % - "Set sampling frequency; default is 49", - TraceOption); + COLLECTOR_INFO("on-cpu")); auto OffCpuOption = clipp::option("off_cpu") - .call([] - { StackCollectorList.push_back(new OffCPUStackCollector()); }) % - COLLECTOR_INFO("off-cpu") & - (TraceOption); + .call([] + { StackCollectorList.push_back(new OffCPUStackCollector()); }) % + COLLECTOR_INFO("off-cpu"); auto MemleakOption = (clipp::option("memleak") .call([] { StackCollectorList.push_back(new MemleakStackCollector()); }) % COLLECTOR_INFO("memleak")) & - ((clipp::option("-i") & - clipp::value("interval", IntTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->sample_rate = IntTmp; })) % - "Set the sampling interval; default is 1", - clipp::option("-w") - .call([] - { static_cast(StackCollectorList.back()) - ->wa_missing_free = true; }) % - "Free when missing in kernel to alleviate misjudgments", - TraceOption); + (clipp::option("-W") + .call([] + { static_cast(StackCollectorList.back()) + ->wa_missing_free = true; }) % + "Free when missing in kernel to alleviate misjudgments"); auto IOOption = clipp::option("io") - .call([] - { StackCollectorList.push_back(new IOStackCollector()); }) % - COLLECTOR_INFO("io") & - (TraceOption); + .call([] + { StackCollectorList.push_back(new IOStackCollector()); }) % + COLLECTOR_INFO("io"); auto ReadaheadOption = clipp::option("readahead") - .call([] - { StackCollectorList.push_back(new ReadaheadStackCollector()); }) % - COLLECTOR_INFO("readahead") & - (TraceOption); - - auto ProbeOption = clipp::option("probe") .call([] - { StackCollectorList.push_back(new ProbeStackCollector()); }) % - COLLECTOR_INFO("probe") & - (clipp::value("probe", StrTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->setScale(StrTmp); }) % - "Set the probe string; specific use is: \n probe func && probe p::func -- probe a kernel function; \n lib:func && p:lib:func -- probe a user-space function in the library 'lib';\n probe t:cat:event -- probe a kernel tracepoint; \n probe u:lib:probe -- probe a USDT tracepoint" & - TraceOption); + { StackCollectorList.push_back(new ReadaheadStackCollector()); }) % + COLLECTOR_INFO("readahead"); auto LlcStatOption = clipp::option("llc_stat").call([] { StackCollectorList.push_back(new LlcStatStackCollector()); }) % COLLECTOR_INFO("llc_stat") & - ((clipp::option("-i") & + ((clipp::option("-P") & clipp::value("period", IntTmp) .call([] { static_cast(StackCollectorList.back()) ->setScale(IntTmp); })) % - "Set sampling period; default is 100", - TraceOption); + "Set sampling period; default is 100"); + + auto ProbeOption = clipp::option("probe") + .call([] + { StackCollectorList.push_back(new ProbeStackCollector()); }) % + COLLECTOR_INFO("probe") & + (clipp::value("probe", StrTmp) + .call([] + { static_cast(StackCollectorList.back()) + ->setScale(StrTmp); }) % + "Set the probe string; specific use is:\n" + " | p:: -- probe a kernel function;\n" + ": | p:: -- probe a user-space function in the library 'lib';\n" + "t:: -- probe a kernel tracepoint;\n" + "u:: -- probe a USDT tracepoint"); auto MainOption = _GREEN "Some overall options" _RE % (( + ((clipp::option("-g") & + clipp::value("cgroup path", StrTmp) + .call([] + { MainConfig::target_cgroup = helper::get_cgroupid(StrTmp.c_str()); printf("Trace cgroup %ld\n", MainConfig::target_cgroup); })) % + "Set the cgroup of the process to be tracked; default is -1, which keeps track of all cgroups") | ((clipp::option("-p") & - clipp::value("pid", MainConfig::target_pid)) % + clipp::value("pid", MainConfig::target_tgid)) % "Set the pid of the process to be tracked; default is -1, which keeps track of all processes") | + ((clipp::option("-t") & + clipp::value("tid", MainConfig::target_pid)) % + "Set the tid of the thread to be tracked; default is -1, which keeps track of all threads") | ((clipp::option("-c") & clipp::value("command", MainConfig::command)) % "Set the command to be run and sampled; defaults is none")), - (clipp::option("-d") & + (clipp::option("-o") & + clipp::value("top", MainConfig::top)) % + "Set the top number; default is 10", + (clipp::option("-f") & + clipp::value("freq", MainConfig::freq)) % + "Set sampling frequency, 0 for close; default is 49", + (clipp::option("-i") & clipp::value("interval", MainConfig::delay)) % "Set the output delay time (seconds); default is 5", - (clipp::option("-t") & + (clipp::option("-d") & clipp::value("duration", MainConfig::run_time) .call([] { stop_time = time(NULL) + MainConfig::run_time; })) % "Set the total sampling time; default is __INT_MAX__", + (clipp::option("-u") + .call([] + { MainConfig::trace_user = true; }) % + "Sample user stacks", + clipp::option("-k") + .call([] + { MainConfig::trace_kernel = true; }) % + "Sample kernel stacks"), (clipp::option("-T") & ((clipp::required("cpu").set(MainConfig::trigger) | clipp::required("memory").set(MainConfig::trigger) | @@ -192,8 +256,8 @@ int main(int argc, char *argv[]) MemleakOption, IOOption, ReadaheadOption, - ProbeOption, LlcStatOption, + ProbeOption, MainOption, Info); } @@ -227,7 +291,7 @@ int main(int argc, char *argv[]) MainConfig::target_pid = fork(); switch (MainConfig::target_pid) { - case -1: + case (uint32_t)-1: { CHECK_ERR(true, "Command create failed."); } @@ -253,6 +317,12 @@ int main(int argc, char *argv[]) fprintf(stderr, _RED "Attach collecotor%d %s.\n" _RE, (int)(Item - StackCollectorList.begin()) + 1, (*Item)->getName()); (*Item)->pid = MainConfig::target_pid; + (*Item)->tgid = MainConfig::target_tgid; + (*Item)->cgroup = MainConfig::target_cgroup; + (*Item)->top = MainConfig::top; + (*Item)->freq = MainConfig::freq; + (*Item)->kstack = MainConfig::trace_kernel; + (*Item)->ustack = MainConfig::trace_user; if ((*Item)->load() || (*Item)->attach()) goto err; Item++; diff --git a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c index 6c9729b8d..47acf0b06 100644 --- a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c +++ b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c @@ -1,13 +1,15 @@ +#define _GNU_SOURCE #include #include #include #include +#include // 线程函数 void *thread_function(void *arg) { while (1) { // 打印当前线程的pid - printf("Thread PID: %d\n", getpid()); + printf("Thread ID: %d\n", gettid()); // 等待一秒 sleep(1); } @@ -29,14 +31,14 @@ void create_thread() { int main() { // 打印主进程的pid - printf("Main process PID: %d\n", getpid()); + printf("Main process ID: %d\n", gettid()); // 调用函数创建线程 create_thread(); // 主进程死循环打印pid while (1) { - printf("Main process PID: %d\n", getpid()); + printf("Main process ID: %d\n", getpid()); // 等待一秒 sleep(1); } diff --git a/eBPF_Supermarket/kvm_watcher/Makefile b/eBPF_Supermarket/kvm_watcher/Makefile index 30f6a4b89..e292f83ba 100644 --- a/eBPF_Supermarket/kvm_watcher/Makefile +++ b/eBPF_Supermarket/kvm_watcher/Makefile @@ -41,7 +41,8 @@ default: bpf deps: sudo apt-get update sudo apt-get install -y clang libelf1 libelf-dev zlib1g-dev libbpf-dev \ - linux-tools-$$(uname -r) linux-cloud-tools-$$(uname -r) + linux-tools-$$(uname -r) linux-cloud-tools-$$(uname -r) \ + libpcap-dev gcc-multilib build-essential sudo apt-get install -y lolcat qemu-kvm wget # 生成 vmlinux.h .PHONY: vmlinux diff --git a/eBPF_Supermarket/kvm_watcher/README.md b/eBPF_Supermarket/kvm_watcher/README.md index 3c83aa161..73218670b 100755 --- a/eBPF_Supermarket/kvm_watcher/README.md +++ b/eBPF_Supermarket/kvm_watcher/README.md @@ -10,6 +10,8 @@ `kvm_watcher`是一款基于eBPF的kvm虚拟机检测工具,其旨在使用户方便快捷在宿主机侧获取kvm虚拟机中的各种信息,报告所有正在运行的guest行为。 +![kvm watcher项目框图](https://gitee.com/nan-shuaibo/image/raw/master/202404251704350.png) + 目前,其实现的功能主要包括: - **[VM Exit 事件分析](./docs/kvm_exit.md)** diff --git a/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md b/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md index bb84b25ec..72d9a8034 100644 --- a/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md +++ b/eBPF_Supermarket/kvm_watcher/docs/kvm_exit.md @@ -2,6 +2,8 @@ 考虑到频繁的虚拟机退出事件可能会导致性能问题,kvm_watcher中的kvm_exit子功能通过显示详细的退出原因和在一台主机上运行的所有vm的每个虚拟机的vcpu上的退出计数及处理时延,可以捕获和分析vm exit事件,该工具旨在定位频繁退出的原因(如EPT_VIOLATION、EPT_MISCONFIG、PML_FULL等),在vm exit基础上,如果kvm这个时候因为某些原因,需要退出到用户态的hypervisor(比如qemu),kvm就要设置KVM_EXIT_XXX,此工具包含了这两部分exit reason。 +![kvm exit](https://gitee.com/nan-shuaibo/image/raw/master/202404251707665.png) + ## 原理介绍 ### VMX 操作模式 @@ -102,5 +104,4 @@ pid tid total_time max_time min_time counts re - **VM Exit 原因统计**:记录并展示触发 VM Exit 的具体原因,帮助用户理解 VM Exit 发生的上下文和背景。 - **VM Exit 延时分析**:统计每次 VM Exit 处理的最大、最小和总共延时,为性能分析提供量化数据。 - **VM Exit 次数计数**:计算每种类型的 VM Exit 发生的次数,帮助识别最频繁的性能瓶颈。 -- **PID、TID号**:其中PID为主机侧的虚拟机进程号,TID为虚拟机内部的vcpu**的进程号** - \ No newline at end of file +- **PID、TID号**:其中PID为主机侧的虚拟机进程号,TID为虚拟机内部的vcpu**的进程号** \ No newline at end of file diff --git a/eBPF_Supermarket/kvm_watcher/docs/kvm_irq.md b/eBPF_Supermarket/kvm_watcher/docs/kvm_irq.md index 9a7e2a801..5f30152f4 100644 --- a/eBPF_Supermarket/kvm_watcher/docs/kvm_irq.md +++ b/eBPF_Supermarket/kvm_watcher/docs/kvm_irq.md @@ -4,6 +4,8 @@ kvm watcher中的kvm irq子功能模块可以对kvm中的虚拟化中断事件的实时监控和分析能力,可以捕获和记录各种中断事件,支持监控传统的PIC中断、高级的IOAPIC中断以及基于消息的MSI中断,覆盖了KVM虚拟化环境中的主要中断类型。对于每个捕获的中断事件,记录详细信息,包括中断类型、中断注入延时、引脚号、触发方式、目标LAPIC的ID、向量号以及是否被屏蔽等关键数据。 +![kvm_irq](https://gitee.com/nan-shuaibo/image/raw/master/202404251710847.png) + ## 原理介绍 x86平台主要使用的中断类型有pic、apic及msi中断,在多核系统下的apic结构图如下所示,每个cpu有一个lapic,外部中断通过ioapic转发到lapic,如果是msi中断,则绕过了io apic直接发给lapic。 @@ -14,48 +16,48 @@ KVM_CREATE_IRQCHIP的ioctl用于在虚拟机初始化阶段创建中断请求芯 ``` int kvm_set_routing_entry(struct kvm *kvm, - struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue) + struct kvm_kernel_irq_routing_entry *e, + const struct kvm_irq_routing_entry *ue) { - switch (ue->type) { - case KVM_IRQ_ROUTING_IRQCHIP: //中断路由芯片 - if (irqchip_split(kvm)) - return -EINVAL; - e->irqchip.pin = ue->u.irqchip.pin;//设置中断芯片引脚 - switch (ue->u.irqchip.irqchip) { - case KVM_IRQCHIP_PIC_SLAVE: - e->irqchip.pin += PIC_NUM_PINS / 2; //从片引脚 - fallthrough; - case KVM_IRQCHIP_PIC_MASTER: - if (ue->u.irqchip.pin >= PIC_NUM_PINS / 2) - return -EINVAL; - //// 设置处理 PIC 中断的回调函数 - e->set = kvm_set_pic_irq; - break; - case KVM_IRQCHIP_IOAPIC: - if (ue->u.irqchip.pin >= KVM_IOAPIC_NUM_PINS) - return -EINVAL; - // 设置处理 IOPIC 中断的回调函数 - e->set = kvm_set_ioapic_irq; - break; - default: - return -EINVAL; - } - e->irqchip.irqchip = ue->u.irqchip.irqchip; - break; - case KVM_IRQ_ROUTING_MSI: - // 设置处理 MSI 中断的回调函数 - e->set = kvm_set_msi; - e->msi.address_lo = ue->u.msi.address_lo; - e->msi.address_hi = ue->u.msi.address_hi; - e->msi.data = ue->u.msi.data; - - if (kvm_msi_route_invalid(kvm, e)) - return -EINVAL; - break; + switch (ue->type) { + case KVM_IRQ_ROUTING_IRQCHIP: //中断路由芯片 + if (irqchip_split(kvm)) + return -EINVAL; + e->irqchip.pin = ue->u.irqchip.pin;//设置中断芯片引脚 + switch (ue->u.irqchip.irqchip) { + case KVM_IRQCHIP_PIC_SLAVE: + e->irqchip.pin += PIC_NUM_PINS / 2; //从片引脚 + fallthrough; + case KVM_IRQCHIP_PIC_MASTER: + if (ue->u.irqchip.pin >= PIC_NUM_PINS / 2) + return -EINVAL; + //// 设置处理 PIC 中断的回调函数 + e->set = kvm_set_pic_irq; + break; + case KVM_IRQCHIP_IOAPIC: + if (ue->u.irqchip.pin >= KVM_IOAPIC_NUM_PINS) + return -EINVAL; + // 设置处理 IOPIC 中断的回调函数 + e->set = kvm_set_ioapic_irq; + break; + default: + return -EINVAL; + } + e->irqchip.irqchip = ue->u.irqchip.irqchip; + break; + case KVM_IRQ_ROUTING_MSI: + // 设置处理 MSI 中断的回调函数 + e->set = kvm_set_msi; + e->msi.address_lo = ue->u.msi.address_lo; + e->msi.address_hi = ue->u.msi.address_hi; + e->msi.data = ue->u.msi.data; + + if (kvm_msi_route_invalid(kvm, e)) + return -EINVAL; + break; ..... - return 0; + return 0; } ``` @@ -75,22 +77,22 @@ KVM_CREATE_IRQCHIP用于虚拟机向VMM的虚拟apic发送中断请求,再有V * > 0 中断成功送达的 CPU 数量 */ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status) + bool line_status) { - struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS]; - .... + struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS]; + .... - while (i--) { - int r; - r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level, - line_status); - if (r < 0) - continue; + while (i--) { + int r; + r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level, + line_status); + if (r < 0) + continue; - ret = r + ((ret < 0) ? 0 : ret); - } + ret = r + ((ret < 0) ? 0 : ret); + } - return ret; + return ret; } ``` @@ -101,7 +103,7 @@ KVM_CREATE_IRQCHIP用于虚拟机向VMM的虚拟apic发送中断请求,再有V 其中ioapic的回调函数kvm_set_ioapic_irq依次调用kvm_ioapic_set_irq、ioapic_set_irq最后调用ioapic_service函数,ioapic_service主要是找到中断的重映射表,然后查找中断的目的地信息并转发到对应vcpu的lapic去处理。然后会调用kvm_irq_delivery_to_apic负责将中断分发给lapic。 > 中断虚拟化详细介绍可以参考:[kvm中断虚拟化 ](https://blog.csdn.net/zgy666/article/details/105456569) -> [内核虚拟化:虚拟中断注入](https://blog.csdn.net/weixin_46324627/article/details/136661252?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22136661252%22%2C%22source%22%3A%22weixin_46324627%22%7D) +> [内核虚拟化:虚拟中断注入](https://blog.csdn.net/weixin_46324627/article/details/136661252?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22136661252%22%2C%22source%22%3A%22weixin_46324627%22%7D) ## 挂载点 diff --git a/eBPF_Supermarket/kvm_watcher/docs/kvm_vcpu.md b/eBPF_Supermarket/kvm_watcher/docs/kvm_vcpu.md index e3733231b..e8980e773 100644 --- a/eBPF_Supermarket/kvm_watcher/docs/kvm_vcpu.md +++ b/eBPF_Supermarket/kvm_watcher/docs/kvm_vcpu.md @@ -8,6 +8,8 @@ kvm watcher中的kvm vcpu子功能模块是设计用于监控和分析虚拟化 ### wakeup、暂停轮询 +![kvm vcpu](https://gitee.com/nan-shuaibo/image/raw/master/202404251709557.png) + KVM 暂停轮询系统是 KVM 内的一项功能,其在某些情况下可以通过在vCPU 放弃运行并让出后,在主机中进行一段时间的轮询来降低虚拟机的延迟。简而言之,当vCPU 放弃运行(即执行 cede 操作)或在 PowerPC 中,当一个虚拟核心(vcore)的所有vCPU 都放弃运行时,主机内核会在将 CPU 让给调度程序之前,通过轮询等待唤醒条件。 轮询在某些情况下提供了延迟优势,尤其是在虚拟机可以非常快速地再次运行的情况下。这至少可以通过减少通过调度程序的开销来节省一些时间,通常在几微秒的数量级上,尽管性能优势取决于工作负载。在轮询间隔内,如果没有唤醒源到达,或者运行队列上有其他可运行的任务,则会调用调度程序。因此,在具有非常短唤醒周期的工作负载中,halt轮询特别有用,因为最小化了halt轮询的时间,同时可以避免调用调度程序的时间花费。 @@ -16,6 +18,8 @@ KVM 暂停轮询系统是 KVM 内的一项功能,其在某些情况下可以 ### dirty page +![dirty page](https://gitee.com/nan-shuaibo/image/raw/master/202404251709559.png) + 在虚拟化环境中,脏页指的是自上次同步以来已经被修改的内存页。特别是在虚拟机热迁移过程中,源虚拟机上的内存页在复制到目标虚拟机的同时仍然处于活动状态,任何在此过程中对这些页的修改都会导致脏页的产生。监控这些脏页对于优化热迁移过程至关重要,因为过多的脏页生成可能会导致迁移延迟,甚至影响到虚拟机的运行性能。此监控功能特别适用于虚拟机热迁移的场景,其中脏页的精确监控和管理可以显著优化迁移过程。 ## 挂载点 diff --git a/eBPF_Supermarket/kvm_watcher/include/kvm_exits.h b/eBPF_Supermarket/kvm_watcher/include/kvm_exits.h index 827e10b99..1e381d007 100644 --- a/eBPF_Supermarket/kvm_watcher/include/kvm_exits.h +++ b/eBPF_Supermarket/kvm_watcher/include/kvm_exits.h @@ -135,7 +135,7 @@ static int trace_kvm_entry() { return 0; } -static int trace_kvm_userspace_entry(struct kvm_vcpu *vcpu) { +static int trace_kvm_vcpu_ioctl() { pid_t tid = (u32)bpf_get_current_pid_tgid(); u64 ts = bpf_ktime_get_ns(); bpf_map_update_elem(&userspace_exit_times, &tid, &ts, BPF_ANY); diff --git a/eBPF_Supermarket/kvm_watcher/include/kvm_ioctl.h b/eBPF_Supermarket/kvm_watcher/include/kvm_ioctl.h index b3cda58b1..dd79a7702 100644 --- a/eBPF_Supermarket/kvm_watcher/include/kvm_ioctl.h +++ b/eBPF_Supermarket/kvm_watcher/include/kvm_ioctl.h @@ -21,22 +21,9 @@ #include "kvm_watcher.h" #include "vmlinux.h" -#include #include #include #include -#include - -#define KVMIO 0xAE -#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */ -#define KVM_CREATE_VCPU _IO(KVMIO, 0x41) -#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) -#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events) -#define KVM_SET_USER_MEMORY_REGION \ - _IOW(KVMIO, 0x46, struct kvm_userspace_memory_region) -#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation) -#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) -#define KVM_RUN _IO(KVMIO, 0x80) static int trace_kvm_ioctl(struct trace_event_raw_sys_enter *args) { int fd = (int)args->args[0]; diff --git a/eBPF_Supermarket/kvm_watcher/include/kvm_watcher.h b/eBPF_Supermarket/kvm_watcher/include/kvm_watcher.h index 6d5e34e53..5fe4fc30f 100644 --- a/eBPF_Supermarket/kvm_watcher/include/kvm_watcher.h +++ b/eBPF_Supermarket/kvm_watcher/include/kvm_watcher.h @@ -19,6 +19,39 @@ #ifndef __KVM_WATCHER_H #define __KVM_WATCHER_H +static const char binary_path[] = "/bin/qemu-system-x86_64"; +#define __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe) \ + do { \ + LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \ + .retprobe = is_retprobe); \ + skel->links.prog_name = bpf_program__attach_uprobe_opts( \ + skel->progs.prog_name, env.vm_pid, binary_path, 0, &uprobe_opts); \ + } while (false) + +#define __CHECK_PROGRAM(skel, prog_name) \ + do { \ + if (!skel->links.prog_name) { \ + perror("no program attached for " #prog_name); \ + return -errno; \ + } \ + } while (false) + +#define __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, is_retprobe) \ + do { \ + __ATTACH_UPROBE(skel, sym_name, prog_name, is_retprobe); \ + __CHECK_PROGRAM(skel, prog_name); \ + } while (false) + +#define ATTACH_UPROBE(skel, sym_name, prog_name) \ + __ATTACH_UPROBE(skel, sym_name, prog_name, false) +#define ATTACH_URETPROBE(skel, sym_name, prog_name) \ + __ATTACH_UPROBE(skel, sym_name, prog_name, true) + +#define ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name) \ + __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, false) +#define ATTACH_URETPROBE_CHECKED(skel, sym_name, prog_name) \ + __ATTACH_UPROBE_CHECKED(skel, sym_name, prog_name, true) + #define TASK_COMM_LEN 16 #define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0) @@ -56,6 +89,19 @@ #define APIC_LVT_TIMER_PERIODIC (1 << 17) // 周期性触发模式 #define APIC_LVT_TIMER_TSCDEADLINE (2 << 17) // TSC 截止模式 +// IOCTL +#include +#define KVMIO 0xAE +#define KVM_CREATE_VM _IO(KVMIO, 0x01) +#define KVM_CREATE_VCPU _IO(KVMIO, 0x41) +#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) +#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events) +#define KVM_SET_USER_MEMORY_REGION \ + _IOW(KVMIO, 0x46, struct kvm_userspace_memory_region) +#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation) +#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) +#define KVM_RUN _IO(KVMIO, 0x80) + #define PRINT_USAGE_ERR() \ do { \ fprintf(stderr, "Please specify exactly one option from %s.\n", \ diff --git a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c index b44ee3922..23b6d87f3 100644 --- a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c +++ b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c @@ -68,18 +68,18 @@ int tp_entry(struct exit *ctx) { return trace_kvm_entry(); } // 记录VCPU调度的信息--进入 -SEC("kprobe/vmx_vcpu_load") -int BPF_KPROBE(kp_vmx_vcpu_load, struct kvm_vcpu *vcpu, int cpu) { +SEC("fentry/vmx_vcpu_load") +int BPF_PROG(kp_vmx_vcpu_load, struct kvm_vcpu *vcpu, int cpu) { CHECK_PID(vm_pid); return trace_vmx_vcpu_load(vcpu, cpu); } // 记录VCPU调度的信息--退出 -SEC("kprobe/vmx_vcpu_put") -int BPF_KPROBE(kp_vmx_vcpu_put, struct kvm_vcpu *vcpu) { +SEC("fentry/vmx_vcpu_put") +int BPF_PROG(kp_vmx_vcpu_put, struct kvm_vcpu *vcpu) { return trace_vmx_vcpu_put(); } -SEC("kprobe/mark_page_dirty_in_slot") -int BPF_KPROBE(kp_mark_page_dirty_in_slot, struct kvm *kvm, +SEC("fentry/mark_page_dirty_in_slot") +int BPF_PROG(kp_mark_page_dirty_in_slot, struct kvm *kvm, const struct kvm_memory_slot *memslot, gfn_t gfn) { CHECK_PID(vm_pid); return trace_mark_page_dirty_in_slot(kvm, memslot, gfn, &rb, e); @@ -172,10 +172,13 @@ int tp_ioctl(struct trace_event_raw_sys_enter *args) { CHECK_PID(vm_pid); return trace_kvm_ioctl(args); } -SEC("fentry/kvm_arch_vcpu_ioctl_run") -int BPF_PROG(fentry_kvm_arch_vcpu_ioctl_run, struct kvm_vcpu *vcpu) { + +SEC("uprobe") +int BPF_KPROBE(up_kvm_vcpu_ioctl, void *cpu, int type) { CHECK_PID(vm_pid); - return trace_kvm_userspace_entry(vcpu); + if (type != KVM_RUN) + return 0; + return trace_kvm_vcpu_ioctl(); } SEC("tp/kvm/kvm_userspace_exit") diff --git a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c index bcb271968..142a2d7fc 100644 --- a/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c +++ b/eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c @@ -805,7 +805,7 @@ static void set_disable_load(struct kvm_watcher_bpf *skel) { env.execute_exit ? true : false); bpf_program__set_autoload(skel->progs.tp_entry, env.execute_exit ? true : false); - bpf_program__set_autoload(skel->progs.fentry_kvm_arch_vcpu_ioctl_run, + bpf_program__set_autoload(skel->progs.up_kvm_vcpu_ioctl, env.execute_exit ? true : false); bpf_program__set_autoload(skel->progs.tp_kvm_userspace_exit, env.execute_exit ? true : false); @@ -857,7 +857,7 @@ const char *getCurrentTimeFormatted() { tm = localtime(&t); // 格式化时间到静态分配的字符串中 - strftime(ts, sizeof(ts), "%H:%M:%S", tm); + strftime(ts, sizeof(ts), "%Y/%m/%d %H:%M:%S", tm); return ts; // 返回指向静态字符串的指针 } @@ -1064,7 +1064,6 @@ void __print_exit_map(int fd, enum NameType name_type) { for (int i = 0; i < count; i++) { if (first_run) { first_run = 0; - printf("\nTIME:%s\n", getCurrentTimeFormatted()); if (name_type == EXIT_NR) { printf( "============================================KVM_EXIT======" @@ -1122,6 +1121,7 @@ void __print_exit_map(int fd, enum NameType name_type) { int print_exit_map(struct kvm_watcher_bpf *skel) { int exit_fd = bpf_map__fd(skel->maps.exit_map); int userspace_exit_fd = bpf_map__fd(skel->maps.userspace_exit_map); + printf("\nTIME:%s\n", getCurrentTimeFormatted()); __print_exit_map(exit_fd, EXIT_NR); __print_exit_map(userspace_exit_fd, EXIT_USERSPACE_NR); return 0; @@ -1143,6 +1143,13 @@ void print_logo() { system(command); } +int attach_probe(struct kvm_watcher_bpf *skel) { + if (env.execute_exit) { + ATTACH_UPROBE_CHECKED(skel, kvm_vcpu_ioctl, up_kvm_vcpu_ioctl); + } + return kvm_watcher_bpf__attach(skel); +} + int main(int argc, char **argv) { // 定义一个环形缓冲区 struct ring_buffer *rb = NULL; @@ -1183,12 +1190,11 @@ int main(int argc, char **argv) { } /* 附加跟踪点处理程序 */ - err = kvm_watcher_bpf__attach(skel); + err = attach_probe(skel); if (err) { fprintf(stderr, "Failed to attach BPF skeleton\n"); goto cleanup; } - /* 设置环形缓冲区轮询 */ rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL); if (!rb) { diff --git a/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.mod b/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.mod index 1d3490081..a23f5d54b 100644 --- a/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.mod +++ b/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.mod @@ -66,11 +66,11 @@ require ( github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.sum b/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.sum index 5bee703f3..082528635 100644 --- a/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.sum +++ b/eBPF_Supermarket/old_project/cilium_ebpf_probe/go.sum @@ -389,8 +389,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -469,8 +469,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -559,12 +559,12 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/eBPF_Supermarket/old_project/sidecar/go.mod b/eBPF_Supermarket/old_project/sidecar/go.mod index 671b1ec46..417d316f1 100644 --- a/eBPF_Supermarket/old_project/sidecar/go.mod +++ b/eBPF_Supermarket/old_project/sidecar/go.mod @@ -66,11 +66,11 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.uber.org/atomic v1.10.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/eBPF_Supermarket/old_project/sidecar/go.sum b/eBPF_Supermarket/old_project/sidecar/go.sum index 91d554753..dae646e8f 100644 --- a/eBPF_Supermarket/old_project/sidecar/go.sum +++ b/eBPF_Supermarket/old_project/sidecar/go.sum @@ -402,8 +402,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -468,12 +468,12 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -481,8 +481,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=