├── .devcontainer ├── Dockerfile_AzureLinux ├── Dockerfile_Rocky ├── Dockerfile_Ubuntu ├── devcontainer.json ├── install-azurelinux.dependencies.sh ├── install-rocky-dependencies.sh └── install-ubuntu-dependencies.sh ├── .github ├── compliance │ └── inventory.yml ├── issue_template.md └── workflows │ └── scorecard.yml ├── .gitignore ├── BUILD.md ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── INSTALL.md ├── LICENSE ├── NOTICE.txt ├── README.md ├── azure-pipelines.yml ├── dist ├── DEBIAN.in │ └── control.in ├── SPECS.in │ └── spec.in ├── changelog └── procdump.spec.in ├── docs ├── cloudnative_kubernetes.md ├── coreclrintegration.md ├── coredumpazure.jpg ├── deploy.yaml ├── trigger_arch.jpg └── write_new_trigger.md ├── ebpf ├── procdump_ebpf.c ├── procdump_ebpf.h ├── procdump_ebpf_common.h ├── vmlinux-arm64.h ├── vmlinux-x86.h └── vmlinux.h ├── include ├── CoreDumpWriter.h ├── DotnetHelpers.h ├── Events.h ├── GenHelpers.h ├── Handle.h ├── Includes.h ├── Logging.h ├── Monitor.h ├── ProcDumpConfiguration.h ├── ProcDumpVersion.h.in ├── Procdump.h ├── Process.h ├── ProfilerCommon.h ├── ProfilerHelpers.h └── Restrack.h ├── makePackages.sh ├── nuget.config ├── procdump.1 ├── procdump.gif ├── procdump_mac.1 ├── profiler ├── inc │ ├── CComPtr.h │ ├── ClassFactory.h │ ├── ProcDumpProfiler.h │ ├── cor.h │ ├── corerror.h │ ├── corhdr.h │ ├── corhlpr.h │ ├── corprof.h │ ├── debugmacrosext.h │ ├── easylogging++.h │ ├── no_sal2.h │ ├── ntimage.h │ ├── oaidl.h │ ├── objidl.h │ ├── ole2.h │ ├── pal.h │ ├── pal_assert.h │ ├── pal_endian.h │ ├── pal_error.h │ ├── pal_mstypes.h │ ├── palrt.h │ ├── poppack.h │ ├── profiler_pal.h │ ├── profilerstring.h │ ├── pshpack1.h │ ├── pshpack2.h │ ├── pshpack4.h │ ├── pshpack8.h │ ├── rpc.h │ ├── rpcndr.h │ ├── safecrt.h │ ├── safemath.h │ ├── sal.h │ ├── servprov.h │ ├── specstrings.h │ ├── specstrings_strict.h │ ├── static_assert.h │ ├── unknwn.h │ ├── unreachable.h │ ├── utils.h │ └── winerror.h └── src │ ├── ClassFactory.cpp │ ├── ClrProfiler.def │ ├── ProcDumpProfiler.cpp │ ├── corprof_i.cpp │ ├── dllmain.cpp │ └── easylogging++.cc ├── src ├── CoreDumpWriter.cpp ├── DotnetHelpers.cpp ├── Events.cpp ├── GenHelpers.cpp ├── Handle.cpp ├── Logging.cpp ├── Monitor.cpp ├── ProcDumpConfiguration.cpp ├── Procdump.cpp ├── Process.cpp ├── ProfilerHelpers.cpp └── Restrack.cpp ├── sudo ├── sym ├── bcc_elf.cpp ├── bcc_elf.h ├── bcc_perf_map.cpp ├── bcc_perf_map.h ├── bcc_proc.cpp ├── bcc_proc.h ├── bcc_syms.cc ├── bcc_syms.h ├── bcc_zip.cpp ├── bcc_zip.h ├── common.h ├── file_desc.h ├── syms.h └── tinyformat.hpp ├── templates └── build.yaml └── tests └── integration ├── ProcDumpTestApplication.c ├── TestWebApi ├── Program.cs ├── Properties │ └── launchSettings.json ├── TestWebApi.csproj ├── appsettings.Development.json └── appsettings.json ├── helpers.sh ├── run.sh ├── runProcDumpAndValidate.sh ├── scenarios ├── dotnet_0ExceptionDump1Thrown_dump.sh ├── dotnet_0WildcardExceptionDump1Thrown_dump.sh ├── dotnet_1FilterExceptionMsgDump1Thrown_dump.sh ├── dotnet_1WildcardExceptionDump1Thrown_dump.sh ├── dotnet_1WildcardFilterExceptionMsgDump1Thrown_dump.sh ├── dotnet_1_gc_gen_1_dump.sh ├── dotnet_1_gc_threshold_1_dump.sh ├── dotnet_1exceptionDump1Thrown_dump.sh ├── dotnet_1exceptionDump2Thrown_dump.sh ├── dotnet_2WildcardExceptionDump2Thrown_dump.sh ├── dotnet_2exceptionDump2Thrown_dump.sh ├── dotnet_3_gc_thresholds_3_dumps.sh ├── dotnet_LOH_thresholds_3_dumps.sh ├── dotnet_MemMultipleDumps.sh ├── dotnet_POH_thresholds_3_dumps.sh ├── dotnet_exception_notdump.sh ├── dotnet_gen_2_thresholds_3_dumps.sh ├── dotnet_sigint_procdump.sh ├── dotnet_wildcardexception_notdump.sh ├── high_cpu.sh ├── high_cpu_by_name.sh ├── high_cpu_custom_core_file_name.sh ├── high_cpu_nonexisting_output_directory.sh ├── high_cpu_notdump.sh ├── high_cpu_trigger_cpu_memory.sh ├── high_fd_by_name.sh ├── high_fd_notdump.sh ├── high_mem.sh ├── high_mem_notdump.sh ├── high_mem_trigger_cpu_memory.sh ├── high_tc_by_name.sh ├── high_tc_notdump.sh ├── low_cpu.sh ├── low_cpu_by_name.sh ├── low_cpu_notdump.sh ├── low_cpu_trigger_cpu_memory.sh ├── low_mem.sh ├── low_mem_notdump.sh ├── low_mem_trigger_cpu_memory.sh └── ondemand.sh ├── scenarios_mac ├── high_cpu.sh ├── high_fd_by_name.sh ├── high_mem.sh └── high_tc_by_name.sh └── signal ├── makefile ├── signaltest └── signaltest.c /.devcontainer/Dockerfile_AzureLinux: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/cbl-mariner/base/core:2.0 2 | 3 | # Install dependencies 4 | COPY install-azurelinux-dependencies.sh /usr/local/bin/install_dependencies.sh 5 | RUN chmod +x /usr/local/bin/install_dependencies.sh && \ 6 | /usr/local/bin/install_dependencies.sh -------------------------------------------------------------------------------- /.devcontainer/Dockerfile_Rocky: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/mirror/docker/library/rockylinux:8 2 | 3 | # Install dependencies 4 | COPY install-rocky-dependencies.sh /usr/local/bin/install_dependencies.sh 5 | RUN chmod +x /usr/local/bin/install_dependencies.sh && \ 6 | /usr/local/bin/install_dependencies.sh -------------------------------------------------------------------------------- /.devcontainer/Dockerfile_Ubuntu: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/mirror/docker/library/ubuntu:20.04 2 | 3 | # To make it easier for build and release pipelines to run apt-get, 4 | # configure apt to not require confirmation (assume the -y argument by default) 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | # Install dependencies 8 | COPY install-ubuntu-dependencies.sh /usr/local/bin/install_dependencies.sh 9 | RUN chmod +x /usr/local/bin/install_dependencies.sh && \ 10 | /usr/local/bin/install_dependencies.sh -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu 3 | { 4 | "name": "ProcDump for Linux Development Container", 5 | "build": { 6 | // If you want to use a different docker file (such as Dockerfile_Rocky) you can specify it here 7 | "dockerfile": "Dockerfile_Ubuntu" 8 | }, 9 | "customizations": { 10 | "vscode": { 11 | "extensions": [ 12 | "ms-vscode.cpptools", 13 | "ms-vscode.cpptools-extension-pack", 14 | "ms-vscode.makefile-tools" 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.devcontainer/install-azurelinux.dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # install all needed packages for builds 4 | yum install -y ca-certificates \ 5 | git \ 6 | gdb \ 7 | zlib-devel \ 8 | gcc \ 9 | rpm-build \ 10 | make \ 11 | curl \ 12 | libcurl-devel \ 13 | libicu-devel \ 14 | libunwind-devel \ 15 | nmap \ 16 | wget \ 17 | clang \ 18 | glibc-devel \ 19 | kernel-headers-5.15.125.1-2.cm2.noarch \ 20 | binutils \ 21 | lsb-release \ 22 | cmake \ 23 | bpftool \ 24 | libbpf-devel \ 25 | sudo \ 26 | which 27 | 28 | # install JQ since it doesn't have a .rpm package 29 | curl https://stedolan.github.io/jq/download/linux64/jq > /usr/bin/jq && chmod +x /usr/bin/jq 30 | 31 | # install .net core 6 for ESRP signing and integration tests 32 | yum install -y dotnet-sdk-6.0 33 | 34 | # Update packages to latest 35 | yum update -y -------------------------------------------------------------------------------- /.devcontainer/install-rocky-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "assumeyes=1" >> /etc/yum.conf 4 | yum install http://opensource.wandisco.com/rhel/8/git/x86_64/wandisco-git-release-8-1.noarch.rpm 5 | dnf install dnf-plugins-core && dnf install epel-release && dnf config-manager --set-enabled powertools && dnf update 6 | yum install git \ 7 | gdb \ 8 | python3 \ 9 | zlib-devel \ 10 | gcc-toolset-10 \ 11 | rpm-build \ 12 | make \ 13 | curl \ 14 | libcurl-devel \ 15 | libicu-devel \ 16 | libunwind-devel \ 17 | nmap \ 18 | wget \ 19 | clang \ 20 | redhat-lsb \ 21 | cmake \ 22 | elfutils-libelf-devel \ 23 | libbpf-devel \ 24 | bpftool 25 | 26 | pip3 uninstall -y setuptools 27 | pip3 uninstall -y pip 28 | curl https://stedolan.github.io/jq/download/linux64/jq > /usr/bin/jq && chmod +x /usr/bin/jq 29 | yum install dotnet-runtime-6.0 30 | yum install dotnet-sdk-6.0 -------------------------------------------------------------------------------- /.devcontainer/install-ubuntu-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes 3 | export DEBIAN_FRONTEND=noninteractive 4 | apt-get update 5 | apt -y install software-properties-common 6 | apt-get update 7 | apt upgrade -y \ 8 | && apt-get install -y --no-install-recommends \ 9 | ca-certificates \ 10 | curl \ 11 | jq \ 12 | git \ 13 | cmake \ 14 | iputils-ping \ 15 | libcurl4 \ 16 | libicu70 \ 17 | libunwind8 \ 18 | netcat \ 19 | gdb \ 20 | zlib1g-dev \ 21 | stress-ng \ 22 | wget \ 23 | dpkg-dev \ 24 | fakeroot \ 25 | lsb-release \ 26 | gettext \ 27 | liblocale-gettext-perl \ 28 | pax \ 29 | libelf-dev \ 30 | clang \ 31 | llvm \ 32 | build-essential \ 33 | libbpf-dev \ 34 | sudo 35 | 36 | # Build and install bpftool 37 | rm -rf /usr/sbin/bpftool 38 | git clone --recurse-submodules https://github.com/libbpf/bpftool.git 39 | cd bpftool/src 40 | make install 41 | ln -s /usr/local/sbin/bpftool /usr/sbin/bpftool 42 | 43 | # install debbuild 44 | wget https://github.com/debbuild/debbuild/releases/download/22.02.1/debbuild_22.02.1-0ubuntu20.04_all.deb \ 45 | && dpkg -i debbuild_22.02.1-0ubuntu20.04_all.deb 46 | 47 | arch=$(uname -m) 48 | if [[ "$arch" == "aarch64" ]]; then 49 | wget https://dot.net/v1/dotnet-install.sh 50 | chmod +x dotnet-install.sh 51 | ./dotnet-install.sh --channel 8.0 --install-dir /usr/share/dotnet 52 | else 53 | # Not ARM64, we can install dotnet the normal way. 54 | # install .NET 8 for signing process and integration tests 55 | apt install -y dotnet-runtime-8.0 56 | apt install -y dotnet-sdk-8.0 57 | fi 58 | -------------------------------------------------------------------------------- /.github/compliance/inventory.yml: -------------------------------------------------------------------------------- 1 | inventory: 2 | - source: DirectOwners 3 | isProduction: false 4 | items: 5 | - id: marioh@microsoft.com 6 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Expected behavior 2 | 3 | ### Actual behavior 4 | 5 | ### Steps to reproduce the behavior 6 | 1. 7 | 2. 8 | 3. 9 | 10 | ### System information (e.g., distro, kernel version, etc.) 11 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | # For Branch-Protection check. Only the default branch is supported. See 8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 9 | branch_protection_rule: 10 | # To guarantee Maintained check is occasionally updated. See 11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 12 | schedule: 13 | - cron: '34 21 * * 5' 14 | push: 15 | branches: [ "master" ] 16 | 17 | # Declare default permissions as read only. 18 | permissions: read-all 19 | 20 | jobs: 21 | analysis: 22 | name: Scorecard analysis 23 | runs-on: ubuntu-latest 24 | permissions: 25 | # Needed to upload the results to code-scanning dashboard. 26 | security-events: write 27 | # Needed to publish results and get a badge (see publish_results below). 28 | id-token: write 29 | # Uncomment the permissions below if installing in a private repository. 30 | # contents: read 31 | # actions: read 32 | 33 | steps: 34 | - name: "Checkout code" 35 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 36 | with: 37 | persist-credentials: false 38 | 39 | - name: "Run analysis" 40 | uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 41 | with: 42 | results_file: results.sarif 43 | results_format: sarif 44 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 45 | # - you want to enable the Branch-Protection check on a *public* repository, or 46 | # - you are installing Scorecard on a *private* repository 47 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. 48 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 49 | 50 | # Public repositories: 51 | # - Publish results to OpenSSF REST API for easy access by consumers 52 | # - Allows the repository to include the Scorecard badge. 53 | # - See https://github.com/ossf/scorecard-action#publishing-results. 54 | # For private repositories: 55 | # - `publish_results` will always be set to `false`, regardless 56 | # of the value entered here. 57 | publish_results: true 58 | 59 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF 60 | # format to the repository Actions tab. 61 | - name: "Upload artifact" 62 | uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 63 | with: 64 | name: SARIF file 65 | path: results.sarif 66 | retention-days: 5 67 | 68 | # Upload the results to GitHub's code scanning dashboard (optional). 69 | # Commenting out will disable upload of results to your repo's Code Scanning dashboard 70 | - name: "Upload to code-scanning" 71 | uses: github/codeql-action/upload-sarif@v3 72 | with: 73 | sarif_file: results.sarif 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE folders & Files 2 | .vs/ 3 | .vscode/ 4 | !.vscode/settings.json 5 | !.vscode/tasks.json 6 | !.vscode/launch.json 7 | !.vscode/extensions.json 8 | 9 | # Prerequisites 10 | *.d 11 | 12 | # Object files 13 | *.o 14 | *.ko 15 | *.obj 16 | *.elf 17 | 18 | # Linker output 19 | *.ilk 20 | *.map 21 | *.exp 22 | 23 | # Precompiled Headers 24 | *.gch 25 | *.pch 26 | 27 | # Libraries 28 | *.lib 29 | *.a 30 | *.la 31 | *.lo 32 | *.o 33 | 34 | # Project directories 35 | bin/ 36 | release/ 37 | pkgbuild/ 38 | obj/ 39 | build/ 40 | -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | # Linux 2 | ## Containerized Builds 3 | The Dockerfiles in this repo (located under the `.devcontainer` directory) are the same Dockerfiles that are used on the backend build systems when a PR is built as part of the PR checks. This provides an easy and convenient way to ensure that any changes being made can be built using the same backend infrastructure. 4 | 5 | There are three Dockerfiles available: 6 | 7 | - `Dockerfile_Ubuntu` (default) 8 | - `Dockerfile_Rocky` 9 | - `Dockerfile_AzureLinux` 10 | 11 | There are two primary ways to build using containers: 12 | 13 | 1. If you use VS Code the repo has support for VS Code Dev Containers. To use this functionality, you need to have the VS Code Dev Containers extension installed as well as Docker. Once installed open VS Code and the `ProcDump-for-Linux` folder and go to command palette and select "Dev Containers: Rebuild and Reopen in Container". 14 | Once the container has finished building, you will be connected to the newly built container. You can also switch which Dockerfile you are using by setting the `dockerfile` field in the file `devcontainer.json`. 15 | For more information about VS Code Dev Containers please see - https://code.visualstudio.com/docs/devcontainers/containers 16 | 17 | 2. Use the Dockerfiles located under the `.devcontainer` directory and build/run docker locally. 18 | 19 | To build inside the container: 20 | ```sh 21 | mkdir build 22 | cd build 23 | cmake .. 24 | make 25 | ``` 26 | ## Local Builds 27 | ### Prerequisites 28 | #### Ubuntu 29 | ``` 30 | sudo apt update 31 | sudo apt -y install gcc cmake make clang clang-12 gdb zlib1g-dev libelf-dev build-essential libbpf-dev linux-tools-common linux-tools-$(uname -r) 32 | ``` 33 | 34 | #### Rocky Linux 35 | ``` 36 | sudo yum install gcc make cmake clang gdb zlib-devel elfutils-libelf-devel libbpf-devel bpftool 37 | ``` 38 | 39 | ### Build 40 | ```sh 41 | mkdir build 42 | cd build 43 | cmake .. 44 | make 45 | ``` 46 | 47 | ## Building Packages 48 | The distribution packages for Procdump for Linux are constructed utilizing `dpkg-deb` for Debian targets and `rpmbuild` for Fedora targets. 49 | 50 | Create a deb package: 51 | ```sh 52 | make deb 53 | ``` 54 | 55 | Create an rpm package: 56 | ```sh 57 | make rpm 58 | ``` 59 | 60 | # macOS 61 | ### Prerequisites 62 | Install the clang tool chain. 63 | 64 | ### Build 65 | ```sh 66 | mkdir build 67 | cd build 68 | cmake .. 69 | make 70 | ``` 71 | 72 | ## Building Packages 73 | ```sh 74 | make brew 75 | ``` 76 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](opencode@microsoft.com) with any additional questions or comments. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Before we can accept a pull request from you, you'll need to sign a [Contributor License Agreement (CLA)](https://cla.microsoft.com). It is an automated process and you only need to do it once. 4 | To enable us to quickly review and accept your pull requests, always create one pull request per issue and link the issue in the pull request. Never merge multiple requests in one unless they have the same root cause. Be sure to follow our Coding Guidelines and keep code changes as small as possible. Avoid pure formatting changes to code that has not been modified otherwise. Pull requests should contain tests whenever possible. 5 | 6 | # Branching 7 | The master branch contains current development. While CI should ensure that master always builds, it is still considered pre-release code. Release checkpoints will be put into stable branches for maintenance. 8 | 9 | To contribute, fork the repository and create a branch in your fork for your work. Please keep branch names short and descriptive. Please direct PRs into the upstream master branch. 10 | 11 | ## Build and run from source 12 | Please refer to [Build instructions](BUILD.md) for details on how to build ProcDump for Linux. 13 | 14 | ## Testing 15 | * There are a multitude of tests included in the `tests` directory of the repository. 16 | * Add new tests corresponding to your change, if applicable. Include tests when adding new features. When fixing bugs, start with adding a test that highlights how the current behavior is broken. 17 | * Make sure that the tests are all passing, including your new tests. 18 | 19 | ## Creating integration tests 20 | The integration tests run using the local procdump built from source. Individual test cases are written as bash scripts and need to be inside `/tests/integration/scenarios/` in order to be called automatically by `run.sh`. 21 | 22 | Test scripts will return `0` when they succeed and `1` when they fail. 23 | 24 | Most of the tests are written using [stress-ng](https://wiki.ubuntu.com/Kernel/References/stress-ng "stress-ng manual"), but you can write your own code to simulate the scenario you require. 25 | 26 | After writing a new test, run the `run.sh` script from $build/tests/integration and verify that no tests fail. 27 | 28 | ## Pull Requests 29 | * Always tag a work item or issue with a pull request. 30 | * Limit pull requests to as few issues as possible, preferably 1 per PR 31 | 32 | ## Coding Guidelines 33 | ## Indentation 34 | We welcome all whitespace characters, but prefer space expanded tabs. 35 | ## Names 36 | * Do not use `typedef`, we like to know what is a struct and what is a type 37 | * Use PascalCase for: 38 | * `struct` names 39 | * `enum` names 40 | * `function` names 41 | * Use camelCase for: 42 | * `local variable` names 43 | * `enum` names should start with a captol `E`, e.g., `enum ECoreDumpType` 44 | * Global variables should be prefixed with `g_`, e.g., `struct ProcDumpConfiguration g_Config;` 45 | * `struct Handle`s that contain a `struct Event` should have variable names prefixed by `evt`, e.g., `struct Handle evtIsQuit;` 46 | * `struct Handle`s that contain a `sem_t` should have variable names prefixed by `sem`, e.g., `struct Handle semDumpSlot;` 47 | * Please use whole words when possible 48 | ## Style 49 | * Curly brackets, `{ }`, should go on the next line after whatever necessitates them 50 | * For structs, put on same line 51 | * Put a space before the open paren, `(`, with `for`, `while`, `if`, and `switch` statements 52 | * No space after function names and before parameter lists 53 | * The `*` for a pointer goes next to the variable name, e.g., `char *variable` 54 | * Declare 1 variable at a time 55 | * Declare all local variables at the start of a function 56 | * Either initialize upon declaration, or initialize before logic 57 | * The exception is `for` loop iterators 58 | * Wrap header (`.h`) files with: 59 | ```c 60 | #ifndef HEADER_FILE_NAME_H 61 | #define HEADER_FILE_NAME_H 62 | //... 63 | #endif // HEADER_FILE_NAME_H 64 | ``` 65 | 66 | ## Trace and Error Handling 67 | For system calls and other "failable" function calls, please make use of the `Trace` macro and the logging methods, like so: 68 | 69 | ```c 70 | int rc = 0; 71 | if ((rc = FailableFunction(...)) != 0) 72 | { 73 | Log(error, INTERNAL_ERROR); 74 | Trace("WriteCoreDump: failed pthread_setcanceltype."); 75 | exit(-1); 76 | } 77 | ``` 78 | ## Example of style 79 | 80 | ```c 81 | struct Baz { 82 | int Foobar; 83 | } 84 | 85 | int main(int argc, char *argv[]) 86 | { 87 | int foo = 0; 88 | int bar = 1; 89 | char[64] str = "This is a string"; 90 | struct Baz baz = { 10 }; 91 | 92 | while (foo < 10) 93 | { 94 | foo++; 95 | } 96 | 97 | for (int i = 0; i < foo; i++) 98 | { 99 | printf(str); 100 | baz.Foobar--; 101 | } 102 | 103 | printf("baz.Foobar is %d", baz.Foobar); 104 | 105 | return bar - 1; 106 | } 107 | ``` 108 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Install ProcDump 2 | 3 | ## Azure Linux 2.0 4 | ```sh 5 | sudo yum install procdump 6 | ``` 7 | 8 | ## Ubuntu 20.04, 22.04, 24.04 9 | #### 1. Register Microsoft key and feed 10 | ```sh 11 | wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 12 | sudo dpkg -i packages-microsoft-prod.deb 13 | ``` 14 | 15 | #### 2. Install Procdump 16 | ```sh 17 | sudo apt-get update 18 | sudo apt-get install procdump 19 | ``` 20 | 21 | ## Debian 11 22 | #### 1. Register Microsoft key and feed 23 | ```sh 24 | wget -q https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 25 | sudo dpkg -i packages-microsoft-prod.deb 26 | ``` 27 | 28 | #### 2. Install Procdump 29 | ```sh 30 | sudo apt-get update 31 | sudo apt-get install apt-transport-https 32 | sudo apt-get update 33 | sudo apt-get install procdump 34 | ``` 35 | 36 | ## Debian 12 37 | #### 1. Register Microsoft key and feed 38 | ```sh 39 | wget -q https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 40 | sudo dpkg -i packages-microsoft-prod.deb 41 | ``` 42 | 43 | #### 2. Install Procdump 44 | ```sh 45 | sudo apt-get update 46 | sudo apt-get install apt-transport-https 47 | sudo apt-get update 48 | sudo apt-get install procdump 49 | ``` 50 | 51 | ## Fedora 38 52 | #### 1. Register Microsoft key and feed 53 | ```sh 54 | sudo rpm -Uvh https://packages.microsoft.com/config/fedora/38/packages-microsoft-prod.rpm 55 | ``` 56 | 57 | #### 2. Install Procdump 58 | ```sh 59 | sudo dnf install procdump 60 | ``` 61 | 62 | ## Fedora 39 63 | #### 1. Register Microsoft key and feed 64 | ```sh 65 | sudo rpm -Uvh https://packages.microsoft.com/config/fedora/39/packages-microsoft-prod.rpm 66 | ``` 67 | 68 | #### 2. Install Procdump 69 | ```sh 70 | sudo dnf install procdump 71 | ``` 72 | 73 | ## Fedora 40 74 | #### 1. Register Microsoft key and feed 75 | ```sh 76 | sudo rpm -Uvh https://packages.microsoft.com/config/fedora/40/packages-microsoft-prod.rpm 77 | ``` 78 | 79 | #### 2. Install Procdump 80 | ```sh 81 | sudo dnf install procdump 82 | ``` 83 | 84 | ## RHEL 7 85 | #### 1. Register Microsoft key and feed 86 | ```sh 87 | sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm 88 | ``` 89 | 90 | #### 2. Install Procdump 91 | ```sh 92 | sudo yum install procdump 93 | ``` 94 | 95 | ## RHEL 8 96 | #### 1. Register Microsoft key and feed 97 | ```sh 98 | sudo rpm -Uvh https://packages.microsoft.com/config/rhel/8/packages-microsoft-prod.rpm 99 | ``` 100 | 101 | #### 2. Install Procdump 102 | ```sh 103 | sudo yum install procdump 104 | ``` 105 | 106 | ## RHEL 9 107 | #### 1. Register Microsoft key and feed 108 | ```sh 109 | sudo rpm -Uvh https://packages.microsoft.com/config/rhel/9/packages-microsoft-prod.rpm 110 | ``` 111 | 112 | #### 2. Install Procdump 113 | ```sh 114 | sudo yum install procdump 115 | ``` 116 | 117 | ## CentOS 7 118 | #### 1. Register Microsoft key and feed 119 | ```sh 120 | sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm 121 | ``` 122 | 123 | #### 2. Install Procdump 124 | ```sh 125 | sudo yum install procdump 126 | ``` 127 | 128 | ## openSUSE 15 129 | #### 1. Register Microsoft key and feed 130 | ```sh 131 | sudo zypper install libicu 132 | sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc 133 | wget -q https://packages.microsoft.com/config/opensuse/15/prod.repo 134 | sudo mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo 135 | sudo chown root:root /etc/zypp/repos.d/microsoft-prod.repo 136 | ``` 137 | 138 | #### 2. Install Procdump 139 | ```sh 140 | sudo zypper install procdump 141 | ``` 142 | 143 | ## SLES 12 144 | #### 1. Register Microsoft key and feed 145 | ```sh 146 | sudo rpm -Uvh https://packages.microsoft.com/config/sles/12/packages-microsoft-prod.rpm 147 | ``` 148 | 149 | #### 2. Install Procdump 150 | ```sh 151 | sudo zypper install procdump 152 | ``` 153 | 154 | ## SLES 15 155 | #### 1. Register Microsoft key and feed 156 | ```sh 157 | sudo rpm -Uvh https://packages.microsoft.com/config/sles/15/packages-microsoft-prod.rpm 158 | ``` 159 | 160 | #### 2. Install Procdump 161 | ```sh 162 | sudo zypper install procdump 163 | ``` 164 | 165 | ## macOS 166 | To install ProcDump for Mac, you'll need to install [Homebrew](https://brew.sh) if you haven't already. 167 | 168 | 1. Add the Sysinternals tap: 169 | ```bash 170 | brew tap Microsoft/sysinternalstap 171 | ``` 172 | 173 | 1. Install ProcDump: 174 | ```bash 175 | brew install procdump 176 | ``` 177 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Azure build pipelines for Procdump-for-Linux 2 | trigger: 3 | branches: 4 | include: 5 | - release/* 6 | exclude: 7 | - dev/* 8 | - test/* 9 | 10 | pr: 11 | - master 12 | 13 | resources: 14 | repositories: 15 | - repository: ProcDump 16 | type: github 17 | endpoint: sysinternals 18 | name: Microsoft/ProcDump-for-Linux 19 | - repository: obtemplates 20 | type: git 21 | name: OneBranch.Pipelines/GovernedTemplates 22 | ref: refs/heads/main 23 | extends: 24 | template: v2/OneBranch.NonOfficial.CrossPlat.yml@obtemplates 25 | parameters: 26 | globalSdl: 27 | tsa: 28 | enabled: false 29 | policheck: 30 | break: true 31 | stages: 32 | - stage: "Build_Run_Tests" 33 | jobs: 34 | - job: "ProcDump_Build_ARM64_Run_Tests" 35 | pool: 36 | type: linux 37 | hostArchitecture: arm64 38 | variables: 39 | LinuxContainerImage: 'mcr.microsoft.com/mirror/docker/library/ubuntu:22.04' 40 | ob_outputDirectory: '$(Build.SourcesDirectory)\out' 41 | steps: 42 | - script: | 43 | DEBIAN_FRONTEND=noninteractive apt -y update && apt install rsyslog -y 44 | rm -f /run/rsyslogd.pid 45 | service rsyslog start || true 46 | displayName: 'Enable syslog' 47 | 48 | - script: | 49 | DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" sudo 50 | chmod +x .devcontainer/install-ubuntu-dependencies.sh 51 | .devcontainer/install-ubuntu-dependencies.sh 52 | displayName: "Install pre-reqs for Ubuntu" 53 | 54 | - script: | 55 | clang --version 56 | clang++ --version 57 | gcc --version 58 | displayName: 'List compiler versions' 59 | 60 | - template: templates/build.yaml@ProcDump 61 | 62 | - script: | 63 | cd procdump_build/tests/integration 64 | ./run.sh 65 | displayName: 'Run unit tests' 66 | 67 | - job: "ProcDump_Build_AMD64_Run_Tests" 68 | pool: 69 | type: linux 70 | variables: 71 | LinuxContainerImage: 'mcr.microsoft.com/mirror/docker/library/ubuntu:22.04' 72 | ob_outputDirectory: '$(Build.SourcesDirectory)\out' 73 | steps: 74 | - script: | 75 | DEBIAN_FRONTEND=noninteractive apt -y update && apt install rsyslog -y 76 | rm -f /run/rsyslogd.pid 77 | service rsyslog start || true 78 | displayName: 'Enable syslog' 79 | 80 | - script: | 81 | DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" sudo 82 | chmod +x .devcontainer/install-ubuntu-dependencies.sh 83 | .devcontainer/install-ubuntu-dependencies.sh 84 | displayName: "Install pre-reqs for Ubuntu" 85 | 86 | - script: | 87 | clang --version 88 | clang++ --version 89 | gcc --version 90 | displayName: 'List compiler versions' 91 | 92 | - template: templates/build.yaml@ProcDump 93 | 94 | - script: | 95 | apt install -y iproute2 96 | echo "Check port 5032" && ss -tulnp | grep 5032 97 | cd procdump_build/tests/integration 98 | ./run.sh 99 | displayName: 'Run unit tests' 100 | 101 | - job: "ProcDump_Build_MACOS_Run_Tests" 102 | pool: 103 | type: linux 104 | isCustom: true 105 | name: Azure Pipelines 106 | vmImage: 'macOS-latest' 107 | variables: 108 | ob_outputDirectory: '$(Build.SourcesDirectory)/out' 109 | steps: 110 | 111 | - script: | 112 | sw_vers 113 | displayName: 'Diagnostics' 114 | 115 | - template: templates/build.yaml@ProcDump 116 | 117 | - script: | 118 | cd procdump_build/tests/integration 119 | sudo ./run.sh 120 | displayName: 'Run unit tests' 121 | -------------------------------------------------------------------------------- /dist/DEBIAN.in/control.in: -------------------------------------------------------------------------------- 1 | Package: procdump 2 | Version: @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@ 3 | Architecture: @ARCHITECTURE@ 4 | Maintainer: Sysinternals 5 | Description: Sysinternals process dump utility 6 | ProcDump is a command-line utility whose primary purpose is monitoring an application 7 | for various resources and generating crash dumps during a spike that an administrator 8 | or developer can use to determine the cause of the issue. ProcDump also serves as a 9 | general process dump utility that you can embed in other scripts. 10 | Depends: zlib1g, gdb (>= 7.6.1) 11 | License: MIT -------------------------------------------------------------------------------- /dist/SPECS.in/spec.in: -------------------------------------------------------------------------------- 1 | Name: procdump 2 | Version: @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@ 3 | Release: @PROJECT_VERSION_TWEAK@%{?dist} 4 | Summary: Sysinternals process dump utility 5 | 6 | License: MIT 7 | URL: https://github.com/Microsoft/ProcDump-for-Linux 8 | 9 | %description 10 | Sysinternals process dump utility 11 | 12 | %install 13 | rm -rf $RPM_BUILD_ROOT 14 | mkdir -p $RPM_BUILD_ROOT/%{_bindir} 15 | cp procdump $RPM_BUILD_ROOT/%{_bindir} 16 | mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1 17 | cp procdump.1.gz $RPM_BUILD_ROOT/usr/share/man/man1 18 | 19 | %clean 20 | rm -rf $RPM_BUILD_ROOT 21 | 22 | %files 23 | %{_bindir}/procdump 24 | /usr/share/man/man1/procdump.1.gz 25 | 26 | %changelog 27 | @CHANGE_LOG@ 28 | 29 | %description 30 | ProcDump is a command-line utility whose primary purpose is monitoring an application 31 | for various resources and generating crash dumps during a spike that an administrator 32 | or developer can use to determine the cause of the issue. ProcDump also serves as a 33 | general process dump utility that you can embed in other scripts. -------------------------------------------------------------------------------- /dist/changelog: -------------------------------------------------------------------------------- 1 | * Mon Mar 17 2025 Mario Hewardt - 3.4.1 2 | - Fix bug that removes : from the core dump file names 3 | 4 | * Wed Jan 29 2025 Mario Hewardt - 3.4 5 | - Adds ARM64 support and compilation fixes 6 | 7 | * Sat May 25 2024 Mario Hewardt - 3.3 8 | - Adds improvements related to containerized workflows 9 | 10 | * Mon Feb 5 2024 Mario Hewardt - 3.2 11 | - Adds mmap/munmap to resource tracking 12 | 13 | * Tue Jan 23 2024 Mario Hewardt - 3.1 14 | - Adds ability to specify multiple comma separated signals 15 | - Adds the new -mc switch which controls what type of memory is included in the core dumps 16 | 17 | * Tue Dec 5 2023 Mario Hewardt - 3.0 18 | - Adds resource tracking and reporting feature 19 | 20 | * Wed Sep 6 2023 Mario Hewardt - 2.2 21 | - Adds Azure Linux package 22 | - Fixes memory leaks 23 | 24 | * Fri Aug 11 2023 Mario Hewardt - 2.1 25 | - Fixes bug that can lead to crash in monitored .NET process 26 | - Adds thread id to profiler tracing 27 | 28 | * Wed Jul 26 2023 Mario Hewardt - 2.0 29 | - -gcm allows you to specify generation or heap (LOH and POH) thresholds. 30 | - -gcgen allows you to create a dump at the start and end of a GC. 31 | - Allow multiple thresholds for memory trigger (-m) 32 | 33 | * Thu Jun 1 2023 Mario Hewardt - 1.5 34 | - security hardening 35 | 36 | * Fri Mar 3 2023 Mario Hewardt - 1.4.1 37 | - added the capability to dump on .NET 1st chance exception messages 38 | - added wildcard support for .NET exception filters 39 | 40 | * Mon Dec 12 2022 Mario Hewardt - 1.4 41 | - added the capability to dump on .NET 1st chance exceptions (-e and -f) 42 | 43 | * Mon Sep 26 2022 Javid Habibi - 1.3 44 | - added process group trigger 45 | - BREAKING CHANGE: rework CLI interface to match that of Procdump for Windows 46 | - various small bug fixes 47 | 48 | * Tue Sep 14 2021 Javid Habibi - 1.2 49 | - added signal trigger 50 | - added custom filepath for memory dump generation 51 | - various small bug fixes 52 | 53 | * Fri Apr 3 2020 Javid Habibi - 1.1.1 54 | - implimented thread and file descriptor count trigger 55 | - added polling interval switch 56 | 57 | * Mon Dec 9 2019 Javid Habibi - 1.1 58 | - Added support for .Net Core 3.x+ core dump generation that results in more manageable core dump sizes 59 | 60 | * Fri Nov 8 2019 Javid Habibi - 1.0.2 61 | - implimented -w target flag 62 | - fixed pthread cancellation bug 63 | - added additional error checking for null process names 64 | - implimented a minimal kernel check validation 65 | - various bug fixes 66 | 67 | * Wed Jan 10 2018 Javid Habibi - 1.0.1 68 | - fixed potential deadlock upon malloc failing 69 | - fixed improper process name parsing and sanitizing process 70 | name for dump file generation 71 | - fixed various typos 72 | - fixed post-build check failures on openSUSE 73 | 74 | * Tue Dec 05 2017 Javid Habibi - 1.0 75 | - Initial release -------------------------------------------------------------------------------- /dist/procdump.spec.in: -------------------------------------------------------------------------------- 1 | Name: procdump 2 | Version: @PKG_VERSION@ 3 | Release: %_Revision 4 | Summary: Sysinternals process dump utility 5 | 6 | %if "%{_vendor}" == "debbuild" 7 | Group: devel 8 | %else 9 | Group: Development/Tools%{?suse_version:/Other} 10 | %endif 11 | 12 | Packager: OSS Tooling Dev Team 13 | 14 | License: MIT 15 | URL: https://github.com/Microsoft/ProcDump-for-Linux 16 | Source0: %{url}/releases/download/%{version}/%{name}-%{version}.tar.gz 17 | 18 | BuildRequires: gcc, make 19 | 20 | %undefine _annotated_build 21 | 22 | %if "%{_vendor}" == "debbuild" 23 | BuildRequires: zlib1g-dev 24 | %else 25 | BuildRequires: zlib-devel 26 | %endif 27 | 28 | Requires: gdb >= 7.6.1 29 | 30 | %description 31 | ProcDump is a command-line utility whose primary purpose is monitoring an application 32 | for various resources and generating crash dumps during a spike that an administrator 33 | or developer can use to determine the cause of the issue. ProcDump also serves as a 34 | general process dump utility that you can embed in other scripts. 35 | 36 | 37 | %prep 38 | %autosetup 39 | 40 | 41 | %build 42 | # The makefile doesn't like %%make_build (parallel make) 43 | make CFLAGS="%{optflags}" 44 | 45 | 46 | %install 47 | %make_install 48 | 49 | 50 | %files 51 | %license LICENSE 52 | %doc README.md procdump.gif 53 | %{_bindir}/procdump 54 | %{_mandir}/man1/procdump.1* 55 | 56 | 57 | 58 | %changelog 59 | * Wed Sep 6 2023 Mario Hewardt - 2.2 60 | - Adds Azure Linux package 61 | - Fixes memory leaks 62 | 63 | * Fri Aug 11 2023 Mario Hewardt - 2.1 64 | - Fixes bug that can lead to crash in monitored .NET process 65 | - Adds thread id to profiler tracing 66 | 67 | * Wed Jul 26 2023 Mario Hewardt - 2.0 68 | - -gcm allows you to specify generation or heap (LOH and POH) thresholds. 69 | - -gcgen allows you to create a dump at the start and end of a GC. 70 | - Allow multiple thresholds for memory trigger (-m) 71 | 72 | * Thu Jun 1 2023 Mario Hewardt - 1.5 73 | - security hardening 74 | 75 | * Fri Mar 3 2023 Mario Hewardt - 1.4.1 76 | - added the capability to dump on .NET 1st chance exception messages 77 | - added wildcard support for .NET exception filters 78 | 79 | * Mon Dec 12 2022 Mario Hewardt - 1.4 80 | - added the capability to dump on .NET 1st chance exceptions (-e and -f) 81 | 82 | * Mon Sep 26 2022 Javid Habibi - 1.3 83 | - added process group trigger 84 | - BREAKING CHANGE: rework CLI interface to match that of Procdump for Windows 85 | - various small bug fixes 86 | 87 | * Tue Sep 14 2021 Javid Habibi - 1.2 88 | - added signal trigger 89 | - added custom filepath for memory dump generation 90 | - various small bug fixes 91 | 92 | * Fri Apr 3 2020 Javid Habibi - 1.1.1 93 | - implimented thread and file descriptor count trigger 94 | - added polling interval switch 95 | 96 | * Mon Dec 9 2019 Javid Habibi - 1.1 97 | - Added support for .Net Core 3.x+ core dump generation that results in more manageable core dump sizes 98 | 99 | * Fri Nov 8 2019 Javid Habibi - 1.0.2 100 | - implimented -w target flag 101 | - fixed pthread cancellation bug 102 | - added additional error checking for null process names 103 | - implimented a minimal kernel check validation 104 | - various bug fixes 105 | 106 | * Wed Jan 10 2018 Javid Habibi - 1.0.1 107 | - fixed potential deadlock upon malloc failing 108 | - fixed improper process name parsing and sanitizing process 109 | name for dump file generation 110 | - fixed various typos 111 | - fixed post-build check failures on openSUSE 112 | 113 | * Tue Dec 05 2017 Javid Habibi - 1.0 114 | - Initial release 115 | -------------------------------------------------------------------------------- /docs/coreclrintegration.md: -------------------------------------------------------------------------------- 1 | # Procdump and .NET Integration 2 | 3 | ## Core Dump Generation 4 | Procdump is a powerful production diagnostics tool that allows you to monitor processes for specific thresholds and generate core dumps based on a specified critera. For example, imagine that you were encountering sporadic CPU spikes in your web app and you would like to generate a core dump for offline analysis. With Procdump you can use the -c switch to specify the CPU threshold of interest (say, 90%) and Procdump will monitor the process and generate a core dump when the CPU goes above 90%. 5 | 6 | In order to understand how a core dump can help resolve production issues, we first have to understand what a core dump is. Essentially, a core dump is nothing more than a static snapshot of the contents of an applications memory. This content is written to a file that can later be loaded into a debugger and other tools to analyze the contents of memory and see if root cause can be determined. What makes core dumps great production debugging tools is that we don't have to worry about the application stopping while debugging is taking place (as is the case with live debugging where a debugger is attached to the application). How big are these dump files? Well, that depends on how much memory your application is consuming (remember, it roughly writes the contents of the application memory usage to the file). As you can imagine, if you are running a massive database application you could result in a core dump file that is many GB in size. Furthermore, on Linux, core dumps tend to be larger than on Windows. This presents a new challenge of how to effectively manage large core dump files. If you intend to copy the core dump file between production and development machines, it can be pretty time consuming. 7 | 8 | With the release of Procdump 1.1, we now recognize if the target application is a .NET application and use a special core dumping mechanism built into the runtime itself. This renders core dump files that are much smaller than normal while still maintaining all the neccessary information to troubleshoot the .NET application. You don't have to specify any new switches to use this new capability, Procdump automatically figures out if the capability is available and uses it. 9 | 10 | To get a feel for the size difference, let's take a look at a simple example. We created and ran a new .NET app using the webapp template: 11 | 12 | ```console 13 | dotnet new webapp -o TestWebApp 14 | dotnet run 15 | ``` 16 | 17 | This webapp does very little and as a matter of fact we won't even send any requests to it. Now, using Procdump (**1.0**), if we generate a core dump of the web app we end up with a file that is roughly 18GB in size. Pretty hefty for a simple web app that essentially does nothing. 18 | 19 | ```console 20 | -rw-r--r-- 1 root root 18127292104 Dec 4 11:37 core.3066 21 | ``` 22 | 23 | Using the same web app, let's use Procdump **1.1** to generate the core dump. This time the file size is much more reasonable: 24 | 25 | ```console 26 | -rw-rw-r-- 1 marioh marioh 273387520 Dec 4 11:44 TestWebApp_time_2019-12-04_11:44:03.3066 27 | ``` 28 | 29 | _Please note that by default the core dump will be placed into the same directory that the target application is running in._ 30 | 31 | This time the core dump file size is only about 273MB. Much better and much more managable. To convince ourselves that the core dump still contains all the neccessary data to debug .NET applications, we can try it out with dotnet-dump analyze (which is a REPL for SOS debugging): 32 | 33 | ```console 34 | dotnet-dump analyze TestWebApp_time_2019-12-04_11:44:03.3066 35 | > dumpheap -stat 36 | Statistics: 37 | MT Count TotalSize Class Name 38 | 00007f7b2f5e4288 1 24 System.Threading.TimerQueueTimer+<>c 39 | 00007f7b2f5e2738 1 24 System.Net.Sockets.SocketAsyncEngine+<>c 40 | ... 41 | ... 42 | ... 43 | 00007f7b2bcd4a18 397 109816 System.Char[] 44 | 00007f7b2b1514c0 628 110601 System.Byte[] 45 | 00007f7b2b145510 509 166528 System.Object[] 46 | 00007f7b2b150f90 4436 342956 System.String 47 | Total 32581 objects 48 | ``` 49 | 50 | How does Procdump achieve this magic? Turns out that .NET introduced the notion of a diagnostics server which at a high level enables external (out of process) tools to send diagnostics commands to the target process. In our case, we used the dump commands that are available but you can also use the diagnostics server to issue trace commands. For more information, please see the following documentation: 51 | 52 | [.NET Diagnostics](https://github.com/dotnet/diagnostics) 53 | 54 | ## Monitoring for exceptions 55 | Often times, it's super useful to be able to get a core dump when a .NET application throws an exception. Starting in ProcDump **1.4** it now has the capability to do so by using the 56 | -e and -f switches. To better understand how ProcDump accomplishes this it's important to note that it requires ProcDump to inject a profiler into the target .NET process. This should 57 | be minimal overhead (unless your .NET application throws thousands of exceptions). 58 | 59 | When ProcDump monitors for exceptions, in addition to injecting the profiler into the target process, it also sets up a couple of IPC channels that allows the profiler to talk to 60 | ProcDump (and vice versa) to communicate status: 61 | 62 | ProcDump acts as a server that listens for status messages from the profiler (success, failure etc). 63 | Profiler acts a server that listens for cancellation requests from ProcDump (in case of SIGINT) 64 | 65 | In all cases, the profiler will be unloaded from the target .NET process once ProcDump has completed monitoring. -------------------------------------------------------------------------------- /docs/coredumpazure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/ProcDump-for-Linux/f3d469ac1aa242e52beb3647ef9beb23b02c4247/docs/coredumpazure.jpg -------------------------------------------------------------------------------- /docs/deploy.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: 5 | provisioner: file.csi.azure.com 6 | allowVolumeExpansion: true 7 | mountOptions: 8 | - dir_mode=0777 9 | - file_mode=0777 10 | - uid=0 11 | - gid=0 12 | - mfsymlinks 13 | - cache=strict 14 | - actimeo=30 15 | parameters: 16 | skuName: Standard_LRS 17 | --- 18 | apiVersion: v1 19 | kind: PersistentVolumeClaim 20 | metadata: 21 | name: 22 | spec: 23 | accessModes: 24 | - ReadWriteMany 25 | storageClassName: 26 | resources: 27 | requests: 28 | storage: 5Gi 29 | --- 30 | apiVersion: apps/v1 31 | kind: Deployment 32 | metadata: 33 | name: webapi 34 | labels: 35 | app: weather-forecast 36 | spec: 37 | replicas: 1 38 | selector: 39 | matchLabels: 40 | service: webapi 41 | template: 42 | metadata: 43 | labels: 44 | app: weather-forecast 45 | service: webapi 46 | spec: 47 | shareProcessNamespace: true 48 | volumes: 49 | - name: tmp 50 | emptyDir: {} 51 | - name: data 52 | persistentVolumeClaim: 53 | claimName: 54 | 55 | containers: 56 | - image: webapi:latest 57 | name: webapi-container 58 | imagePullPolicy: IfNotPresent 59 | ports: 60 | - containerPort: 80 61 | protocol: TCP 62 | env: 63 | - name: ASPNETCORE_URLS 64 | value: http://+:80 65 | volumeMounts: 66 | - name: tmp 67 | mountPath: /tmp 68 | - name: data 69 | mountPath: /data 70 | - image: sysinternals:latest 71 | imagePullPolicy: Always 72 | name: sysinternals-container 73 | stdin: true 74 | tty: true 75 | volumeMounts: 76 | - name: tmp 77 | mountPath: /tmp 78 | - name: data 79 | mountPath: /data 80 | --- 81 | apiVersion: v1 82 | kind: Service 83 | metadata: 84 | name: webapi 85 | labels: 86 | app: weather-forecast 87 | service: webapi 88 | spec: 89 | type: LoadBalancer 90 | ports: 91 | - port: 80 92 | targetPort: 80 93 | protocol: TCP 94 | selector: 95 | service: webapi 96 | -------------------------------------------------------------------------------- /docs/trigger_arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/ProcDump-for-Linux/f3d469ac1aa242e52beb3647ef9beb23b02c4247/docs/trigger_arch.jpg -------------------------------------------------------------------------------- /ebpf/procdump_ebpf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ProcDump for Linux 3 | 4 | Copyright (c) Microsoft Corporation 5 | 6 | All rights reserved. 7 | 8 | MIT License 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #ifndef __PROCDUMP_EBPF_H__ 18 | #define __PROCDUMP_EBPF_H__ 19 | 20 | #include "vmlinux.h" 21 | #include 22 | #include 23 | 24 | #define USER_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) 25 | #define ARGS_HASH_SIZE 10240 26 | 27 | #define BPF_PRINTK( format, ... ) \ 28 | if(isLoggingEnabled == true) \ 29 | { \ 30 | char fmt[] = format; \ 31 | bpf_trace_printk(fmt, sizeof(fmt), ##__VA_ARGS__ ); \ 32 | } 33 | 34 | // 35 | // This is a hashmap to hold resource arguments (such as size) between alloc and free calls. 36 | // It's shared by all cpus because alloc and free could be on different cpus. 37 | struct argsStruct 38 | { 39 | unsigned long size; 40 | }; 41 | 42 | struct 43 | { 44 | __uint(type, BPF_MAP_TYPE_HASH); 45 | __uint(max_entries, ARGS_HASH_SIZE); 46 | __type(key, int); 47 | __type(value, struct ResourceInformation); 48 | } argsHashMap SEC(".maps"); 49 | 50 | 51 | // 52 | // Since stack space is minimal, we use this to store an event on the heap 53 | // 54 | struct 55 | { 56 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 57 | __uint(max_entries, 512); 58 | __type(key, int); 59 | __type(value, struct ResourceInformation); 60 | } heapStorage SEC(".maps"); 61 | 62 | // 63 | // The ring buffer we use to communicate with user space 64 | // 65 | struct 66 | { 67 | __uint(type, BPF_MAP_TYPE_RINGBUF); 68 | __uint(max_entries, 10 * 1024 * 1024 /* 10 MB */); 69 | } ringBuffer SEC(".maps"); 70 | 71 | #endif // __PROCDUMP_EBPF_H__ -------------------------------------------------------------------------------- /ebpf/procdump_ebpf_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | ProcDump for Linux 3 | 4 | Copyright (c) Microsoft Corporation 5 | 6 | All rights reserved. 7 | 8 | MIT License 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #ifndef __PROCDUMP_EBPF_COMMON_H__ 18 | #define __PROCDUMP_EBPF_COMMON_H__ 19 | 20 | #define MAX_CALL_STACK_FRAMES 100 21 | 22 | #define RESTRACK_ALLOC 0x00000001 23 | #define RESTRACK_FREE 0x00000002 24 | 25 | struct ResourceInformation 26 | { 27 | unsigned long allocAddress; 28 | uint64_t pid; 29 | unsigned int resourceType; 30 | unsigned long allocSize; 31 | long callStackLen; 32 | __u64 stackTrace[MAX_CALL_STACK_FRAMES]; 33 | }; 34 | 35 | #endif // __PROCDUMP_EBPF_COMMON_H__ -------------------------------------------------------------------------------- /ebpf/vmlinux.h: -------------------------------------------------------------------------------- 1 | #if defined(__TARGET_ARCH_x86) 2 | #include "vmlinux-x86.h" 3 | #elif defined(__TARGET_ARCH_arm64) 4 | #include "vmlinux-arm64.h" 5 | #else 6 | #error "Unknown architecture" 7 | #endif -------------------------------------------------------------------------------- /include/CoreDumpWriter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Core dump orchestrator 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef CORE_DUMP_WRITER_H 11 | #define CORE_DUMP_WRITER_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #ifdef __linux__ 23 | #include 24 | #elif __APPLE_ 25 | #endif 26 | 27 | #define DATE_LENGTH 26 28 | #define MAX_LINES 15 29 | #define BUFFER_LENGTH 1024 30 | 31 | #define CORECLR_DUMPTYPE_FULL 4 32 | #define CORECLR_DUMPLOGGING_OFF 0 33 | #define CORECLR_DIAG_IPCHEADER_SIZE 24 34 | 35 | // Magic version for the IpcHeader struct 36 | struct MagicVersion 37 | { 38 | uint8_t Magic[14]; 39 | }; 40 | 41 | 42 | // CLSID struct 43 | struct CLSID 44 | { 45 | uint32_t Data1; 46 | unsigned short Data2; 47 | unsigned short Data3; 48 | unsigned char Data4[8]; 49 | }; 50 | 51 | // The header to be associated with every command and response 52 | // to/from the diagnostics server 53 | struct IpcHeader 54 | { 55 | union 56 | { 57 | struct MagicVersion _magic; 58 | uint8_t Magic[14]; // Magic Version number 59 | }; 60 | 61 | uint16_t Size; // The size of the incoming packet, size = header + payload size 62 | uint8_t CommandSet; // The scope of the Command. 63 | uint8_t CommandId; // The command being sent 64 | uint16_t Reserved; // reserved for future use 65 | }; 66 | 67 | 68 | enum ECoreDumpType { 69 | COMMIT, // trigger on memory threshold 70 | CPU, // trigger on CPU threshold 71 | THREAD, // trigger on thread count 72 | FILEDESC, // trigger on file descriptor count 73 | SIGNAL, // trigger on signal 74 | TIME, // trigger on time interval 75 | EXCEPTION, // trigger on exception 76 | MANUAL // manual trigger 77 | }; 78 | 79 | struct CoreDumpWriter { 80 | struct ProcDumpConfiguration *Config; 81 | enum ECoreDumpType Type; 82 | }; 83 | 84 | struct CoreDumpWriter *NewCoreDumpWriter(enum ECoreDumpType type, struct ProcDumpConfiguration *config); 85 | char* WriteCoreDumpInternal(struct CoreDumpWriter *self, char* socketName); 86 | char* WriteCoreDump(struct CoreDumpWriter *self); 87 | char* GetCoreDumpPrefixName(pid_t pid, char* procName, char* dumpPath, char* dumpName, enum ECoreDumpType type); 88 | char* GetCoreDumpName(ProcDumpConfiguration* config, ECoreDumpType type); 89 | 90 | #endif // CORE_DUMP_WRITER_H -------------------------------------------------------------------------------- /include/DotnetHelpers.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // .NET helpers 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef DOTNETHELPERS_H 11 | #define DOTNETHELPERS_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | bool IsCoreClrProcess(pid_t pid, char** socketName); 18 | bool GenerateCoreClrDump(char* socketName, char* dumpFileName); 19 | 20 | #endif // DOTNETHELPERS_H -------------------------------------------------------------------------------- /include/Events.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Quick events implementation 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef EVENTS_H 11 | #define EVENTS_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_EVENT_NAME 64 22 | 23 | #define MANUAL_RESET_EVENT_INITIALIZER(NAME) \ 24 | {\ 25 | .mutex = PTHREAD_MUTEX_INITIALIZER,\ 26 | .cond = PTHREAD_COND_INITIALIZER,\ 27 | .bManualReset = true,\ 28 | .bTriggered = false,\ 29 | .nWaiters = 0,\ 30 | .Name = NAME\ 31 | } 32 | 33 | struct Event { 34 | pthread_mutex_t mutex; 35 | pthread_cond_t cond; 36 | bool bTriggered; 37 | bool bManualReset; 38 | char Name[MAX_EVENT_NAME]; 39 | int nWaiters; 40 | }; 41 | 42 | struct Event *CreateEvent(bool IsManualReset, bool InitialState); 43 | struct Event *CreateNamedEvent(bool IsManualReset, bool InitialState, char *Name); 44 | void InitEvent(struct Event *Event, bool IsManualReset, bool InitialState); 45 | void InitNamedEvent(struct Event *Event, bool IsManualReset, bool InitialState, char *Name); 46 | void DestroyEvent(struct Event *Event); 47 | bool SetEvent(struct Event *Event); 48 | bool ResetEvent(struct Event *Event); 49 | 50 | #endif // EVENTS_H -------------------------------------------------------------------------------- /include/GenHelpers.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // General purpose helpers 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef GENHELPERS_H 11 | #define GENHELPERS_H 12 | 13 | #ifdef __linux__ 14 | #include 15 | #elif __APPLE_ 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | // 32 | // Minimum kernel version for ProcDump to run 33 | // 34 | #define MIN_KERNEL_VERSION 3 35 | #define MIN_KERNEL_PATCH 5 36 | 37 | // 38 | // Minimum kernel version for ProcDump restrack to run 39 | // 40 | #define MIN_RESTRACK_KERNEL_VERSION 4 41 | #define MIN_RESTRACK_KERNEL_PATCH 18 42 | 43 | 44 | //------------------------------------------------------------------------------------- 45 | // Auto clean up of memory using free (void) 46 | //------------------------------------------------------------------------------------- 47 | static inline void cleanup_void(void* val) 48 | { 49 | void **ppVal = (void**)val; 50 | free(*ppVal); 51 | } 52 | 53 | //------------------------------------------------------------------------------------- 54 | // Auto clean up of file descriptors using close 55 | //------------------------------------------------------------------------------------- 56 | #if (__GNUC__ >= 13) 57 | #pragma GCC diagnostic push 58 | #pragma GCC diagnostic ignored "-Wanalyzer-fd-leak" 59 | #endif 60 | static inline void cleanup_fd(int* val) 61 | { 62 | if (*val) 63 | { 64 | close(*val); 65 | } 66 | else 67 | { 68 | // Make static analyzer happy, otherwise it thinks we leak when *val == 0 69 | } 70 | } 71 | #if (__GNUC__ >= 13) 72 | #pragma GCC diagnostic pop 73 | #endif 74 | 75 | //------------------------------------------------------------------------------------- 76 | // Auto clean up of dir using closedir 77 | //------------------------------------------------------------------------------------- 78 | static inline void cleanup_dir(DIR** val) 79 | { 80 | if(*val) 81 | { 82 | closedir(*val); 83 | } 84 | } 85 | 86 | //------------------------------------------------------------------------------------- 87 | // Auto clean up of FILE using fclose 88 | //------------------------------------------------------------------------------------- 89 | static inline void cleanup_file(FILE** val) 90 | { 91 | if(*val) 92 | { 93 | fclose(*val); 94 | } 95 | } 96 | 97 | //------------------------------------------------------------------------------------- 98 | // Auto cancel pthread 99 | //------------------------------------------------------------------------------------- 100 | static inline void cancel_pthread(unsigned long* val) 101 | { 102 | if(*val!=-1) 103 | { 104 | #ifdef __linux__ 105 | pthread_cancel(*val); 106 | #endif 107 | } 108 | } 109 | 110 | #define auto_free __attribute__ ((__cleanup__(cleanup_void))) 111 | #define auto_free_fd __attribute__ ((__cleanup__(cleanup_fd))) 112 | #define auto_free_dir __attribute__ ((__cleanup__(cleanup_dir))) 113 | #define auto_free_file __attribute__ ((__cleanup__(cleanup_file))) 114 | #define auto_cancel_thread __attribute__ ((__cleanup__(cancel_pthread))) 115 | 116 | int* GetSeparatedValues(char* src, char* separator, int* numValues); 117 | bool ConvertToInt(const char* src, int* conv); 118 | bool ConvertToIntHex(const char* src, int* conv); 119 | bool IsValidNumberArg(const char *arg); 120 | bool CheckKernelVersion(int major, int minor); 121 | uint16_t* GetUint16(char* buffer); 122 | char* GetPath(char* lineBuf); 123 | FILE *popen2(const char *command, const char *type, pid_t *pid); 124 | char *sanitize(char *processName); 125 | int StringToGuid(char* szGuid, struct CLSID* pGuid); 126 | int GetHex(char* szStr, int size, void* pResult); 127 | bool createDir(const char *dir, mode_t perms); 128 | char* GetSocketPath(char* prefix, pid_t pid, pid_t targetPid); 129 | int send_all(int socket, void *buffer, size_t length); 130 | int recv_all(int socket, void* buffer, size_t length); 131 | pid_t gettid() noexcept; 132 | unsigned long GetCoreDumpFilter(int pid); 133 | bool SetCoreDumpFilter(int pid, unsigned long filter); 134 | 135 | #endif // GENHELPERS_H 136 | 137 | -------------------------------------------------------------------------------- /include/Handle.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Generalization of Events and Semaphores (Critical Sections) 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef HANDLE_H 11 | #define HANDLE_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "Events.h" 20 | #include "Logging.h" 21 | 22 | #define INFINITE_WAIT -1 23 | #define WAIT_OBJECT_0 0 24 | #define WAIT_TIMEOUT ETIMEDOUT 25 | #define WAIT_ABANDONED 0x80 26 | 27 | #define HANDLE_MANUAL_RESET_EVENT_INITIALIZER(NAME) \ 28 | {\ 29 | {\ 30 | .event = {\ 31 | .mutex = PTHREAD_MUTEX_INITIALIZER,\ 32 | .cond = PTHREAD_COND_INITIALIZER,\ 33 | .bManualReset = true,\ 34 | .bTriggered = false,\ 35 | .nWaiters = 0,\ 36 | .Name = NAME\ 37 | }\ 38 | },\ 39 | .type = EVENT\ 40 | } 41 | 42 | enum EHandleType { 43 | EVENT, 44 | SEMAPHORE 45 | }; 46 | 47 | struct Handle { 48 | union { 49 | struct Event event; 50 | sem_t* semaphore; 51 | }; 52 | enum EHandleType type; 53 | }; 54 | 55 | int WaitForSingleObject(struct Handle *Handle, int Milliseconds); 56 | int WaitForMultipleObjects(int Count, struct Handle **Handles, bool WaitAll, int Milliseconds); 57 | 58 | #endif // HANDLE_H -------------------------------------------------------------------------------- /include/Includes.h: -------------------------------------------------------------------------------- 1 | #include "ProfilerCommon.h" 2 | #include "CoreDumpWriter.h" 3 | #include "Events.h" 4 | #include "GenHelpers.h" 5 | #include "Handle.h" 6 | #include "Logging.h" 7 | #include "Monitor.h" 8 | #include "Procdump.h" 9 | #include "ProcDumpConfiguration.h" 10 | #include "Process.h" 11 | #include "DotnetHelpers.h" 12 | #include "ProfilerHelpers.h" 13 | #include "Restrack.h" 14 | #include "ProcDumpVersion.h" 15 | 16 | 17 | -------------------------------------------------------------------------------- /include/Logging.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // A simple logging library for log generation and debugging 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef LOGGING_H 11 | #define LOGGING_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define INTERNAL_ERROR "Internal Error has occurred. If problem continues to occur run procdump with -log flag to trace issue." 23 | 24 | // double-macro-stringify to expand __FILE__ and __LINE__ properly when they are injected in files 25 | #define S1(x) #x 26 | #define S2(x) S1(x) 27 | #define LOCATION "in " __FILE__ ", at line " S2(__LINE__) 28 | 29 | enum LogLevel{ 30 | debug, 31 | info, // standard output 32 | warn, 33 | crit, 34 | error 35 | }; 36 | 37 | void Log(enum LogLevel logLevel, const char *message, ...); 38 | 39 | 40 | void DiagTrace(const char* message, ...); 41 | 42 | /* 43 | * Summary: Used similarly to printf, but requires a format string for all input. 44 | * This macro appends line number and file information at the end of the format string and va_args. 45 | * Params: 46 | * - format: printf style format string literal 47 | * - var_args: variable number of format args 48 | * Example: Trace("%s", strerror(errno)) // %s format specifier required. 49 | */ 50 | #define Trace(format, ...) \ 51 | DiagTrace(format " %s", ##__VA_ARGS__, LOCATION); 52 | 53 | #endif // LOGGING_H -------------------------------------------------------------------------------- /include/Monitor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Monitor functions 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef MONITOR_H 11 | #define MONITOR_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "ProcDumpConfiguration.h" 18 | 19 | #define MAX_PROFILER_CONNECTIONS 50 20 | 21 | // Monitor functions 22 | void MonitorProcesses(struct ProcDumpConfiguration*self); 23 | int CreateMonitorThread(struct ProcDumpConfiguration *self, enum TriggerType triggerType, void *(*monitorThread) (void *), void *arg); 24 | int CreateMonitorThreads(struct ProcDumpConfiguration *self); 25 | int StartMonitor(struct ProcDumpConfiguration* monitorConfig); 26 | int WaitForQuit(struct ProcDumpConfiguration *self, int milliseconds); 27 | int WaitForQuitOrEvent(struct ProcDumpConfiguration *self, struct Handle *handle, int milliseconds); 28 | int WaitForAllMonitorsToTerminate(struct ProcDumpConfiguration *self); 29 | int WaitForSignalThreadToTerminate(struct ProcDumpConfiguration *self); 30 | int CancelRestrackThread(struct ProcDumpConfiguration *self); 31 | bool IsQuit(struct ProcDumpConfiguration *self); 32 | int SetQuit(struct ProcDumpConfiguration *self, int quit); 33 | bool ContinueMonitoring(struct ProcDumpConfiguration *self); 34 | bool BeginMonitoring(struct ProcDumpConfiguration *self); 35 | bool MonitorDotNet(struct ProcDumpConfiguration *self); 36 | char* GetThresholds(struct ProcDumpConfiguration *self); 37 | char* GetClientData(struct ProcDumpConfiguration *self, char* fullDumpPath); 38 | char* GetClientDataHelper(enum TriggerType triggerType, char* path, const char* format, ...); 39 | bool ExitProcessMonitor(struct ProcDumpConfiguration* config, pthread_t processMonitor); 40 | 41 | // Monitor worker threads 42 | void *CommitMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 43 | void *CpuMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 44 | void *ThreadCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 45 | void *FileDescriptorCountMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 46 | void *SignalMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 47 | void *TimerThread(void *thread_args /* struct ProcDumpConfiguration* */); 48 | void *DotNetMonitoringThread(void *thread_args /* struct ProcDumpConfiguration* */); 49 | void *RestrackThread(void *thread_args /* struct ProcDumpConfiguration* */); 50 | void *ProcessMonitor(void *thread_args /* struct ProcDumpConfiguration* */); 51 | void *WaitForProfilerCompletion(void *thread_args /* struct ProcDumpConfiguration* */); 52 | 53 | #endif // MONITOR_H -------------------------------------------------------------------------------- /include/ProcDumpVersion.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | ProcDump for Linux 3 | 4 | Copyright (c) Microsoft Corporation 5 | 6 | All rights reserved. 7 | 8 | MIT License 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | //==================================================================== 18 | // 19 | // ProcDumpVersion.h.in 20 | // 21 | // Version information 22 | // 23 | //==================================================================== 24 | 25 | // 26 | // Version information 27 | // 28 | #define STRFILEVER "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@" 29 | 30 | // 31 | // File information 32 | // 33 | #define VER_COMPANY "Sysinternals - www.sysinternals.com" 34 | 35 | #define VER_COPYRIGHT "Copyright (C) 2009-2024 Microsoft Corporation. All rights reserved. Licensed under the MIT license.\nMark Russinovich, Mario Hewardt, John Salem, Javid Habibi." 36 | 37 | -------------------------------------------------------------------------------- /include/Procdump.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // This program monitors a process and generates core dumps in 7 | // in response to various triggers 8 | // 9 | //-------------------------------------------------------------------- 10 | 11 | #ifndef UBUNTU_SYSINTERNALS_PROCDUMP_H 12 | #define UBUNTU_SYSINTERNALS_PROCDUMP_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define MIN_CPU 0 // minimum CPU value 23 | #define DEFAULT_NUMBER_OF_DUMPS 1 // default number of core dumps taken 24 | #define DEFAULT_DELTA_TIME 10 // default delta time in seconds between core dumps 25 | #define DEFAULT_SAMPLE_RATE 1 // default sample rate is 1 26 | 27 | void termination_handler(int sig_num); 28 | 29 | #endif //UBUNTU_SYSINTERNALS_PROCDUMP_H 30 | -------------------------------------------------------------------------------- /include/ProfilerCommon.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Profiler Common 7 | // 8 | //-------------------------------------------------------------------- 9 | #ifndef PROFILERCOMMON_H 10 | #define PROFILERCOMMON_H 11 | 12 | #define CUMULATIVE_GC_SIZE 2008 13 | #define MAX_GC_GEN 2 14 | 15 | enum TriggerType 16 | { 17 | Processor, 18 | Commit, 19 | Timer, 20 | Signal, 21 | ThreadCount, 22 | FileDescriptorCount, 23 | Exception, 24 | GCThreshold, 25 | GCGeneration, 26 | Restrack 27 | }; 28 | 29 | #endif // PROFILERCOMMON_H -------------------------------------------------------------------------------- /include/ProfilerHelpers.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Profiler helpers 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef PROFILERHELPERS_H 11 | #define PROFILERHELPERS_H 12 | 13 | #define PROCDUMP_DIR "/usr/local/bin" 14 | #define PROFILER_FILE_NAME "procdumpprofiler.so" 15 | #define PROFILER_GUID "{cf0d821e-299b-5307-a3d8-b283c03916dd}" 16 | 17 | int InjectProfiler(pid_t pid, char* clientData); 18 | int LoadProfiler(pid_t pid, char* clientData); 19 | int ExtractProfiler(); 20 | char* GetEncodedExceptionFilter(char* exceptionFilterCmdLine, unsigned int numDumps); 21 | 22 | #endif // PROFILERHELPERS_H 23 | 24 | -------------------------------------------------------------------------------- /include/Restrack.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // Restrack.h 7 | // 8 | //-------------------------------------------------------------------- 9 | 10 | #ifndef RESTRACK_H 11 | #define RESTRACK_H 12 | 13 | #define MAX_CALL_STACK_FRAMES 100 14 | 15 | struct procdump_ebpf* RunRestrack(struct ProcDumpConfiguration *config); 16 | void StopRestrack(struct procdump_ebpf* skel); 17 | int RestrackHandleEvent(void *ctx, void *data, size_t data_sz); 18 | void* ReportLeaks(void* args); 19 | pthread_t WriteRestrackSnapshot(ProcDumpConfiguration* config, ECoreDumpType type); 20 | 21 | #endif // RESTRACK_H 22 | 23 | -------------------------------------------------------------------------------- /makePackages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # ProcDump for Linux 4 | # 5 | # Copyright (c) Microsoft Corporation 6 | # 7 | # All rights reserved. 8 | # 9 | # MIT License 10 | # 11 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | # 17 | 18 | ################################################################################# 19 | # 20 | # makePackages.sh 21 | # 22 | # Builds the directory trees for DEB and RPM packages and, if suitable tools are 23 | # available, builds the actual packages too. 24 | # 25 | ################################################################################# 26 | 27 | if [ "$5" = "" ]; then 28 | echo "Usage: $0 " 29 | exit 1 30 | fi 31 | 32 | # copy cmake vars 33 | CMAKE_SOURCE_DIR=$1 34 | PROJECT_BINARY_DIR=$2 35 | PACKAGE_NAME=$3 36 | PACKAGE_VER=$4 37 | PACKAGE_REL=$5 38 | PACKAGE_TYPE=$6 39 | ARCHITECTURE=$7 40 | 41 | DEB_PACKAGE_NAME="${PACKAGE_NAME}_${PACKAGE_VER}_${ARCHITECTURE}" 42 | RPM_PACKAGE_NAME="${PACKAGE_NAME}-${PACKAGE_VER}-${PACKAGE_REL}" 43 | BREW_PACKAGE_NAME="${PACKAGE_NAME}-mac-${PACKAGE_VER}" 44 | 45 | if [ "$PACKAGE_TYPE" = "deb" ]; then 46 | DPKGDEB=`which dpkg-deb` 47 | 48 | if [ -d "${PROJECT_BINARY_DIR}/deb" ]; then 49 | rm -rf "${PROJECT_BINARY_DIR}/deb" 50 | fi 51 | 52 | # copy deb files 53 | mkdir -p "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}" 54 | #cp -a "${CMAKE_SOURCE_DIR}/dist/DEBIAN" "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/" 55 | mkdir -p "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/DEBIAN" 56 | cp "${PROJECT_BINARY_DIR}/DEBIANcontrol" "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/DEBIAN/control" 57 | mkdir -p "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/share/doc/procdump" 58 | cp "${PROJECT_BINARY_DIR}/changelog.gz" "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/share/doc/procdump" 59 | mkdir -p "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/share/man/man1" 60 | cp -a "${PROJECT_BINARY_DIR}/procdump.1.gz" "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/share/man/man1" 61 | mkdir -p "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/bin" 62 | cp "${PROJECT_BINARY_DIR}/procdump" "${PROJECT_BINARY_DIR}/deb/${DEB_PACKAGE_NAME}/usr/bin/" 63 | 64 | # make the deb 65 | if [ "$DPKGDEB" != "" ]; then 66 | cd "${PROJECT_BINARY_DIR}/deb" 67 | "$DPKGDEB" -Zxz --build --root-owner-group "${DEB_PACKAGE_NAME}" 68 | RET=$? 69 | else 70 | echo "No dpkg-deb found" 71 | RET=1 72 | fi 73 | 74 | exit 0 75 | fi 76 | 77 | if [ "$PACKAGE_TYPE" = "rpm" ]; then 78 | RPMBUILD=`which rpmbuild` 79 | 80 | if [ -d "${PROJECT_BINARY_DIR}/rpm" ]; then 81 | rm -rf "${PROJECT_BINARY_DIR}/rpm" 82 | fi 83 | 84 | # copy rpm files 85 | mkdir -p "${PROJECT_BINARY_DIR}/rpm/${RPM_PACKAGE_NAME}/SPECS" 86 | cp -a "${PROJECT_BINARY_DIR}/SPECS.spec" "${PROJECT_BINARY_DIR}/rpm/${RPM_PACKAGE_NAME}/SPECS/${RPM_PACKAGE_NAME}.spec" 87 | mkdir "${PROJECT_BINARY_DIR}/rpm/${RPM_PACKAGE_NAME}/BUILD/" 88 | cp "${PROJECT_BINARY_DIR}/procdump.1.gz" "${PROJECT_BINARY_DIR}/changelog" "${PROJECT_BINARY_DIR}/procdump" "${PROJECT_BINARY_DIR}/rpm/${RPM_PACKAGE_NAME}/BUILD/" 89 | 90 | # make the rpm 91 | if [ "$RPMBUILD" != "" ]; then 92 | cd "${PROJECT_BINARY_DIR}/rpm/${RPM_PACKAGE_NAME}" 93 | "$RPMBUILD" --define "_topdir `pwd`" -v -bb "SPECS/${RPM_PACKAGE_NAME}.spec" 94 | RET=$? 95 | cp RPMS/$(uname -m)/*.rpm .. 96 | else 97 | echo "No rpmbuild found" 98 | RET=1 99 | fi 100 | fi 101 | 102 | if [ "$PACKAGE_TYPE" = "brew" ]; then 103 | 104 | # create brew package 105 | zip $PROJECT_BINARY_DIR/${BREW_PACKAGE_NAME}.zip procdump procdump.1.gz 106 | fi 107 | exit $RET -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /procdump.1: -------------------------------------------------------------------------------- 1 | .\" Manpage for procdump. 2 | .TH man 8 "3/17/2025" "3.4.1" "procdump manpage" 3 | .SH NAME 4 | procdump \- generate coredumps based off performance triggers. 5 | .SH SYNOPSIS 6 | procdump [-n Count] 7 | [-s Seconds] 8 | [-c|-cl CPU_Usage] 9 | [-m|-ml Commit_Usage1[,Commit_Usage2...]] 10 | [-gcm [: | LOH: | POH:]Memory_Usage1[,Memory_Usage2...]] 11 | [-gcgen Generation] 12 | [-restrack [nodump]] 13 | [-sr Sample_Rate] 14 | [-tc Thread_Threshold] 15 | [-fc FileDescriptor_Threshold] 16 | [-sig Signal_Number1[,Signal_Number2...]] 17 | [-e] 18 | [-f Include_Filter,...] 19 | [-fx Exclude_Filter] 20 | [-mc Custom_Dump_Mask] 21 | [-pf Polling_Frequency] 22 | [-o] 23 | [-log syslog|stdout] 24 | { 25 | {{[-w] Process_Name | [-pgid] PID} [Dump_File | Dump_Folder]} 26 | } 27 | 28 | Options: 29 | -n Number of dumps to write before exiting. 30 | -s Consecutive seconds before dump is written (default is 10). 31 | -c CPU threshold above which to create a dump of the process. 32 | -cl CPU threshold below which to create a dump of the process. 33 | -m Memory commit threshold(s) (MB) above which to create dumps. 34 | -ml Memory commit threshold(s) (MB) below which to create dumps. 35 | -gcm [.NET] GC memory threshold(s) (MB) above which to create dumps for the specified generation or heap (default is total .NET memory usage). 36 | -gcgen [.NET] Create dump when the garbage collection of the specified generation starts and finishes. 37 | -restrack Enable memory leak tracking (malloc family of APIs). Use the nodump option to prevent dump generation and only produce restrack report(s). 38 | -sr Sample rate when using -restrack. 39 | -tc Thread count threshold above which to create a dump of the process. 40 | -fc File descriptor count threshold above which to create a dump of the process. 41 | -sig Comma separated list of signal number(s) during which any signal results in a dump of the process. 42 | -e [.NET] Create dump when the process encounters an exception. 43 | -f Filter (include) on the content of .NET exceptions (comma separated). Wildcards (*) are supported. 44 | -fx Filter (exclude) on the content of -restrack call stacks. Wildcards (*) are supported. 45 | -mc Custom core dump mask (in hex) indicating what memory should be included in the core dump. Please see 'man core' (/proc/[pid]/coredump_filter) for available options. 46 | -pf Polling frequency. 47 | -o Overwrite existing dump file. 48 | -log Writes extended ProcDump tracing to the specified output stream (syslog or stdout). 49 | -w Wait for the specified process to launch if it's not running. 50 | -pgid Process ID specified refers to a process group ID. 51 | 52 | .SH DESCRIPTION 53 | ProcDump provides a convenient way for Linux and Mac developers to create core dumps of their application based on performance triggers. ProcDump is part of Sysinternals. -------------------------------------------------------------------------------- /procdump.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/ProcDump-for-Linux/f3d469ac1aa242e52beb3647ef9beb23b02c4247/procdump.gif -------------------------------------------------------------------------------- /procdump_mac.1: -------------------------------------------------------------------------------- 1 | .\" Manpage for procdump. 2 | .TH man 8 "2/5/2024" "1.0" "procdump manpage" 3 | .SH NAME 4 | procdump \- generate coredumps based off performance triggers. 5 | .SH SYNOPSIS 6 | procdump [-n Count] 7 | [-s Seconds] 8 | [-c|-cl CPU_Usage] 9 | [-m|-ml Commit_Usage1[,Commit_Usage2...]] 10 | [-tc Thread_Threshold] 11 | [-fc FileDescriptor_Threshold] 12 | [-pf Polling_Frequency] 13 | [-o] 14 | [-log syslog|stdout] 15 | { 16 | {{[-w] Process_Name} [Dump_File | Dump_Folder]} 17 | } 18 | 19 | Options: 20 | -n Number of dumps to write before exiting. 21 | -s Consecutive seconds before dump is written (default is 10). 22 | -c CPU threshold above which to create a dump of the process. 23 | -cl CPU threshold below which to create a dump of the process. 24 | -m Memory commit threshold(s) (MB) above which to create dumps. 25 | -ml Memory commit threshold(s) (MB) below which to create dumps. 26 | -tc Thread count threshold above which to create a dump of the process. 27 | -fc File descriptor count threshold above which to create a dump of the process. 28 | -pf Polling frequency. 29 | -o Overwrite existing dump file. 30 | -log Writes extended ProcDump tracing to the specified output stream (syslog or stdout). 31 | -w Wait for the specified process to launch if it's not running. 32 | 33 | .SH DESCRIPTION 34 | ProcDump provides a convenient way for Linux and Mac developers to create core dumps of their application based on performance triggers. ProcDump is part of Sysinternals. -------------------------------------------------------------------------------- /profiler/inc/CComPtr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | 6 | template 7 | class CComPtr 8 | { 9 | private: 10 | TInterface* pointer; 11 | public: 12 | CComPtr(const CComPtr&) = delete; // Copy constructor 13 | CComPtr& operator= (const CComPtr&) = delete; // Copy assignment 14 | CComPtr(CComPtr&&) = delete; // Move constructor 15 | CComPtr& operator= (CComPtr&&) = delete; // Move assignment 16 | 17 | void* operator new(std::size_t) = delete; 18 | void* operator new[](std::size_t) = delete; 19 | 20 | void operator delete(void *ptr) = delete; 21 | void operator delete[](void *ptr) = delete; 22 | 23 | CComPtr() 24 | { 25 | this->pointer = nullptr; 26 | } 27 | 28 | ~CComPtr() 29 | { 30 | if (this->pointer) 31 | { 32 | this->pointer->Release(); 33 | this->pointer = nullptr; 34 | } 35 | } 36 | 37 | operator TInterface*() 38 | { 39 | return this->pointer; 40 | } 41 | 42 | operator TInterface*() const 43 | { 44 | return this->pointer; 45 | } 46 | 47 | TInterface& operator *() 48 | { 49 | return *this->pointer; 50 | } 51 | 52 | TInterface& operator *() const 53 | { 54 | return *this->pointer; 55 | } 56 | 57 | TInterface** operator&() 58 | { 59 | return &this->pointer; 60 | } 61 | 62 | TInterface** operator&() const 63 | { 64 | return &this->pointer; 65 | } 66 | 67 | TInterface* operator->() 68 | { 69 | return this->pointer; 70 | } 71 | 72 | TInterface* operator->() const 73 | { 74 | return this->pointer; 75 | } 76 | 77 | void Release() 78 | { 79 | this->~CComPtr(); 80 | } 81 | }; -------------------------------------------------------------------------------- /profiler/inc/ClassFactory.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | 6 | #include "unknwn.h" 7 | #include 8 | 9 | class ClassFactory : public IClassFactory 10 | { 11 | private: 12 | std::atomic refCount; 13 | public: 14 | ClassFactory(); 15 | virtual ~ClassFactory(); 16 | HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; 17 | ULONG STDMETHODCALLTYPE AddRef(void) override; 18 | ULONG STDMETHODCALLTYPE Release(void) override; 19 | HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) override; 20 | HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override; 21 | }; -------------------------------------------------------------------------------- /profiler/inc/debugmacrosext.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | //***************************************************************************** 4 | // DebugMacrosExt.h 5 | // 6 | // Simple debugging macros that take no dependencies on CLR headers. 7 | // This header can be used from outside the CLR. 8 | // 9 | //***************************************************************************** 10 | 11 | #ifndef __DebugMacrosExt_h__ 12 | #define __DebugMacrosExt_h__ 13 | 14 | #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) 15 | #define _DEBUG_IMPL 1 16 | #endif 17 | 18 | #ifdef _DEBUG 19 | // A macro to execute a statement only in _DEBUG. 20 | #define DEBUG_STMT(stmt) stmt 21 | #define INDEBUG(x) x 22 | #define INDEBUG_COMMA(x) x, 23 | #define COMMA_INDEBUG(x) ,x 24 | #define NOT_DEBUG(x) 25 | #else 26 | #define DEBUG_STMT(stmt) 27 | #define INDEBUG(x) 28 | #define INDEBUG_COMMA(x) 29 | #define COMMA_INDEBUG(x) 30 | #define NOT_DEBUG(x) x 31 | #endif 32 | 33 | 34 | #ifdef _DEBUG_IMPL 35 | #define INDEBUGIMPL(x) x 36 | #define INDEBUGIMPL_COMMA(x) x, 37 | #define COMMA_INDEBUGIMPL(x) ,x 38 | #else 39 | #define INDEBUGIMPL(x) 40 | #define INDEBUGIMPL_COMMA(x) 41 | #define COMMA_INDEBUGIMPL(x) 42 | #endif 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /profiler/inc/oaidl.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: oaidl.h 8 | // 9 | // =========================================================================== 10 | 11 | #ifndef __OAIDL_H__ 12 | #define __OAIDL_H__ 13 | 14 | // Pointer to IErrorInfo is still used in non-Windows code 15 | // Prevent accidentally using its member 16 | struct IErrorInfo; 17 | 18 | #endif //__OAIDL_H__ 19 | -------------------------------------------------------------------------------- /profiler/inc/ole2.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // dummy ole2.h for PAL 7 | 8 | #include "objidl.h" 9 | #include "servprov.h" 10 | #include "oaidl.h" 11 | 12 | -------------------------------------------------------------------------------- /profiler/inc/pal_assert.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | /*++ 5 | 6 | 7 | 8 | 9 | 10 | --*/ 11 | 12 | #ifndef __PAL_ASSERT_H__ 13 | #define __PAL_ASSERT_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | // 21 | // C_ASSERT() can be used to perform many compile-time assertions: 22 | // type sizes, field offsets, etc. 23 | // 24 | #define C_ASSERT(e) static_assert(e, #e) 25 | 26 | // 27 | // CPP_ASSERT() can be used within a class definition, to perform a 28 | // compile-time assertion involving private names within the class. 29 | // 30 | #define CPP_ASSERT(n, e) static_assert(e, #e) 31 | 32 | #endif // __cplusplus 33 | 34 | #ifndef _ASSERTE 35 | #if defined(_DEBUG) 36 | #define _ASSERTE(e) do { \ 37 | if (!(e)) { \ 38 | PAL_fprintf (PAL_get_stderr(PAL_get_caller), \ 39 | "ASSERT FAILED\n" \ 40 | "\tExpression: %s\n" \ 41 | "\tLocation: line %d in %s\n" \ 42 | "\tFunction: %s\n" \ 43 | "\tProcess: %d\n", \ 44 | #e, __LINE__, __FILE__, __FUNCTION__, \ 45 | GetCurrentProcessId()); \ 46 | DebugBreak(); \ 47 | } \ 48 | }while (0) 49 | #else // !DEBUG 50 | #define _ASSERTE(e) ((void)0) 51 | #endif 52 | #endif // _ASSERTE 53 | 54 | #ifndef assert 55 | #define assert(e) _ASSERTE(e) 56 | #endif // assert 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif // __PAL_ASSERT_H__ 63 | -------------------------------------------------------------------------------- /profiler/inc/pal_endian.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | /*++ 5 | 6 | 7 | 8 | 9 | 10 | --*/ 11 | 12 | #ifndef __PAL_ENDIAN_H__ 13 | #define __PAL_ENDIAN_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C++" { 17 | inline UINT16 SWAP16(UINT16 x) 18 | { 19 | return (UINT16)((x >> 8) | (x << 8)); 20 | } 21 | 22 | inline UINT32 SWAP32(UINT32 x) 23 | { 24 | return (x >> 24) | 25 | ((x >> 8) & 0x0000FF00L) | 26 | ((x & 0x0000FF00L) << 8) | 27 | (x << 24); 28 | } 29 | 30 | } 31 | #endif // __cplusplus 32 | 33 | #if BIGENDIAN 34 | #ifdef __cplusplus 35 | extern "C++" { 36 | inline UINT16 VAL16(UINT16 x) 37 | { 38 | return SWAP16(x); 39 | } 40 | 41 | inline UINT32 VAL32(UINT32 x) 42 | { 43 | return SWAP32(x); 44 | } 45 | 46 | inline UINT64 VAL64(UINT64 x) 47 | { 48 | return ((UINT64)VAL32(x) << 32) | VAL32(x >> 32); 49 | } 50 | 51 | inline void SwapString(WCHAR *szString) 52 | { 53 | unsigned i; 54 | for (i = 0; szString[i] != L'\0'; i++) 55 | { 56 | szString[i] = VAL16(szString[i]); 57 | } 58 | } 59 | 60 | inline void SwapStringLength(WCHAR *szString, ULONG StringLength) 61 | { 62 | unsigned i; 63 | for (i = 0; i < StringLength; i++) 64 | { 65 | szString[i] = VAL16(szString[i]); 66 | } 67 | } 68 | 69 | inline void SwapGuid(GUID *pGuid) 70 | { 71 | pGuid->Data1 = VAL32(pGuid->Data1); 72 | pGuid->Data2 = VAL16(pGuid->Data2); 73 | pGuid->Data3 = VAL16(pGuid->Data3); 74 | } 75 | }; 76 | #else // __cplusplus 77 | /* C Version of VAL functionality. Swap functions omitted for lack of use in C code */ 78 | #define VAL16(x) (((x) >> 8) | ((x) << 8)) 79 | #define VAL32(y) (((y) >> 24) | (((y) >> 8) & 0x0000FF00L) | (((y) & 0x0000FF00L) << 8) | ((y) << 24)) 80 | #define VAL64(z) (((UINT64)VAL32(z) << 32) | VAL32((z) >> 32)) 81 | #endif // __cplusplus 82 | 83 | #else // !BIGENDIAN 84 | 85 | #define VAL16(x) x 86 | #define VAL32(x) x 87 | #define VAL64(x) x 88 | #define SwapString(x) 89 | #define SwapStringLength(x, y) 90 | #define SwapGuid(x) 91 | 92 | #endif // !BIGENDIAN 93 | 94 | #ifdef HOST_64BIT 95 | #define VALPTR(x) VAL64(x) 96 | #else 97 | #define VALPTR(x) VAL32(x) 98 | #endif 99 | 100 | #ifdef HOST_ARM 101 | #define LOG2_PTRSIZE 2 102 | #define ALIGN_ACCESS ((1<= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 29 | #pragma warning(disable:4103) 30 | #if !(defined( MIDL_PASS )) || defined( __midl ) 31 | #pragma pack(pop) 32 | #else 33 | #pragma pack() 34 | #endif 35 | #else 36 | #pragma pack() 37 | #endif 38 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 39 | -------------------------------------------------------------------------------- /profiler/inc/profiler_pal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | 6 | #ifndef WIN32 7 | #include 8 | #include "pal_mstypes.h" 9 | #include "pal.h" 10 | #include "ntimage.h" 11 | #include "corhdr.h" 12 | 13 | #define CoTaskMemAlloc(cb) malloc(cb) 14 | #define CoTaskMemFree(cb) free(cb) 15 | 16 | #define UINT_PTR_FORMAT "lx" 17 | 18 | #else 19 | #define UINT_PTR_FORMAT "llx" 20 | #endif -------------------------------------------------------------------------------- /profiler/inc/pshpack1.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: pshpack1.h 8 | // 9 | // =========================================================================== 10 | 11 | /*++ 12 | 13 | Abstract: 14 | 15 | This file turns 1 byte packing of structures on. (That is, it disables 16 | automatic alignment of structure fields.) An include file is needed 17 | because various compilers do this in different ways. For Microsoft 18 | compatible compilers, this files uses the push option to the pack pragma 19 | so that the poppack.h include file can restore the previous packing 20 | reliably. 21 | 22 | The file poppack.h is the complement to this file. 23 | 24 | --*/ 25 | 26 | #if ! (defined(lint) || defined(RC_INVOKED)) 27 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 28 | #pragma warning(disable:4103) 29 | #if !(defined( MIDL_PASS )) || defined( __midl ) 30 | #pragma pack(push,1) 31 | #else 32 | #pragma pack(1) 33 | #endif 34 | #else 35 | #pragma pack(1) 36 | #endif 37 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 38 | -------------------------------------------------------------------------------- /profiler/inc/pshpack2.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: pshpack2.h 8 | // 9 | // =========================================================================== 10 | /*++ 11 | 12 | Abstract: 13 | 14 | This file turns 2 byte packing of structures on. (That is, it disables 15 | automatic alignment of structure fields.) An include file is needed 16 | because various compilers do this in different ways. For Microsoft 17 | compatible compilers, this files uses the push option to the pack pragma 18 | so that the poppack.h include file can restore the previous packing 19 | reliably. 20 | 21 | The file poppack.h is the complement to this file. 22 | 23 | --*/ 24 | 25 | #if ! (defined(lint) || defined(RC_INVOKED)) 26 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 27 | #pragma warning(disable:4103) 28 | #if !(defined( MIDL_PASS )) || defined( __midl ) 29 | #pragma pack(push,2) 30 | #else 31 | #pragma pack(2) 32 | #endif 33 | #else 34 | #pragma pack(2) 35 | #endif 36 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 37 | -------------------------------------------------------------------------------- /profiler/inc/pshpack4.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: pshpack4.h 8 | // 9 | // =========================================================================== 10 | 11 | /*++ 12 | 13 | Abstract: 14 | 15 | This file turns 4 byte packing of structures on. (That is, it disables 16 | automatic alignment of structure fields.) An include file is needed 17 | because various compilers do this in different ways. For Microsoft 18 | compatible compilers, this files uses the push option to the pack pragma 19 | so that the poppack.h include file can restore the previous packing 20 | reliably. 21 | 22 | The file poppack.h is the complement to this file. 23 | 24 | --*/ 25 | 26 | #if ! (defined(lint) || defined(RC_INVOKED)) 27 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 28 | #pragma warning(disable:4103) 29 | #if !(defined( MIDL_PASS )) || defined( __midl ) 30 | #pragma pack(push,4) 31 | #else 32 | #pragma pack(4) 33 | #endif 34 | #else 35 | #pragma pack(4) 36 | #endif 37 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 38 | -------------------------------------------------------------------------------- /profiler/inc/pshpack8.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: pshpack8.h 8 | // 9 | // =========================================================================== 10 | 11 | /*++ 12 | 13 | Abstract: 14 | 15 | This file turns 8 byte packing of structures on. (That is, it disables 16 | automatic alignment of structure fields.) An include file is needed 17 | because various compilers do this in different ways. For Microsoft 18 | compatible compilers, this files uses the push option to the pack pragma 19 | so that the poppack.h include file can restore the previous packing 20 | reliably. 21 | 22 | The file poppack.h is the complement to this file. 23 | 24 | --*/ 25 | 26 | #if ! (defined(lint) || defined(RC_INVOKED)) 27 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 28 | #pragma warning(disable:4103) 29 | #if !(defined( MIDL_PASS )) || defined( __midl ) 30 | #pragma pack(push,8) 31 | #else 32 | #pragma pack(8) 33 | #endif 34 | #else 35 | #pragma pack(8) 36 | #endif 37 | #endif // ! (defined(lint) || defined(RC_INVOKED)) 38 | -------------------------------------------------------------------------------- /profiler/inc/rpc.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: rpc.h 8 | // 9 | // =========================================================================== 10 | // dummy rpc.h for PAL 11 | 12 | #ifndef __RPC_H__ 13 | #define __RPC_H__ 14 | 15 | #include "palrt.h" 16 | 17 | #define __RPC_STUB 18 | #define __RPC_USER 19 | #define __RPC_FAR 20 | 21 | #define __uuidof(type) IID_##type 22 | 23 | #define DECLSPEC_UUID(x) 24 | 25 | #define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE 26 | 27 | #define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) \ 28 | constexpr IID itf = {l1,s1,s2,{c1,c2,c3,c4,c5,c6,c7,c8}} 29 | 30 | interface IRpcStubBuffer; 31 | interface IRpcChannelBuffer; 32 | 33 | typedef void* PRPC_MESSAGE; 34 | typedef void* RPC_IF_HANDLE; 35 | 36 | #endif // __RPC_H__ 37 | -------------------------------------------------------------------------------- /profiler/inc/rpcndr.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: rpcndr.h 8 | // 9 | // =========================================================================== 10 | // dummy rpcndr.h for PAL 11 | 12 | #ifndef __RPCNDR_H__ 13 | #define __RPCNDR_H__ 14 | 15 | #ifndef __RPCNDR_H_VERSION__ 16 | #define __RPCNDR_H_VERSION__ 17 | #endif 18 | 19 | #endif // __RPCNDR_H__ 20 | -------------------------------------------------------------------------------- /profiler/inc/servprov.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: servprov.h 8 | // 9 | // =========================================================================== 10 | // simplified servprov.h for PAL 11 | 12 | #include "rpc.h" 13 | #include "rpcndr.h" 14 | 15 | #include "unknwn.h" 16 | 17 | #ifndef __IServiceProvider_INTERFACE_DEFINED__ 18 | #define __IServiceProvider_INTERFACE_DEFINED__ 19 | 20 | // 6d5140c1-7436-11ce-8034-00aa006009fa 21 | EXTERN_C const IID IID_IServiceProvider; 22 | 23 | interface IServiceProvider : public IUnknown 24 | { 25 | virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService( 26 | /* [in] */ REFGUID guidService, 27 | /* [in] */ REFIID riid, 28 | /* [out] */ void **ppvObject) = 0; 29 | }; 30 | 31 | #endif // __IServiceProvider_INTERFACE_DEFINED__ 32 | -------------------------------------------------------------------------------- /profiler/inc/static_assert.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // --------------------------------------------------------------------------- 4 | // static_assert.h 5 | // 6 | // Static assertion infrastructure 7 | // --------------------------------------------------------------------------- 8 | 9 | //-------------------------------------------------------------------------------- 10 | // static_assert represents a check which should be made at compile time. It 11 | // can only be done on a constant expression. 12 | //-------------------------------------------------------------------------------- 13 | 14 | #ifndef __STATIC_ASSERT_H__ 15 | #define __STATIC_ASSERT_H__ 16 | 17 | // Replaces previous uses of C_ASSERT and COMPILE_TIME_ASSERT 18 | #define static_assert_no_msg( cond ) static_assert( cond, #cond ) 19 | 20 | #endif // __STATIC_ASSERT_H__ 21 | 22 | -------------------------------------------------------------------------------- /profiler/inc/unknwn.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: unknwn.h 8 | // 9 | // =========================================================================== 10 | // simplified unknwn.h for PAL 11 | 12 | #include "rpc.h" 13 | #include "rpcndr.h" 14 | 15 | #ifndef __IUnknown_INTERFACE_DEFINED__ 16 | #define __IUnknown_INTERFACE_DEFINED__ 17 | 18 | typedef interface IUnknown IUnknown; 19 | 20 | typedef /* [unique] */ IUnknown *LPUNKNOWN; 21 | 22 | // 00000000-0000-0000-C000-000000000046 23 | EXTERN_C const IID IID_IUnknown; 24 | 25 | MIDL_INTERFACE("00000000-0000-0000-C000-000000000046") 26 | IUnknown 27 | { 28 | virtual HRESULT STDMETHODCALLTYPE QueryInterface( 29 | REFIID riid, 30 | void **ppvObject) = 0; 31 | 32 | virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; 33 | 34 | virtual ULONG STDMETHODCALLTYPE Release( void) = 0; 35 | }; 36 | 37 | #endif // __IUnknown_INTERFACE_DEFINED__ 38 | 39 | #ifndef __IClassFactory_INTERFACE_DEFINED__ 40 | #define __IClassFactory_INTERFACE_DEFINED__ 41 | 42 | // 00000001-0000-0000-C000-000000000046 43 | EXTERN_C const IID IID_IClassFactory; 44 | 45 | MIDL_INTERFACE("00000001-0000-0000-C000-000000000046") 46 | IClassFactory : public IUnknown 47 | { 48 | virtual HRESULT STDMETHODCALLTYPE CreateInstance( 49 | IUnknown *pUnkOuter, 50 | REFIID riid, 51 | void **ppvObject) = 0; 52 | 53 | virtual HRESULT STDMETHODCALLTYPE LockServer( 54 | BOOL fLock) = 0; 55 | }; 56 | 57 | #endif // __IClassFactory_INTERFACE_DEFINED__ 58 | -------------------------------------------------------------------------------- /profiler/inc/unreachable.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // --------------------------------------------------------------------------- 4 | // unreachable.h 5 | // --------------------------------------------------------------------------- 6 | 7 | 8 | #ifndef __UNREACHABLE_H__ 9 | #define __UNREACHABLE_H__ 10 | 11 | #if defined(_MSC_VER) || defined(_PREFIX_) 12 | #define __UNREACHABLE() __assume(0) 13 | #else 14 | #define __UNREACHABLE() __builtin_unreachable() 15 | #endif 16 | 17 | #endif // __UNREACHABLE_H__ 18 | 19 | -------------------------------------------------------------------------------- /profiler/inc/utils.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | #ifndef HAVE_MINIPAL_UTILS_H 5 | #define HAVE_MINIPAL_UTILS_H 6 | 7 | #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) 8 | 9 | // Number of characters in a string literal. Excludes terminating NULL. 10 | #define STRING_LENGTH(str) (ARRAY_SIZE(str) - 1) 11 | 12 | #ifndef __has_builtin 13 | #define __has_builtin(x) 0 14 | #endif 15 | 16 | #if defined(_MSC_VER) 17 | # if defined(__SANITIZE_ADDRESS__) 18 | # define HAS_ADDRESS_SANITIZER 19 | # define DISABLE_ASAN __declspec(no_sanitize_address) 20 | # else 21 | # define DISABLE_ASAN 22 | # endif 23 | #elif defined(__has_feature) 24 | # if __has_feature(address_sanitizer) 25 | # define HAS_ADDRESS_SANITIZER 26 | # define DISABLE_ASAN __attribute__((no_sanitize("address"))) 27 | # else 28 | # define DISABLE_ASAN 29 | # endif 30 | #else 31 | # define DISABLE_ASAN 32 | #endif 33 | 34 | #if defined(_MSC_VER) 35 | # ifdef SANITIZER_SHARED_RUNTIME 36 | # define SANITIZER_CALLBACK_CALLCONV __declspec(dllexport no_sanitize_address) __cdecl 37 | # define SANITIZER_INTERFACE_CALLCONV __declspec(dllimport) __cdecl 38 | # else 39 | # define SANITIZER_CALLBACK_CALLCONV __declspec(no_sanitize_address) __cdecl 40 | # define SANITIZER_INTERFACE_CALLCONV __cdecl 41 | # endif 42 | #else 43 | # ifdef SANITIZER_SHARED_RUNTIME 44 | # define SANITIZER_CALLBACK_CALLCONV __attribute__((no_address_safety_analysis)) __attribute__((visibility("default"))) 45 | # else 46 | # define SANITIZER_CALLBACK_CALLCONV __attribute__((no_address_safety_analysis)) 47 | # endif 48 | # define SANITIZER_INTERFACE_CALLCONV 49 | #endif 50 | 51 | #if defined(HAS_ADDRESS_SANITIZER) 52 | # ifdef __cplusplus 53 | extern "C" 54 | { 55 | # endif 56 | void SANITIZER_INTERFACE_CALLCONV __asan_handle_no_return(void); 57 | # ifdef __cplusplus 58 | } 59 | # endif 60 | #elif defined(__llvm__) 61 | # pragma clang diagnostic push 62 | # ifdef COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER 63 | # pragma clang diagnostic ignored "-Wreserved-identifier" 64 | # endif 65 | // Stub out a dummy implmentation when asan isn't enabled. 66 | inline void __asan_handle_no_return(void); 67 | inline void __asan_handle_no_return(void){} 68 | # pragma clang diagnostic pop 69 | #else 70 | // Use a macro for GCC since __asan_handle_no_return is always available as a built-in on GCC 71 | #define __asan_handle_no_return() 72 | #endif 73 | 74 | #endif // HAVE_MINIPAL_UTILS_H 75 | -------------------------------------------------------------------------------- /profiler/inc/winerror.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // 4 | 5 | // 6 | // =========================================================================== 7 | // File: winerror.h 8 | // 9 | // =========================================================================== 10 | // dummy winerror.h for PAL 11 | 12 | #include "palrt.h" 13 | -------------------------------------------------------------------------------- /profiler/src/ClassFactory.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include "ClassFactory.h" 5 | #include "ProcDumpProfiler.h" 6 | 7 | ClassFactory::ClassFactory() : refCount(0) 8 | { 9 | } 10 | 11 | ClassFactory::~ClassFactory() 12 | { 13 | } 14 | 15 | HRESULT STDMETHODCALLTYPE ClassFactory::QueryInterface(REFIID riid, void **ppvObject) 16 | { 17 | if (riid == IID_IUnknown || riid == IID_IClassFactory) 18 | { 19 | *ppvObject = this; 20 | this->AddRef(); 21 | return S_OK; 22 | } 23 | 24 | *ppvObject = nullptr; 25 | return E_NOINTERFACE; 26 | } 27 | 28 | ULONG STDMETHODCALLTYPE ClassFactory::AddRef() 29 | { 30 | return std::atomic_fetch_add(&this->refCount, 1) + 1; 31 | } 32 | 33 | ULONG STDMETHODCALLTYPE ClassFactory::Release() 34 | { 35 | int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; 36 | if (count <= 0) 37 | { 38 | delete this; 39 | } 40 | 41 | return count; 42 | } 43 | 44 | HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) 45 | { 46 | if (pUnkOuter != nullptr) 47 | { 48 | *ppvObject = nullptr; 49 | return CLASS_E_NOAGGREGATION; 50 | } 51 | 52 | CorProfiler* profiler = new CorProfiler(); 53 | if (profiler == nullptr) 54 | { 55 | return E_FAIL; 56 | } 57 | 58 | return profiler->QueryInterface(riid, ppvObject); 59 | } 60 | 61 | HRESULT STDMETHODCALLTYPE ClassFactory::LockServer(BOOL fLock) 62 | { 63 | return S_OK; 64 | } -------------------------------------------------------------------------------- /profiler/src/ClrProfiler.def: -------------------------------------------------------------------------------- 1 | LIBRARY "ClrProfiler.Dll" 2 | 3 | EXPORTS 4 | DllCanUnloadNow PRIVATE 5 | DllGetClassObject PRIVATE -------------------------------------------------------------------------------- /profiler/src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #include "ClassFactory.h" 5 | 6 | const IID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; 7 | 8 | const IID IID_IClassFactory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; 9 | 10 | BOOL STDMETHODCALLTYPE DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 11 | { 12 | return TRUE; 13 | } 14 | 15 | extern "C" HRESULT STDMETHODCALLTYPE DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) 16 | { 17 | // {cf0d821e-299b-5307-a3d8-b283c03916dd} 18 | const GUID CLSID_CorProfiler = { 0xcf0d821e, 0x299b, 0x5307, { 0xa3, 0xd8, 0xb2, 0x83, 0xc0, 0x39, 0x16, 0xdd } }; 19 | 20 | if (ppv == nullptr || rclsid != CLSID_CorProfiler) 21 | { 22 | return E_FAIL; 23 | } 24 | 25 | auto factory = new ClassFactory; 26 | if (factory == nullptr) 27 | { 28 | return E_FAIL; 29 | } 30 | 31 | return factory->QueryInterface(riid, ppv); 32 | } 33 | 34 | extern "C" HRESULT STDMETHODCALLTYPE DllCanUnloadNow() 35 | { 36 | return S_OK; 37 | } -------------------------------------------------------------------------------- /src/Logging.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // A simple logging library for log generation and debugging 7 | // 8 | //-------------------------------------------------------------------- 9 | #include "Includes.h" 10 | 11 | static const char *LogLevelStrings[] = { "DEBUG", "INFO", "WARN", "CRITICAL", "ERROR" }; 12 | extern struct ProcDumpConfiguration g_config; 13 | pthread_mutex_t LoggerLock; 14 | 15 | void LogFormatter(enum LogLevel logLevel, enum DiagnosticsLogTarget target, const char *message, va_list args) 16 | { 17 | char timeBuff[64]; 18 | time_t rawTime; 19 | struct tm *timeInfo=NULL; 20 | char* trace=NULL; 21 | 22 | va_list copy; 23 | va_copy(copy, args); 24 | 25 | pthread_mutex_lock(&LoggerLock); 26 | 27 | rawTime = time(NULL); 28 | timeInfo = localtime(&rawTime); 29 | strftime(timeBuff, 64, "%T", timeInfo); 30 | 31 | int traceLen = snprintf(NULL, 0, "[%s - %s]: ", timeBuff, LogLevelStrings[logLevel]); 32 | int argsLen = vsnprintf(NULL, 0, message, copy); 33 | if(!(trace = (char*) malloc(traceLen+argsLen+1))) 34 | { 35 | pthread_mutex_unlock(&LoggerLock); 36 | va_end(copy); 37 | return; 38 | } 39 | 40 | snprintf(trace, traceLen+argsLen, "[%s - %s]: ", timeBuff, LogLevelStrings[logLevel]); 41 | vsnprintf(trace+traceLen, traceLen+argsLen, message, args); 42 | 43 | // If a log entry is not 'debug' it simply goes to stdout. 44 | // If you want an entry to only go to the syslog, use 'debug' 45 | if(logLevel != debug) 46 | { 47 | puts(trace); 48 | } 49 | else 50 | { 51 | if(target == diag_syslog) 52 | { 53 | syslog(LOG_DEBUG, "%s", trace); 54 | } 55 | else if(target == diag_stdout) 56 | { 57 | puts(trace); 58 | } 59 | } 60 | 61 | va_end(copy); 62 | free(trace); 63 | pthread_mutex_unlock(&LoggerLock); 64 | } 65 | 66 | void Log(enum LogLevel logLevel, const char *message, ...) 67 | { 68 | va_list args; 69 | va_start(args, message); 70 | LogFormatter(logLevel, diag_stdout, message, args); 71 | va_end(args); 72 | } 73 | 74 | 75 | void DiagTrace(const char *message, ...) 76 | { 77 | va_list args; 78 | va_start(args, message); 79 | 80 | if(g_config.DiagnosticsLoggingEnabled != none) 81 | { 82 | LogFormatter(debug, g_config.DiagnosticsLoggingEnabled, message, args); 83 | } 84 | 85 | va_end(args); 86 | } 87 | -------------------------------------------------------------------------------- /src/Procdump.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License 3 | 4 | //-------------------------------------------------------------------- 5 | // 6 | // This program monitors a process and generates core dumps in 7 | // in response to various triggers 8 | // 9 | //-------------------------------------------------------------------- 10 | #include "Includes.h" 11 | 12 | extern struct ProcDumpConfiguration g_config; 13 | 14 | //-------------------------------------------------------------------- 15 | // 16 | // OnExit 17 | // 18 | // Invoked when ProcDump exits. 19 | // 20 | //-------------------------------------------------------------------- 21 | void OnExit() 22 | { 23 | ExitProcDump(); 24 | } 25 | 26 | 27 | //-------------------------------------------------------------------- 28 | // 29 | // main 30 | // 31 | // main ProcDump function 32 | // 33 | //-------------------------------------------------------------------- 34 | int main(int argc, char *argv[]) 35 | { 36 | // print banner and begin initialization 37 | PrintBanner(); 38 | InitProcDump(); 39 | 40 | // Parse command line arguments 41 | if (GetOptions(&g_config, argc, argv) != 0) 42 | { 43 | exit(-1); 44 | } 45 | 46 | // Register exit handler 47 | atexit(OnExit); 48 | 49 | // monitor for all specified processes 50 | MonitorProcesses(&g_config); 51 | } 52 | -------------------------------------------------------------------------------- /sudo: -------------------------------------------------------------------------------- 1 | APT::Get::Assume-Yes "true"; /etc/apt/apt.conf.d/90assumeyes 2 | -------------------------------------------------------------------------------- /sym/bcc_elf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 GitHub, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef LIBBCC_ELF_H 17 | #define LIBBCC_ELF_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | 26 | struct bcc_elf_usdt { 27 | uint64_t pc; 28 | uint64_t base_addr; 29 | // Virtual address semaphore is found at 30 | uint64_t semaphore; 31 | 32 | const char *provider; 33 | const char *name; 34 | const char *arg_fmt; 35 | 36 | // Offset from start of file where the semaphore is at 37 | uint64_t semaphore_offset; 38 | }; 39 | 40 | // Binary module path, bcc_elf_usdt struct, payload 41 | typedef void (*bcc_elf_probecb)(const char *, const struct bcc_elf_usdt *, 42 | void *); 43 | // Symbol name, start address, length, payload 44 | // Callback returning a negative value indicates to stop the iteration 45 | typedef int (*bcc_elf_symcb)(const char *, uint64_t, uint64_t, void *); 46 | // Section idx, str table idx, str length, start address, length, payload 47 | typedef int (*bcc_elf_symcb_lazy)(size_t, size_t, size_t, uint64_t, uint64_t, 48 | int, void *); 49 | // Segment virtual address, memory size, file offset, payload 50 | // Callback returning a negative value indicates to stop the iteration 51 | typedef int (*bcc_elf_load_sectioncb)(uint64_t, uint64_t, uint64_t, void *); 52 | 53 | // Iterate over all USDT probes noted in a binary module 54 | // Returns -1 on error, and 0 on success 55 | int bcc_elf_foreach_usdt(const char *path, bcc_elf_probecb callback, 56 | void *payload); 57 | // Iterate over all executable load sections of an ELF 58 | // Returns -1 on error, 1 if stopped by callback, and 0 on success 59 | int bcc_elf_foreach_load_section(const char *path, 60 | bcc_elf_load_sectioncb callback, 61 | void *payload); 62 | // Iterate over symbol table of a binary module 63 | // Parameter "option" points to a bcc_symbol_option struct to indicate whether 64 | // and how to use debuginfo file, and what types of symbols to load. 65 | // Returns -1 on error, and 0 on success or stopped by callback 66 | int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback, void *option, 67 | void *payload); 68 | // Similar to bcc_elf_foreach_sym, but pass reference to symbolized string along 69 | // with symbolized string length 70 | int bcc_elf_foreach_sym_lazy(const char *path, bcc_elf_symcb_lazy callback, 71 | void *option, void *payload); 72 | // Iterate over all symbols from current system's vDSO 73 | // Returns -1 on error, and 0 on success or stopped by callback 74 | int bcc_elf_foreach_vdso_sym(bcc_elf_symcb callback, void *payload); 75 | 76 | int bcc_elf_get_text_scn_info(const char *path, uint64_t *addr, 77 | uint64_t *offset); 78 | 79 | int bcc_elf_get_type(const char *path); 80 | int bcc_elf_is_shared_obj(const char *path); 81 | int bcc_elf_is_exe(const char *path); 82 | int bcc_elf_is_vdso(const char *name); 83 | int bcc_free_memory(); 84 | int bcc_elf_get_buildid(const char *path, char *buildid); 85 | int bcc_elf_symbol_str(const char *path, size_t section_idx, 86 | size_t str_table_idx, char *out, size_t len, 87 | int debugfile); 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | #endif 93 | -------------------------------------------------------------------------------- /sym/bcc_perf_map.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Facebook, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "bcc_perf_map.h" 24 | 25 | bool bcc_is_perf_map(const char *path) { 26 | char* pos = strstr(const_cast(path), ".map"); 27 | // Path ends with ".map" 28 | return (pos != NULL) && (*(pos + 4)== 0); 29 | } 30 | 31 | bool bcc_is_valid_perf_map(const char *path) { 32 | return bcc_is_perf_map(path) && (access(path, R_OK) == 0); 33 | } 34 | 35 | int bcc_perf_map_nstgid(int pid) { 36 | char status_path[64]; 37 | FILE *status; 38 | 39 | snprintf(status_path, sizeof(status_path), "/proc/%d/status", pid); 40 | status = fopen(status_path, "r"); 41 | 42 | if (!status) 43 | return -1; 44 | 45 | // return the original PID if we fail to work out the TGID 46 | int nstgid = pid; 47 | 48 | size_t size = 0; 49 | char *line = NULL; 50 | while (getline(&line, &size, status) != -1) { 51 | // check Tgid line first in case CONFIG_PID_NS is off 52 | if (strstr(line, "Tgid:") != NULL) 53 | nstgid = (int)strtol(strrchr(line, '\t'), NULL, 10); 54 | if (strstr(line, "NStgid:") != NULL) 55 | // PID namespaces can be nested -- last number is innermost PID 56 | nstgid = (int)strtol(strrchr(line, '\t'), NULL, 10); 57 | } 58 | free(line); 59 | fclose(status); 60 | 61 | return nstgid; 62 | } 63 | 64 | bool bcc_perf_map_path(char *map_path, size_t map_len, int pid) { 65 | char source[64]; 66 | snprintf(source, sizeof(source), "/proc/%d/root", pid); 67 | 68 | char target[4096]; 69 | ssize_t target_len = readlink(source, target, sizeof(target) - 1); 70 | if (target_len == -1) 71 | return false; 72 | 73 | target[target_len] = '\0'; 74 | if (strcmp(target, "/") == 0) 75 | target[0] = '\0'; 76 | 77 | int nstgid = bcc_perf_map_nstgid(pid); 78 | 79 | snprintf(map_path, map_len, "%s/tmp/perf-%d.map", target, nstgid); 80 | return true; 81 | } 82 | 83 | int bcc_perf_map_foreach_sym(const char *path, bcc_perf_map_symcb callback, 84 | void* payload) { 85 | FILE* file = fopen(path, "r"); 86 | if (!file) 87 | return -1; 88 | 89 | char *line = NULL; 90 | size_t size = 0; 91 | long long begin, len; 92 | while (getline(&line, &size, file) != -1) { 93 | char *cursor = line; 94 | char *newline, *sep; 95 | 96 | begin = strtoull(cursor, &sep, 16); 97 | if (begin == 0 || *sep != ' ' || (begin == ULLONG_MAX && errno == ERANGE)) 98 | continue; 99 | cursor = sep; 100 | while (*cursor && isspace(*cursor)) cursor++; 101 | 102 | len = strtoull(cursor, &sep, 16); 103 | if (*sep != ' ' || 104 | (sep == cursor && len == 0) || 105 | (len == ULLONG_MAX && errno == ERANGE)) 106 | continue; 107 | cursor = sep; 108 | while (*cursor && isspace(*cursor)) cursor++; 109 | 110 | newline = strchr(cursor, '\n'); 111 | if (newline) 112 | newline[0] = '\0'; 113 | 114 | callback(cursor, begin, len, payload); 115 | } 116 | 117 | free(line); 118 | fclose(file); 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /sym/bcc_perf_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Facebook, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef LIBBCC_PERF_MAP_H 17 | #define LIBBCC_PERF_MAP_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // Symbol name, start address, length, payload 28 | typedef int (*bcc_perf_map_symcb)(const char *, uint64_t, uint64_t, void *); 29 | 30 | bool bcc_is_perf_map(const char *path); 31 | bool bcc_is_valid_perf_map(const char *path); 32 | 33 | int bcc_perf_map_nstgid(int pid); 34 | bool bcc_perf_map_path(char *map_path, size_t map_len, int pid); 35 | int bcc_perf_map_foreach_sym(const char *path, bcc_perf_map_symcb callback, 36 | void* payload); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /sym/bcc_proc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 GitHub, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef LIBBCC_PROC_H 17 | #define LIBBCC_PROC_H 18 | 19 | #include "bcc_syms.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | typedef struct mod_info { 31 | char *name; 32 | uint64_t start_addr; 33 | uint64_t end_addr; 34 | long long unsigned int file_offset; 35 | uint64_t dev_major; 36 | uint64_t dev_minor; 37 | uint64_t inode; 38 | } mod_info; 39 | 40 | // Module info, whether to check mount namespace, payload 41 | // Callback returning a negative value indicates to stop the iteration 42 | typedef int (*bcc_procutils_modulecb)(mod_info *, int, void *); 43 | 44 | // Symbol name, address, payload 45 | typedef void (*bcc_procutils_ksymcb)(const char *, const char *, uint64_t, void *); 46 | 47 | char *bcc_procutils_which_so(const char *libname, int pid); 48 | char *bcc_procutils_which(const char *binpath); 49 | int bcc_mapping_is_file_backed(const char *mapname); 50 | // Iterate over all executable memory mapping sections of a Process. 51 | // All anonymous and non-file-backed mapping sections, namely those 52 | // listed in bcc_mapping_is_file_backed, will be ignored. 53 | // Returns -1 on error, and 0 on success 54 | int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, 55 | void *payload); 56 | 57 | int _procfs_maps_each_module(FILE *procmaps, int pid, 58 | bcc_procutils_modulecb callback, void *payload); 59 | // Iterate over all non-data Kernel symbols. 60 | // Returns -1 on error, and 0 on success 61 | int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload); 62 | void bcc_procutils_free(const char *ptr); 63 | const char *bcc_procutils_language(int pid); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | #endif 69 | -------------------------------------------------------------------------------- /sym/bcc_syms.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 GitHub, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef LIBBCC_SYMS_H 17 | #define LIBBCC_SYMS_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include "linux/bpf.h" 25 | #include "bcc_proc.h" 26 | 27 | struct bcc_symbol { 28 | const char *name; 29 | const char *demangle_name; 30 | const char *module; 31 | uint64_t offset; 32 | }; 33 | 34 | typedef int (*SYM_CB)(const char *symname, uint64_t addr); 35 | struct mod_info; 36 | 37 | #ifndef STT_GNU_IFUNC 38 | #define STT_GNU_IFUNC 10 39 | #endif 40 | 41 | #if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2 42 | // Indicate if the Local Entry Point (LEP) should be used as a symbol's 43 | // start address 44 | #define STT_PPC64_ELFV2_SYM_LEP 31 45 | #endif 46 | 47 | static const uint32_t BCC_SYM_ALL_TYPES = 65535; 48 | struct bcc_symbol_option { 49 | int use_debug_file; 50 | int check_debug_file_crc; 51 | // Symbolize on-demand or symbolize everything ahead of time 52 | int lazy_symbolize; 53 | // Bitmask flags indicating what types of ELF symbols to use 54 | uint32_t use_symbol_type; 55 | }; 56 | 57 | void *bcc_symcache_new(int pid, struct bcc_symbol_option *option); 58 | void bcc_free_symcache(void *symcache, int pid); 59 | 60 | // The demangle_name pointer in bcc_symbol struct is returned from the 61 | // __cxa_demangle function call, which is supposed to be freed by caller. Call 62 | // this function after done using returned result of bcc_symcache_resolve. 63 | void bcc_symbol_free_demangle_name(struct bcc_symbol *sym); 64 | int bcc_symcache_resolve(void *symcache, uint64_t addr, struct bcc_symbol *sym); 65 | int bcc_symcache_resolve_no_demangle(void *symcache, uint64_t addr, 66 | struct bcc_symbol *sym); 67 | 68 | int bcc_symcache_resolve_name(void *resolver, const char *module, 69 | const char *name, uint64_t *addr); 70 | void bcc_symcache_refresh(void *resolver); 71 | 72 | int _bcc_syms_find_module(struct mod_info *info, int enter_ns, void *p); 73 | int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address, 74 | uint8_t inode_match_only, uint64_t *global); 75 | 76 | /*bcc APIs for build_id stackmap support*/ 77 | void *bcc_buildsymcache_new(void); 78 | void bcc_free_buildsymcache(void *symcache); 79 | int bcc_buildsymcache_add_module(void *resolver, const char *module_name); 80 | int bcc_buildsymcache_resolve(void *resolver, 81 | struct bpf_stack_build_id *trace, 82 | struct bcc_symbol *sym); 83 | // Call cb on every function symbol in the specified module. Uses simpler 84 | // SYM_CB callback mainly for easier to use in Python API. 85 | // Will prefer use debug file and check debug file CRC when reading the module. 86 | int bcc_foreach_function_symbol(const char *module, SYM_CB cb); 87 | 88 | // Find the offset of a symbol in a module binary. If addr is not zero, will 89 | // calculate the offset using the provided addr and the module's load address. 90 | // 91 | // If pid is provided, will use it to help lookup the module in the Process and 92 | // enter the Process's mount Namespace. 93 | // 94 | // If option is not NULL, will respect the specified options for lookup. 95 | // Otherwise default option will apply, which is to use debug file, verify 96 | // checksum, and try all types of symbols. 97 | // 98 | // Return 0 on success and -1 on failure. Output will be write to sym. After 99 | // use, sym->module need to be freed if it's not empty. 100 | int bcc_resolve_symname(const char *module, const char *symname, 101 | const uint64_t addr, int pid, 102 | struct bcc_symbol_option* option, 103 | struct bcc_symbol *sym); 104 | 105 | /* Calculate the global address for 'offset' in a shared object loaded into 106 | * a process 107 | * 108 | * Need to know (start_addr, file_offset) pairs for the /proc/PID/maps module 109 | * entry containing the offset and the elf section containing the module's 110 | * .text 111 | */ 112 | uint64_t __so_calc_global_addr(uint64_t mod_start_addr, 113 | uint64_t mod_file_offset, 114 | uint64_t elf_sec_start_addr, 115 | uint64_t elf_sec_file_offset, uint64_t offset); 116 | 117 | /* Given a global address which falls within a shared object's mapping in a 118 | * process, calculate the corresponding 'offset' in the .so 119 | * 120 | * Need to know (start_addr, file_offset) pairs for the /proc/PID/maps module 121 | * entry containing the offset and the elf section containing the module's 122 | * .text 123 | */ 124 | uint64_t __so_calc_mod_offset(uint64_t mod_start_addr, uint64_t mod_file_offset, 125 | uint64_t elf_sec_start_addr, 126 | uint64_t elf_sec_file_offset, 127 | uint64_t global_addr); 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | #endif 133 | -------------------------------------------------------------------------------- /sym/bcc_zip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef LIBBCC_ZIP_H 18 | #define LIBBCC_ZIP_H 19 | 20 | #include 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | // Represents an opened zip archive. 27 | // Only basic ZIP files are supported, in particular the following are not 28 | // supported: 29 | // - encryption 30 | // - streaming 31 | // - multi-part ZIP files 32 | // - ZIP64 33 | struct bcc_zip_archive; 34 | 35 | // Carries information on name, compression method and data corresponding to 36 | // a file in a zip archive. 37 | struct bcc_zip_entry { 38 | // Compression method as defined in pkzip spec. 0 means data is uncompressed. 39 | uint16_t compression; 40 | 41 | // Non-null terminated name of the file. 42 | const char* name; 43 | // Length of the file name. 44 | uint16_t name_length; 45 | 46 | // Pointer to the file data. 47 | const void* data; 48 | // Length of the file data. 49 | uint32_t data_length; 50 | // Offset of the file data within the archive. 51 | uint32_t data_offset; 52 | }; 53 | 54 | // Opens a zip archive. Returns NULL in case of an error. 55 | struct bcc_zip_archive* bcc_zip_archive_open(const char* path); 56 | 57 | // Closes a zip archive and releases resources. 58 | void bcc_zip_archive_close(struct bcc_zip_archive* archive); 59 | 60 | // Looks up data corresponding to a file in given zip archive. 61 | int bcc_zip_archive_find_entry(struct bcc_zip_archive* archive, 62 | const char* name, struct bcc_zip_entry* out); 63 | 64 | int bcc_zip_archive_find_entry_at_offset(struct bcc_zip_archive* archive, 65 | uint32_t offset, 66 | struct bcc_zip_entry* out); 67 | 68 | // Opens a zip archives and looks up entry within the archive. 69 | // Provided path is interpreted as archive path followed by "!/" 70 | // characters and name of the zip entry. This convention is used 71 | // by Android tools. 72 | struct bcc_zip_archive* bcc_zip_archive_open_and_find( 73 | const char* path, struct bcc_zip_entry* out); 74 | 75 | #ifdef __cplusplus 76 | } 77 | #endif 78 | #endif 79 | -------------------------------------------------------------------------------- /sym/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 PLUMgrid, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace ebpf { 25 | 26 | #ifdef __cpp_lib_make_unique 27 | using std::make_unique; 28 | #else 29 | template 30 | typename std::enable_if::value, std::unique_ptr>::type 31 | make_unique(Args &&... args) { 32 | return std::unique_ptr(new T(std::forward(args)...)); 33 | } 34 | #endif 35 | 36 | std::vector get_online_cpus(); 37 | 38 | std::vector get_possible_cpus(); 39 | 40 | std::string get_pid_exe(pid_t pid); 41 | 42 | std::string tracefs_path(); 43 | 44 | std::string tracepoint_format_file(std::string const& category, 45 | std::string const& event); 46 | 47 | std::string parse_tracepoint(std::istream &input, std::string const& category, 48 | std::string const& event); 49 | } // namespace ebpf 50 | -------------------------------------------------------------------------------- /sym/file_desc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Facebook, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | namespace ebpf { 22 | 23 | /// FileDesc is a helper class for managing open file descriptors. Copy is 24 | /// disallowed (call dup instead), and cleanup happens automatically. 25 | class FileDesc { 26 | public: 27 | explicit FileDesc(int fd = -1) : fd_(fd) {} 28 | FileDesc(FileDesc &&that) : fd_(-1) { *this = std::move(that); } 29 | FileDesc(const FileDesc &that) = delete; 30 | 31 | ~FileDesc() { 32 | if (fd_ >= 0) 33 | ::close(fd_); 34 | } 35 | 36 | FileDesc &operator=(int fd) { 37 | if (fd_ >= 0) 38 | ::close(fd_); 39 | fd_ = fd; 40 | return *this; 41 | } 42 | FileDesc &operator=(FileDesc &&that) { 43 | if (fd_ >= 0) 44 | ::close(fd_); 45 | fd_ = that.fd_; 46 | that.fd_ = -1; 47 | return *this; 48 | } 49 | FileDesc &operator=(const FileDesc &that) = delete; 50 | 51 | FileDesc dup() const { 52 | if (fd_ >= 0) { 53 | int dup_fd = ::dup(fd_); 54 | return FileDesc(dup_fd); 55 | } else { 56 | return FileDesc(-1); 57 | } 58 | } 59 | 60 | operator int() { return fd_; } 61 | operator int() const { return fd_; } 62 | 63 | private: 64 | int fd_; 65 | }; 66 | 67 | } // namespace ebpf 68 | -------------------------------------------------------------------------------- /templates/build.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: srcPath 3 | type: string 4 | default: '.' 5 | - name: runStaticAnalysis 6 | type: boolean 7 | default: False 8 | - name: builddir 9 | type: string 10 | default: 'procdump_build' 11 | 12 | steps: 13 | - script: | 14 | mkdir -p ${{ parameters.srcPath }}/${{ parameters.builddir }} && cd ${{ parameters.srcPath }}/${{ parameters.builddir }} 15 | cmake .. 16 | make 17 | displayName: "Build ProcDump binaries" 18 | -------------------------------------------------------------------------------- /tests/integration/ProcDumpTestApplication.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define FILE_DESC_COUNT 500 11 | #define THREAD_COUNT 100 12 | 13 | 14 | void* dFunc(int type) 15 | { 16 | if(type == 0) 17 | { 18 | char* alloc = malloc(10000); 19 | for(int i=0; i<10000; i++) 20 | { 21 | alloc[i] = 'a'; 22 | } 23 | mlock(alloc, 10000); 24 | return alloc; 25 | } 26 | else if (type == 1) 27 | { 28 | char* callocAlloc = calloc(1, 10000); 29 | mlock(callocAlloc, 10000); 30 | return callocAlloc; 31 | } 32 | else if (type == 2) 33 | { 34 | void* lastAlloc = malloc(10000); 35 | void* newAlloc = realloc(lastAlloc, 20000); 36 | for(int i=0; i<20000; i++) 37 | { 38 | ((char*)newAlloc)[i] = 'a'; 39 | } 40 | mlock(newAlloc, 20000); 41 | return newAlloc; 42 | } 43 | else if (type == 3) 44 | { 45 | #ifdef __linux__ 46 | void* lastAlloc = malloc(10000); 47 | void* newAlloc = reallocarray(lastAlloc, 10, 20000); 48 | return newAlloc; 49 | #endif 50 | return NULL; 51 | } 52 | else 53 | { 54 | return NULL; 55 | } 56 | } 57 | 58 | void* c(int type) 59 | { 60 | return dFunc(type); 61 | } 62 | 63 | void* b(int type) 64 | { 65 | return c(type); 66 | } 67 | 68 | void* a(int type) 69 | { 70 | return b(type); 71 | } 72 | 73 | void* ThreadProc(void *input) 74 | { 75 | sleep(UINT_MAX); 76 | return NULL; 77 | }; 78 | 79 | int main(int argc, char *argv[]) 80 | { 81 | if (argc > 1) 82 | { 83 | // 84 | // To avoid timing differences, each test below should sleep indefinately once done. 85 | // The process will be killed by the test harness once procdump has finished monitoring 86 | // 87 | if (strcmp("sleep", argv[1]) == 0) 88 | { 89 | sleep(UINT_MAX); 90 | } 91 | else if (strcmp("burn", argv[1]) == 0) 92 | { 93 | while(1); 94 | } 95 | else if (strcmp("fc", argv[1]) == 0) 96 | { 97 | FILE* fd[FILE_DESC_COUNT]; 98 | for(int i=0; i 7 | { 8 | throw new System.InvalidOperationException(); 9 | }); 10 | 11 | app.MapGet("/fullgc", () => 12 | { 13 | System.GC.Collect(); 14 | }); 15 | 16 | app.MapGet("/memincrease", () => 17 | { 18 | // Gen2 19 | var myList = new List(); 20 | for(int i = 0; i < 1000; i++) 21 | { 22 | myList.Add(new byte[10000]); 23 | } 24 | // Promote to Gen2 25 | GC.Collect(); 26 | GC.Collect(); 27 | GC.Collect(); 28 | 29 | // LOH 30 | var myLOHList = new List(); 31 | myLOHList.Add(new byte[15000000]); 32 | System.GC.Collect(); 33 | myLOHList.Add(new byte[15000000]); 34 | System.GC.Collect(); 35 | myLOHList.Add(new byte[15000000]); 36 | System.GC.Collect(); 37 | 38 | // POH 39 | var p1 = GC.AllocateArray(15000000, pinned: true); 40 | System.GC.Collect(); 41 | var p2 = GC.AllocateArray(15000000, pinned: true); 42 | System.GC.Collect(); 43 | var p3 = GC.AllocateArray(15000000, pinned: true); 44 | System.GC.Collect(); 45 | }); 46 | 47 | 48 | app.MapGet("/throwandcatchinvalidoperation", () => 49 | { 50 | try 51 | { 52 | throw new System.InvalidOperationException(); 53 | } 54 | catch(Exception){} 55 | 56 | throw new System.InvalidOperationException(); 57 | }); 58 | 59 | 60 | app.MapGet("/throwargumentexception", () => 61 | { 62 | throw new System.ArgumentException(); 63 | }); 64 | 65 | // Kills the web api 66 | app.MapGet("/terminate", () => 67 | { 68 | System.Environment.Exit(0); 69 | }); 70 | 71 | // Kills the web api 72 | app.MapGet("/stress", () => 73 | { 74 | List arr = new List(); 75 | for(int i=0; i<50; i++) 76 | { 77 | arr.Add(new Thread(DoWork)); 78 | } 79 | 80 | foreach(Thread thread in arr) 81 | { 82 | thread.Start(); 83 | } 84 | }); 85 | 86 | void DoWork() 87 | { 88 | for(int i = 0; i<50;i++) 89 | { 90 | try 91 | { 92 | throw new System.InvalidOperationException(); 93 | } 94 | catch(Exception){} 95 | } 96 | } 97 | 98 | app.Run(); 99 | -------------------------------------------------------------------------------- /tests/integration/TestWebApi/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:1187", 7 | "sslPort": 44319 8 | } 9 | }, 10 | "profiles": { 11 | "http": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5032", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "https": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": true, 23 | "launchBrowser": true, 24 | "applicationUrl": "https://localhost:7118;http://localhost:5032", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | }, 29 | "IIS Express": { 30 | "commandName": "IISExpress", 31 | "launchBrowser": true, 32 | "environmentVariables": { 33 | "ASPNETCORE_ENVIRONMENT": "Development" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/integration/TestWebApi/TestWebApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/integration/TestWebApi/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/integration/TestWebApi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /tests/integration/helpers.sh: -------------------------------------------------------------------------------- 1 | # Max number of seconds for programs to be available in test run. 2 | MAX_WAIT=60 3 | 4 | # 5 | # Waits until the specified URL is reachable. 6 | # 7 | function waitforurl { 8 | local url=$1 9 | 10 | i=0 11 | wget $url 12 | while [ $? -ne 8 ] 13 | do 14 | ((i=i+1)) 15 | if [[ "$i" -gt $MAX_WAIT ]]; then 16 | return -1 17 | fi 18 | sleep 1s 19 | wget $url 20 | done 21 | 22 | return 0 23 | } 24 | 25 | # 26 | # Waits until the procdump child process has become available 27 | # 28 | function waitforprocdump { 29 | local -n result=$1 30 | 31 | i=0 32 | pid=$(ps -o pid= -C "procdump" | tr -d ' ') 33 | while [ ! $pid ] 34 | do 35 | ((i=i+1)) 36 | if [[ "$i" -gt $MAX_WAIT ]]; then 37 | result=-1 38 | return 39 | fi 40 | sleep 1s 41 | pid=$(ps -o pid= -C "procdump" | tr -d ' ') 42 | done 43 | 44 | result=$pid 45 | } 46 | 47 | # 48 | # Waits until the procdump status socket (in case of .net apps) is available 49 | # 50 | function waitforprocdumpsocket { 51 | local procdumpchildpid=$1 52 | local testchildpid=$2 53 | local -n result=$3 54 | 55 | ps -A -l 56 | 57 | if [[ -v TMPDIR ]]; 58 | then 59 | tmpfolder=$TMPDIR 60 | else 61 | tmpfolder="/tmp" 62 | fi 63 | prefixname="/procdump/procdump-status-" 64 | socketpath=$tmpfolder$prefixname$procdumpchildpid"-"$testchildpid 65 | 66 | echo "ProcDump .NET status socket: "$socketpath 67 | echo "List of ProcDump sockets:" 68 | sudo ls /tmp/procdump 69 | 70 | i=0 71 | while [ ! -S $socketpath ] 72 | do 73 | ((i=i+1)) 74 | if [[ "$i" -gt $MAX_WAIT ]]; then 75 | echo "List of ProcDump sockets:" 76 | sudo ls /tmp/procdump 77 | echo "ProcDump .NET status socket not available within alloted time" 78 | result=-1 79 | return 80 | fi 81 | sleep 1s 82 | done 83 | 84 | sudo ls /tmp/procdump 85 | echo "ProcDump .NET status socket found" 86 | result=$socketpath 87 | } -------------------------------------------------------------------------------- /tests/integration/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "You can optionally specify a specific test script to run rather than running all (default)" 4 | echo "NOTE: If you manually install .NET, this script assumes the installation directory is /usr/share/dotnet" 5 | 6 | failed=0 7 | failedTests="\n" 8 | 9 | rootcheck () { 10 | if [ $(id -u) != "0" ] 11 | then 12 | sudo "$0" "$@" 13 | exit $? 14 | fi 15 | } 16 | 17 | rootcheck 18 | 19 | if [[ $EUID -ne 0 ]]; then 20 | echo "This script must be run as root" 21 | exit 1 22 | fi 23 | 24 | OS=$(uname -s) 25 | if [ "$OS" != "Darwin" ]; then 26 | if [ ! -e /usr/bin/stress-ng ]; then 27 | echo "Please install stress-ng before running this script!" 28 | exit 1 29 | fi 30 | fi 31 | # NOTE: If you manually install .NET, this script assumes the installation directory is /usr/share/dotnet" 32 | DOTNET_PATH=$(which dotnet) 33 | 34 | if [ -z "$DOTNET_PATH" ] && [ "$OS" != "Darwin" ]; then 35 | export PATH=$PATH:/usr/share/dotnet 36 | fi 37 | 38 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 39 | 40 | function runTest { 41 | printf "\n========================================================================================\n" 42 | printf "\nStarting $(basename $1)\n" 43 | $1 "../../../procdump" 44 | 45 | if [ $? -ne 0 ]; then 46 | echo "$(basename $1) failed" 47 | failedTests="$failedTests$(basename $1)\n" 48 | failed=1 49 | else 50 | echo "$(basename $1) passed" 51 | fi 52 | } 53 | 54 | 55 | scenarioDir="" 56 | if [ "$OS" = "Darwin" ]; then 57 | scenarioDir=$DIR/scenarios_mac 58 | else 59 | scenarioDir=$DIR/scenarios 60 | fi 61 | 62 | echo "Running tests in $scenarioDir" 63 | 64 | for file in $scenarioDir/*.sh; 65 | do 66 | if [ ! -z "$1" ]; then 67 | if [[ "$file" =~ "$1" ]]; then 68 | runTest $file 69 | fi 70 | else 71 | runTest $file 72 | fi 73 | done 74 | 75 | printf "\nFailed tests: $failedTests" 76 | 77 | if [ "$failed" -eq "1" ]; then 78 | exit 1 79 | else 80 | exit 0 81 | fi 82 | -------------------------------------------------------------------------------- /tests/integration/runProcDumpAndValidate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function runProcDumpAndValidate { 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 4 | PROCDUMPPATH="$DIR/../../procdump"; 5 | 6 | OS=$(uname -s) 7 | 8 | # In cases where the previous scenario is still writing a dump we simply want to kill it 9 | pkill -9 gdb > /dev/null 10 | 11 | # Make absolutely sure we cleanup dumps from prior run 12 | rm -rf /tmp/dump_* 13 | 14 | dumpDir=$(mktemp -d -t dump_XXXXXX) 15 | cd $dumpDir 16 | 17 | dumpParam="" 18 | if [ -n "$DUMPTARGET" ]; then 19 | dumpParam="$dumpDir/$DUMPTARGET" 20 | fi 21 | 22 | if [ -z "$TESTPROGNAME" ]; then 23 | echo [`date +"%T.%3N"`] Starting stress-ng 24 | if [ "$RESTYPE" == "MEM" ]; then 25 | stress-ng --vm 1 --vm-hang 0 --vm-bytes $TARGETVALUE -q& 26 | else 27 | stress-ng -c 1 -l $TARGETVALUE -q& 28 | fi 29 | pid=$! 30 | echo "PID: $pid" 31 | 32 | # Give test app opportunity to start and get into scenario state 33 | sleep 5 34 | echo [`date +"%T.%3N"`] Done waiting for stress-ng to start 35 | 36 | childrenpid="" 37 | if [ "$OS" = "Darwin" ]; then 38 | childrenpid=$(pgrep stress-ng | grep -v "^$pid$") 39 | else 40 | childrenpid=$(pidof -o $pid $(which stress-ng)) 41 | fi 42 | 43 | echo "ChildrenPID: $childrenpid" 44 | 45 | childpid=$(echo $childrenpid | cut -d " " -f1) 46 | echo "ChildPID: $childpid" 47 | 48 | # We launch procdump in background and wait for 10 secs to complete the monitoring 49 | echo "$PROCDUMPPATH -log stdout $PREFIX $childpid $POSTFIX $dumpParam " 50 | echo [`date +"%T.%3N"`] Starting ProcDump 51 | $PROCDUMPPATH -log stdout $PREFIX $childpid $POSTFIX $dumpParam& 52 | pidPD=$! 53 | echo "ProcDump PID: $pidPD" 54 | sleep 30 55 | echo [`date +"%T.%3N"`] Killing ProcDump 56 | if ps -p $pidPD > /dev/null 57 | then 58 | kill -9 $pidPD > /dev/null 59 | fi 60 | if ps -p $childpid > /dev/null 61 | then 62 | kill -9 $childpid > /dev/null 63 | fi 64 | else 65 | # We launch procdump in background and wait for target process to start 66 | echo [`date +"%T.%3N"`] Starting ProcDump 67 | echo "$PROCDUMPPATH -log stdout $PREFIX -w $TESTPROGNAME" $POSTFIX $dumpParam 68 | $PROCDUMPPATH -log stdout $PREFIX -w "$TESTPROGNAME" $POSTFIX $dumpParam& 69 | pidPD=$! 70 | echo "ProcDump PID: $pidPD" 71 | 72 | # Wait for procdump to initialize 73 | sleep 10 74 | 75 | # Launch target process 76 | echo [`date +"%T.%3N"`] Starting $TESTPROGNAME 77 | if [ "$OS" = "Darwin" ]; then 78 | TESTPROGPATH=$DIR/../../$TESTPROGNAME; 79 | else 80 | TESTPROGPATH=$(readlink -m "$DIR/../../$TESTPROGNAME"); 81 | fi 82 | ($TESTPROGPATH "$TESTPROGMODE") & 83 | pid=$! 84 | echo "Test App: $TESTPROGPATH $TESTPROGMODE" 85 | echo "PID: $pid" 86 | 87 | sleep 30 88 | if ps -p $pidPD > /dev/null 89 | then 90 | echo [`date +"%T.%3N"`] Killing ProcDump: $pidPD 91 | kill -9 $pidPD > /dev/null 92 | fi 93 | fi 94 | 95 | if ps -p $pid > /dev/null 96 | then 97 | kill -9 $pid > /dev/null 98 | fi 99 | 100 | # If we are checking restrack results 101 | if [[ $PREFIX == *"-restrack"* ]]; then 102 | foundFile=$(find "$dumpDir" -mindepth 1 -name "*.restrack" -print -quit) 103 | if [[ -n $foundFile ]]; then 104 | pwd 105 | if [ $(stat -c%s "$foundFile") -gt 19 ]; then 106 | exit 0 107 | fi 108 | fi 109 | exit 1; 110 | fi 111 | 112 | # We're checking dump results 113 | if find "$dumpDir" -mindepth 1 -print -quit | grep -q .; then 114 | if $SHOULDDUMP; then 115 | exit 0 116 | else 117 | exit 1 118 | fi 119 | else 120 | if $SHOULDDUMP; then 121 | exit 1 122 | else 123 | exit 0 124 | fi 125 | fi 126 | } 127 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_0ExceptionDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "ProcDump path "$1 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 4 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 5 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 6 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 7 | 8 | source $HELPERS 9 | 10 | pushd . 11 | cd $TESTWEBAPIPATH 12 | rm -rf *TestWebApi_*Exception* 13 | pkill -9 TestWebApi 14 | pkill -9 procdump 15 | dotnet restore --configfile ../../../../nuget.config 16 | dotnet run --urls=http://localhost:5032& 17 | 18 | # waiting TestWebApi ready to service 19 | waitforurl http://localhost:5032/throwinvalidoperation 20 | if [ $? -eq -1 ]; then 21 | pkill -9 TestWebApi 22 | popds 23 | exit 1 24 | fi 25 | 26 | sudo $PROCDUMPPATH -log stdout -e -w TestWebApi& 27 | 28 | # waiting for procdump child process 29 | PROCDUMPCHILDPID=-1 30 | waitforprocdump PROCDUMPCHILDPID 31 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 32 | pkill -9 TestWebApi 33 | pkill -9 procdump 34 | popd 35 | exit 1 36 | fi 37 | 38 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 39 | 40 | #make sure procdump ready to capture before throw exception by checking if socket created 41 | SOCKETPATH=-1 42 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 43 | if [ $SOCKETPATH -eq -1 ]; then 44 | pkill -9 TestWebApi 45 | pkill -9 procdump 46 | popd 47 | exit 1 48 | fi 49 | echo "SOCKETPATH: "$SOCKETPATH 50 | 51 | wget http://localhost:5032/throwinvalidoperation 52 | 53 | sudo pkill -9 procdump 54 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 55 | if [ -S $SOCKETPATH ]; 56 | then 57 | rm $SOCKETPATH 58 | fi 59 | 60 | if [[ "$COUNT" -eq 1 ]]; then 61 | rm -rf *TestWebApi_*Exception* 62 | popd 63 | 64 | #check to make sure profiler so is unloaded 65 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 66 | pkill -9 TestWebApi 67 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 68 | exit 1 69 | else 70 | exit 0 71 | fi 72 | else 73 | pkill -9 TestWebApi 74 | popd 75 | exit 1 76 | fi 77 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_0WildcardExceptionDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f invalid -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -eq 1 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | popd 59 | 60 | #check to make sure profiler so is unloaded 61 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 62 | pkill -9 TestWebApi 63 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 64 | exit 1 65 | else 66 | exit 0 67 | fi 68 | else 69 | pkill -9 TestWebApi 70 | popd 71 | exit 1 72 | fi 73 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1FilterExceptionMsgDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f "current state" -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -eq 1 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | popd 59 | 60 | #check to make sure profiler so is unloaded 61 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 62 | pkill -9 TestWebApi 63 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 64 | exit 1 65 | else 66 | exit 0 67 | fi 68 | else 69 | pkill -9 TestWebApi 70 | popd 71 | exit 1 72 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1WildcardExceptionDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f Invali*xception -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -eq 1 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | popd 59 | 60 | #check to make sure profiler so is unloaded 61 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 62 | pkill -9 TestWebApi 63 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 64 | exit 1 65 | else 66 | exit 0 67 | fi 68 | else 69 | pkill -9 TestWebApi 70 | popd 71 | exit 1 72 | fi 73 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1WildcardFilterExceptionMsgDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f "*current*sta*" -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -eq 1 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | popd 59 | 60 | #check to make sure profiler so is unloaded 61 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 62 | pkill -9 TestWebApi 63 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 64 | exit 1 65 | else 66 | exit 0 67 | fi 68 | else 69 | pkill -9 TestWebApi 70 | popd 71 | exit 1 72 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1_gc_gen_1_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_gen_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 2 dumps (gc start and finish) for generation 1 23 | sudo $PROCDUMPPATH -log stdout -gcgen 1 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/fullgc 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_gen_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 2 ]]; then 58 | rm -rf *TestWebApi_*gc_gen_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1_gc_threshold_1_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_size_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 1 GC commit thresholds (10MB) 23 | sudo $PROCDUMPPATH -log stdout -gcm 10 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/memincrease 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_size_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 1 ]]; then 58 | rm -rf *TestWebApi_*gc_size_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1exceptionDump1Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f System.InvalidOperationException -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -eq 1 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | popd 59 | 60 | #check to make sure profiler so is unloaded 61 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 62 | pkill -9 TestWebApi 63 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 64 | exit 1 65 | else 66 | exit 0 67 | fi 68 | else 69 | pkill -9 TestWebApi 70 | popd 71 | exit 1 72 | fi 73 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_1exceptionDump2Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f System.InvalidOperationException -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | wget http://localhost:5032/throwinvalidoperation 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 1 ]]; then 58 | rm -rf *TestWebApi_*Exception* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_2WildcardExceptionDump2Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -n 2 -e -f In*rat*ption -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | wget http://localhost:5032/throwinvalidoperation 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 2 ]]; then 58 | rm -rf *TestWebApi_*Exception* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_2exceptionDump2Thrown_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -n 2 -e -f System.InvalidOperationException -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | wget http://localhost:5032/throwinvalidoperation 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 2 ]]; then 58 | rm -rf *TestWebApi_*Exception* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_3_gc_thresholds_3_dumps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_size_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 3 GC commit thresholds (10, 20 and 30MB) 23 | sudo $PROCDUMPPATH -log stdout -gcm 10,20,30 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/memincrease 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_size_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 3 ]]; then 58 | rm -rf *TestWebApi_*gc_size_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_LOH_thresholds_3_dumps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_size_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 3 GC commit thresholds (10, 20 and 30MB) 23 | sudo $PROCDUMPPATH -log stdout -gcm LOH:10,20,30 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/memincrease 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_size_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 3 ]]; then 58 | rm -rf *TestWebApi_*gc_size_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_MemMultipleDumps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*commit* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -m 10,20,30 -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | COUNT=( $(ls *TestWebApi_*commit* 2>/dev/null | wc -l) ) 35 | i=0 36 | while [ $COUNT -ne 3 ] 37 | do 38 | ((i=i+1)) 39 | if [[ "$i" -gt 60 ]]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | return 45 | fi 46 | sleep 1s 47 | COUNT=( $(ls *TestWebApi_*commit* 2>/dev/null | wc -l) ) 48 | done 49 | 50 | sudo pkill -9 procdump 51 | pkill -9 TestWebApi 52 | 53 | rm -rf *TestWebApi_*commit* 54 | popd 55 | if [[ "$COUNT" -eq 3 ]]; then 56 | 57 | exit 0 58 | else 59 | exit 1 60 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_POH_thresholds_3_dumps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_size_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 3 GC commit thresholds (10, 20 and 30MB) 23 | sudo $PROCDUMPPATH -log stdout -gcm POH:10,20,30 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/memincrease 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_size_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 3 ]]; then 58 | rm -rf *TestWebApi_*gc_size_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_exception_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f System.NonExistingException -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -ne 0 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | sudo pkill -9 TestWebApi 59 | popd 60 | exit 1 61 | else 62 | popd 63 | 64 | #check to make sure profiler so is unloaded 65 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 66 | pkill -9 TestWebApi 67 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 68 | exit 1 69 | else 70 | exit 0 71 | fi 72 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_gen_2_thresholds_3_dumps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*gc_size_* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | # Wait for 3 GC commit thresholds (10, 20 and 30MB) 23 | sudo $PROCDUMPPATH -log stdout -gcm 2:4,6,8 -w TestWebApi& 24 | 25 | # waiting for procdump child process 26 | PROCDUMPCHILDPID=-1 27 | waitforprocdump PROCDUMPCHILDPID 28 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 29 | pkill -9 TestWebApi 30 | pkill -9 procdump 31 | popd 32 | exit 1 33 | fi 34 | 35 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 36 | 37 | #make sure procdump ready to capture before throw exception by checking if socket created 38 | SOCKETPATH=-1 39 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 40 | if [ $SOCKETPATH -eq -1 ]; then 41 | pkill -9 TestWebApi 42 | pkill -9 procdump 43 | popd 44 | exit 1 45 | fi 46 | echo "SOCKETPATH: "$SOCKETPATH 47 | 48 | wget -O /dev/null http://localhost:5032/memincrease 49 | 50 | sudo pkill -9 procdump 51 | COUNT=( $(ls *TestWebApi_*gc_size_* | wc -l) ) 52 | if [ -S $SOCKETPATH ]; 53 | then 54 | rm $SOCKETPATH 55 | fi 56 | 57 | if [[ "$COUNT" -eq 3 ]]; then 58 | rm -rf *TestWebApi_*gc_size_* 59 | popd 60 | 61 | #check to make sure profiler so is unloaded 62 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 63 | pkill -9 TestWebApi 64 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 65 | exit 1 66 | else 67 | exit 0 68 | fi 69 | else 70 | pkill -9 TestWebApi 71 | popd 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_sigint_procdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | sudo kill -2 ${PROCDUMPCHILDPID} 48 | popd 49 | 50 | sleep 1s 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | #check to make sure profiler so is unloaded 57 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 58 | pkill -9 TestWebApi 59 | pkill -9 procdump 60 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 61 | exit 1 62 | else 63 | exit 0 64 | fi -------------------------------------------------------------------------------- /tests/integration/scenarios/dotnet_wildcardexception_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | PROCDUMPPATH=$(readlink -m "$DIR/$1"); 4 | TESTWEBAPIPATH=$(readlink -m "$DIR/../TestWebApi"); 5 | HELPERS=$(readlink -m "$DIR/../helpers.sh"); 6 | 7 | source $HELPERS 8 | 9 | pushd . 10 | cd $TESTWEBAPIPATH 11 | rm -rf *TestWebApi_*Exception* 12 | dotnet run --urls=http://localhost:5032& 13 | 14 | # waiting TestWebApi ready to service 15 | waitforurl http://localhost:5032/throwinvalidoperation 16 | if [ $? -eq -1 ]; then 17 | pkill -9 TestWebApi 18 | popds 19 | exit 1 20 | fi 21 | 22 | sudo $PROCDUMPPATH -log stdout -e -f on*Existing -w TestWebApi& 23 | 24 | # waiting for procdump child process 25 | PROCDUMPCHILDPID=-1 26 | waitforprocdump PROCDUMPCHILDPID 27 | if [ $PROCDUMPCHILDPID -eq -1 ]; then 28 | pkill -9 TestWebApi 29 | pkill -9 procdump 30 | popd 31 | exit 1 32 | fi 33 | 34 | TESTCHILDPID=$(ps -o pid= -C "TestWebApi" | tr -d ' ') 35 | 36 | #make sure procdump ready to capture before throw exception by checking if socket created 37 | SOCKETPATH=-1 38 | waitforprocdumpsocket $PROCDUMPCHILDPID $TESTCHILDPID SOCKETPATH 39 | if [ $SOCKETPATH -eq -1 ]; then 40 | pkill -9 TestWebApi 41 | pkill -9 procdump 42 | popd 43 | exit 1 44 | fi 45 | echo "SOCKETPATH: "$SOCKETPATH 46 | 47 | wget http://localhost:5032/throwinvalidoperation 48 | 49 | sudo pkill -9 procdump 50 | COUNT=( $(ls *TestWebApi_*Exception* | wc -l) ) 51 | if [ -S $SOCKETPATH ]; 52 | then 53 | rm $SOCKETPATH 54 | fi 55 | 56 | if [[ "$COUNT" -ne 0 ]]; then 57 | rm -rf *TestWebApi_*Exception* 58 | sudo pkill -9 TestWebApi 59 | popd 60 | exit 1 61 | else 62 | popd 63 | 64 | #check to make sure profiler so is unloaded 65 | PROF="$(cat /proc/${TESTCHILDPID}/maps | awk '{print $6}' | grep '\procdumpprofiler.so' | uniq)" 66 | pkill -9 TestWebApi 67 | if [[ "$PROF" == "procdumpprofiler.so" ]]; then 68 | exit 1 69 | else 70 | exit 0 71 | fi 72 | fi 73 | -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-c 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate 25 | 26 | -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="burn" 8 | 9 | # This are all the ProcDump switches preceeding the target 10 | PREFIX="-c 50" 11 | 12 | # This are all the ProcDump switches after the target 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | # RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu_custom_core_file_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-c 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # The dump target 19 | DUMPTARGET="custom_dump_file" 20 | 21 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu_nonexisting_output_directory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-c 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=false 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="missing_subdir/custom_dump_file" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="mem" 8 | 9 | # TARGETVALUE is only used for stress-ng 10 | TARGETVALUE=20 11 | 12 | # These are all the ProcDump switches preceeding the PID 13 | PREFIX="-c 80" 14 | 15 | # This are all the ProcDump switches after the PID 16 | POSTFIX="" 17 | 18 | # Indicates whether the test should result in a dump or not 19 | SHOULDDUMP=false 20 | 21 | # Only applicable to stress-ng and can be either MEM or CPU 22 | #RESTYPE="CPU" 23 | 24 | # The dump target 25 | DUMPTARGET="" 26 | 27 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_cpu_trigger_cpu_memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-m 1000 -c 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate 25 | 26 | -------------------------------------------------------------------------------- /tests/integration/scenarios/high_fd_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | OS=$(uname -s) 4 | if [ "$OS" = "Darwin" ]; then 5 | runProcDumpAndValidate=$DIR/../runProcDumpAndValidate.sh; 6 | else 7 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 8 | fi 9 | 10 | source $runProcDumpAndValidate 11 | 12 | TESTPROGNAME="ProcDumpTestApplication" 13 | TESTPROGMODE="fc" 14 | 15 | # These are all the ProcDump switches preceeding the PID 16 | PREFIX="-fc 100" 17 | 18 | # This are all the ProcDump switches after the PID 19 | POSTFIX="" 20 | 21 | # Indicates whether the test should result in a dump or not 22 | SHOULDDUMP=true 23 | 24 | # Only applicable to stress-ng and can be either MEM or CPU 25 | RESTYPE="" 26 | 27 | # The dump target 28 | DUMPTARGET="" 29 | 30 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_fd_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="fc" 8 | 9 | # TARGETVALUE is only used for stress-ng 10 | #TARGETVALUE=3M 11 | 12 | # These are all the ProcDump switches preceeding the PID 13 | PREFIX="-fc 1000" 14 | 15 | # This are all the ProcDump switches after the PID 16 | POSTFIX="" 17 | 18 | # Indicates whether the test should result in a dump or not 19 | SHOULDDUMP=false 20 | 21 | # Only applicable to stress-ng and can be either MEM or CPU 22 | RESTYPE="" 23 | 24 | # The dump target 25 | DUMPTARGET="" 26 | 27 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-m 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_mem_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=60M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-m 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=false 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_mem_trigger_cpu_memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=90M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-c 100 -m 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate 25 | -------------------------------------------------------------------------------- /tests/integration/scenarios/high_tc_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | OS=$(uname -s) 4 | if [ "$OS" = "Darwin" ]; then 5 | runProcDumpAndValidate=$DIR/../runProcDumpAndValidate.sh; 6 | else 7 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 8 | fi 9 | 10 | source $runProcDumpAndValidate 11 | 12 | TESTPROGNAME="ProcDumpTestApplication" 13 | TESTPROGMODE="tc" 14 | 15 | # TARGETVALUE is only used for stress-ng 16 | #TARGETVALUE=3M 17 | 18 | # These are all the ProcDump switches preceeding the PID 19 | PREFIX="-tc 50" 20 | 21 | # This are all the ProcDump switches after the PID 22 | POSTFIX="" 23 | 24 | # Indicates whether the test should result in a dump or not 25 | SHOULDDUMP=true 26 | 27 | # Only applicable to stress-ng and can be either MEM or CPU 28 | RESTYPE="" 29 | 30 | # The dump target 31 | DUMPTARGET="" 32 | 33 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/high_tc_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="tc" 8 | 9 | # TARGETVALUE is only used for stress-ng 10 | #TARGETVALUE=3M 11 | 12 | # These are all the ProcDump switches preceeding the PID 13 | PREFIX="-tc 500" 14 | 15 | # This are all the ProcDump switches after the PID 16 | POSTFIX="" 17 | 18 | # Indicates whether the test should result in a dump or not 19 | SHOULDDUMP=false 20 | 21 | # Only applicable to stress-ng and can be either MEM or CPU 22 | RESTYPE="" 23 | 24 | # The dump target 25 | DUMPTARGET="" 26 | 27 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_cpu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=10 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-cl 20" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_cpu_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | TESTPROGNAME="ProcDumpTestApplication" 5 | TESTPROGMODE="sleep" 6 | source $runProcDumpAndValidate 7 | 8 | # TARGETVALUE is only used for stress-ng 9 | TARGETVALUE=10 10 | 11 | # These are all the ProcDump switches preceeding the PID 12 | PREFIX="-cl 20" 13 | 14 | # This are all the ProcDump switches after the PID 15 | POSTFIX="" 16 | 17 | # Indicates whether the test should result in a dump or not 18 | SHOULDDUMP=true 19 | 20 | # Only applicable to stress-ng and can be either MEM or CPU 21 | RESTYPE="CPU" 22 | 23 | # The dump target 24 | DUMPTARGET="" 25 | 26 | runProcDumpAndValidate 27 | -------------------------------------------------------------------------------- /tests/integration/scenarios/low_cpu_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=80 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-cl 20" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=false 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_cpu_trigger_cpu_memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=10 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-m 1000 -cl 20" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=40M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-ml 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_mem_notdump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=200M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-ml 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=false 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/low_mem_trigger_cpu_memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=40M 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="-c 100 -ml 80" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="MEM" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios/ondemand.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$(readlink -m "$DIR/../runProcDumpAndValidate.sh"); 4 | source $runProcDumpAndValidate 5 | 6 | # TARGETVALUE is only used for stress-ng 7 | TARGETVALUE=1 8 | 9 | # These are all the ProcDump switches preceeding the PID 10 | PREFIX="" 11 | 12 | # This are all the ProcDump switches after the PID 13 | POSTFIX="" 14 | 15 | # Indicates whether the test should result in a dump or not 16 | SHOULDDUMP=true 17 | 18 | # Only applicable to stress-ng and can be either MEM or CPU 19 | RESTYPE="CPU" 20 | 21 | # The dump target 22 | DUMPTARGET="" 23 | 24 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios_mac/high_cpu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$DIR/../runProcDumpAndValidate.sh; 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="burn" 8 | 9 | # TARGETVALUE is only used for stress-ng 10 | #TARGETVALUE=3M 11 | 12 | # These are all the ProcDump switches preceeding the PID 13 | PREFIX="-c 50" 14 | 15 | # This are all the ProcDump switches after the PID 16 | POSTFIX="" 17 | 18 | # Indicates whether the test should result in a dump or not 19 | SHOULDDUMP=true 20 | 21 | # Only applicable to stress-ng and can be either MEM or CPU 22 | RESTYPE="" 23 | 24 | # The dump target 25 | DUMPTARGET="" 26 | 27 | runProcDumpAndValidate 28 | 29 | -------------------------------------------------------------------------------- /tests/integration/scenarios_mac/high_fd_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source scenarios/high_fd_by_name.sh 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/integration/scenarios_mac/high_mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; 3 | runProcDumpAndValidate=$DIR/../runProcDumpAndValidate.sh; 4 | source $runProcDumpAndValidate 5 | 6 | TESTPROGNAME="ProcDumpTestApplication" 7 | TESTPROGMODE="mem" 8 | 9 | # TARGETVALUE is only used for stress-ng 10 | #TARGETVALUE=3M 11 | 12 | # These are all the ProcDump switches preceeding the PID 13 | PREFIX="-m 1" 14 | 15 | # This are all the ProcDump switches after the PID 16 | POSTFIX="" 17 | 18 | # Indicates whether the test should result in a dump or not 19 | SHOULDDUMP=true 20 | 21 | # Only applicable to stress-ng and can be either MEM or CPU 22 | RESTYPE="" 23 | 24 | # The dump target 25 | DUMPTARGET="" 26 | 27 | runProcDumpAndValidate -------------------------------------------------------------------------------- /tests/integration/scenarios_mac/high_tc_by_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source scenarios/high_tc_by_name.sh -------------------------------------------------------------------------------- /tests/integration/signal/makefile: -------------------------------------------------------------------------------- 1 | signaltest: signaltest.c 2 | gcc -o signaltest signaltest.c -I. 3 | -------------------------------------------------------------------------------- /tests/integration/signal/signaltest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/ProcDump-for-Linux/f3d469ac1aa242e52beb3647ef9beb23b02c4247/tests/integration/signal/signaltest -------------------------------------------------------------------------------- /tests/integration/signal/signaltest.c: -------------------------------------------------------------------------------- 1 | // 2 | // Used to test the signal triggering (and forwarding) of procdump. 3 | // 4 | // 1. Run this test app (it registers for the first 23 signals). 5 | // 2. Run procdump against this pid 6 | // 3. use kill to send whichever signal you are interested in triggering procdump (or not trigger) 7 | // 4. Make sure in all cases (except for signals that can't be intercepted) that this program outputs "Caught signal X" 8 | // where X is the signal you sent. If the output does not show that signal being handled, it means the signal forwarding 9 | // in procdump is not working properly and needs to be investigated. 10 | // 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | void sig_handler(int signum) 20 | { 21 | if(signum==SIGINT) 22 | { 23 | exit(-1); 24 | } 25 | 26 | // We shouldnt be using printf in a signal handler but in this simple test case its fine 27 | printf("Caught signal: %d\n", signum); 28 | } 29 | 30 | void main(int argc, char** argv) 31 | { 32 | for(int i=0; i<24; i++) 33 | { 34 | signal(i, sig_handler); 35 | } 36 | 37 | while(1) 38 | { 39 | pause(); 40 | } 41 | } --------------------------------------------------------------------------------