diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a3f77a1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,124 @@
+# ROCm Debugger
+
+## Overview
+The ROCm Debugger provides a gdb-based debugging environment for debugging host application and GPU kernels running on Radeon Open Compute platforms (ROCm).
+It can support all language runtimes (such as HIP and HCC) built on top of ROCm. Initially, the debugging support within the GPU kernels starts with the
+HSAIL 1.0 programming language. This support requires a kernel compilation path that goes through HSAIL kernel (such as through HCC-HSAIL or [libHSAIL/HSAILAsm](https://github.com/HSAFoundation/HSAIL-Tools)).
+
+There are two packages included in this release:
+* ROCm gdb package that contains the rocm-gdb tool
+ * based on GDB 7.11, the GNU source-level debugger
+* ROCm GPU Debug SDK package that contains the necessary header, library and sample files to run the rocm-gdb tool
+
+The ROCm Debugger extends the existing [HSA Debugger](https://github.com/HSAFoundation/HSA-Debugger-AMD) with new features for ROCm .
+
+## Table of Contents
+* [Major Features](#Major)
+* [What's New](#WhatsNew)
+* [System Requirements](#System)
+* [Package Contents](#Package)
+* [Installation](#Installation)
+* [Usage Examples](TUTORIAL.md)
+* [Known Issues](#Known)
+* [ROCm GDB LICENSE](gdb/LICENSE.txt) and [SDK LICENSE](gpudebugsdk/LICENSE.txt)
+
+
+## Major Features
+* Seamless host application and GPU kernel source debugging using a familiar gdb-based debugging environment on ROCm
+* Set GPU kernel breakpoints, single stepping and inspect registers within HSAIL kernel source
+* View active GPU states (active work-groups, work-items and wavefronts information)
+* Disassemble GPU kernel at GPU kernel function and source breakpoint
+* Trace GPU kernel launches into an output file
+
+
+## What's New in Aug 2016 Release (version 1.2)
+* Compatible with [ROCm 1.2 release](https://github.com/RadeonOpenCompute/ROCm)
+* Update gdb base to gdb v7.11.
+* Initial support for provided GPU debug information via the GDB machine interface
+* Support for debugging applications that use SIGUSR2. (Provided by [Pull Request#1](https://github.com/RadeonOpenCompute/ROCm-GDB/pull/1) from Didier Nadeaud)
+* Add support to report HSAIL source text along with line number when single stepping.
+
+## What's New in April 2016 Release (version 1.0)
+* Compatible with [ROCm 1.0 release](https://github.com/RadeonOpenCompute/ROCm)
+* Support 6th Generation AMD A-series APU processors (codenamed “Carrizo”)
+* Support AMD Radeon™ R9 Fury, Fury X and Fury Nano GPUs (codenamed “Fiji”)
+* Support [CodeXL 2.0](https://github.com/GPUOpen-Tools/CodeXL/tree/v2.0)
+* Add support to gdb *disassemble* command to disassemble and show the GPU isa disassembly text
+* Add ability to trace GPU kernel launches
+* Add gdb *help rocm* command to show the list of rocm debugging related commands
+* Add support to report the hardware slot scheduling information for wavefronts
+
+
+## System Requirements
+* Boltzmann system
+ * CPU: CPUs with PCIe Gen3 Atomics: Haswell-class Intel(c) Core CPUs v3 or newer and Intel Xeon E5 v3 or newer.
+ * GPU: AMD Radeon™ R9 Fury, Fury X and Fury Nano GPUs (codenamed “Fiji”)
+ * Refer to the [ROCm platform requirements](https://radeonopencompute.github.io/hardware.html) for additional information
+* or 6th Generation AMD A-series APU processors (codenamed “Carrizo”).
+* OS: 64-bit Ubuntu 14.04
+* [ROCm 1.2 platform](https://github.com/RadeonOpenCompute/ROCm)
+
+To debug within a GPU kernel, the GPU kernel must be assembled using the latest [LibHSAIL/HSAILAsm](https://github.com/HSAFoundation/HSAIL-Tools) (from April 4th 2016 or newer) built with *BUILD_WITH_LIBBRIGDWARF=1*.
+
+
+## Package Contents
+The directory structure of the ROCm Debugger packages:
+* *gpudebugsdk*
+ * *include*
+ * *AMDGPUDebug.h*, *FacilitiesInterface.h*
+ * *bin/x86_64*
+ * *amd-debug-lock*, *rocm-gdb-debug-flags.sh*
+ * *lib/x86_64*
+ * *libAMDGPUDebugHSA-x64.so*, *libAMDHSADebugAgent-x64.so*, *libAMDHwDbgFacilities-x64.so*
+ * *samples*
+ * *Common*
+ * *HSAResourceManager.h*, *HSAResourceManager.cpp*, *HSAExtensionFinalizer.h*, *HSAExtensionFinalizer.cpp*
+ * *MatrixMultiplication*
+ * *Makefile*, *MatrixMul.cpp*, *matrixMul_kernel.brig*, *matrixMul_kernel.hsail*
+ * *LICENSE.txt*
+* *gdb*
+ * *bin/x86_64*
+ * *rocm-gdb*, *amd-gdb*, *.gdbinit*, *data-directory*
+ * *LICENSE.txt*
+* *ubuntu*
+ * *rocm-gpudebugsdk_\_amd64.deb*
+ * *rocm-gdb_\_amd64.deb*
+
+If you download the ROCm Debugger packages or files separately, you must create the same directory structure as shown above in order to run rocm-gdb successfully.
+
+
+## Installation
+First, make sure that the ROCm platform is setup correctly.
+* [Install ROCm](https://github.com/RadeonOpenCompute/ROCm#installing-from-amd-rocm-repositories)
+* [Verify the setup by running HSAIL *vector_copy* sample successfully](https://github.com/RadeonOpenCompute/ROCm#verify-installation)
+ * Note that with the default *vector_copy* sample, you can't single step within the GPU kernel as the GPU kernel is not compiled with debugging support.
+ * As part of the ROCm debugger package, there is a sample *MatrixMultiplication* that can be used with rocm-gdb.
+
+###ROCm Debugger Installation
+1. If you did not install ROCm Debugger as part of the ROCm installation, you can download the ROCm Debugger debian packages (*rocm-gpudebugsdk_\_amd64.deb* and *rocm-gdb_\_amd64.deb*) independently and install them as follows.
+ * `sudo dpkg -i rocm-gpudebugsdk__amd64.deb`
+ * `sudo dpkg -i rocm-gdb__amd64.deb`
+ * The installed files will be placed in */opt/rocm/gpudebugsdk* and */opt/rocm/gdb* folders.
+ * Note that both *rocm-gpudebugsdk* and *rocm-gdb* debian packages are included as part of the [ROCm](https://github.com/RadeonOpenCompute/ROCm#installing-from-amd-rocm-repositories) repo install.
+2. Verify the setup
+ * Run the *MatrixMultiplication* sample provided in the GPU Debug SDK package
+ * `cd /opt/rocm/gpudebugsdk/samples/MatrixMultiplication`
+ * `make`
+ * The *Makefile* assumes that the hsa header files are located at */opt/rocm/hsa/include*. If you encounter a compilation failure, please update the *HSADIR* within the *Makefile* to the directory of the hsa header files in the system.
+ * Note that *matrixMul_kernel.hsail* is included for reference only. This sample will load the pre-built brig binary (*matrixMul_kernel.brig*) to run the kernel.
+ * `/opt/rocm/bin/rocm-gdb MatrixMul`
+ * Tips: include the */opt/rocm/bin* in your *PATH* environment variable
+
+## Usage Examples
+Check out the [tutorial](TUTORIAL.md) for some usage examples.
+
+
+## Known Issues for August 2016 Release
+* HCC applications compiled with HCC-HSAIL and offline HSAIL finalization may experience inconsistent stepping behavior. HCC applications need to be compiled with the environment variable `HCC_NOISA=1`
+* Debugging hsa code objects that contain more than one BRIG module are not supported
+* Debugging HSAIL kernels that contain global (or read only) variables are not supported
+* Debugging HSAIL kernels that contain HSAIL function calls are not supported
+* Using rocm-gdb objects in python scripts is not yet supported
+* Single stepping branch instructions could require multiple step commands
+
+
diff --git a/TUTORIAL.md b/TUTORIAL.md
new file mode 100644
index 0000000..55589b9
--- /dev/null
+++ b/TUTORIAL.md
@@ -0,0 +1,383 @@
+## Table of Contents
+* [How do I debug my GPU application?](#HowDoIStart)
+* [How do I view the list of all ROCm gdb commands](#HelpROCm)
+* [How do I set breakpoints in my GPU application?](#HowDoISetBreakpoints)
+ * [Setting GPU function breakpoints](#SetGPUFunctionBreakpoints)
+ * [Setting GPU kernel source breakpoints](#SetGPUKernelSourceBreakpoints)
+ * [Setting conditional GPU kernel source breakpoints](#SetConditionalGPUKernelSourceBreakpoints)
+ * [Managing GPU breakpoints](#ManagingGPUBreakpoints)
+* [How do I single step in a GPU kernel?](#HowDoISingleStep)
+* [How do I print GPU registers?](#HowDoIPrintGPURegisters)
+* [How do I view the GPU ISA disassembly?](#HowDoIDisassemble)
+* [How do I view GPU dispatch info?](#HowDoIViewGPUDispatchInfo)
+* [How do I view a trace of GPU dispatches?](#HowDoITraceGPUDispatches)
+* [How do I compile GPU kernels for debug?](#HowDoICompileGPUKernelsForDebug)
+* [Generating logs for reporting Issues in rocm-gdb](#GeneratingLogs)
+* [Others](#Others)
+
+
+
+### How do I debug my GPU application?
+You can start your program in rocm-gdb just like you would any application under gdb
+* `rocm-gdb MatrixMul`
+* You should now be in the gdb prompt and can start execution of the application
+* `(ROCm-gdb) start`
+
+
+### How do I view the list of all ROCm gdb commands
+To view the list of all rocm related gdb commands, you can type `help rocm`.
+```
+(ROCm-gdb) help rocm
+ROCm specific features in ROCm-gdb.
+--------------------------------------------------------------------------
+ROCm focus thread command:
+rocm thread wg: wi: Switch focus to a specific active GPU work-item
+--------------------------------------------------------------------------
+ROCm breakpoint commands:
+break rocm Break on every GPU dispatch
+break rocm: Break when kernel is about to begin execution
+break rocm: Break when execution hits line in temp_source
+--------------------------------------------------------------------------
+ROCm info commands:
+info rocm kernels Print all GPU kernel dispatches
+info rocm kernel Print all GPU kernel dispatches with a specific
+info rocm [work-groups|wgs] Print all GPU work-group items
+info rocm [work-group|wg] [|] Print a specific GPU work-group item
+info rocm [work-item|wi|work-items|wis] Print the focus GPU work-item
+info rocm [work-item|wi] Print a specific GPU work-item
+--------------------------------------------------------------------------
+ROCm specific configuration commands:
+set rocm trace [on|off] Enable/Disable tracing of GPU dispatches
+set rocm trace Save GPU dispatch trace to
+set rocm logging [on|off] Enable/Disable internal logging
+set rocm show-isa [on|off] Enable/Disable saving ISA to a temp_isa file when in GPU dispatches
+--------------------------------------------------------------------------
+ROCm variable print commands:
+print rocm: Print value of for the focus work-item
+--------------------------------------------------------------------------
+To disassemble a GPU kernel:
+disassemble Show the GPU ISA disassembly text when at a GPU breakpoint
+--------------------------------------------------------------------------
+```
+
+
+### How do I set breakpoints in my GPU application?
+To set breakpoints in GPU kernels, rocm-gdb defines
+* **GPU kernel function breakpoint:** Similar to a gdb function breakpoint, allows you stop the application just before a **specific** GPU dispatch starts
+* **Generic GPU kernel breakpoint:** Stop the application before **any** GPU dispatch starts
+* **Source line breakpoint:** A breakpoint that is set on a particular line of GPU kernel source
+
+
+#### Setting GPU function breakpoints
+The gdb `break` command has been extended to `break rocm` in order to set GPU breakpoints.
+To set a specific GPU kernel function breakpoints:
+* `break rocm:`
+
+For matrix multiplication, you can specify the kernel name
+* `(ROCm-gdb) break rocm:&__OpenCL_matrixMul_kernel`
+
+This will stop the application's execution just before the GPU kernel (in this case, the matrix multiplication kernel) begins executing on the device.
+
+To set a general GPU kernel function breakpoint, use either of the following command:
+* `(ROCm-gdb) break rocm`
+* `(ROCm-gdb) break rocm:*`
+
+This will stop the application just before every dispatch begins executing on the device.
+
+
+#### Setting GPU kernel source breakpoints
+In order to break into GPU kernels, you need to set GPU source breakpoints. ROCm-gdb saves the kernel source for the present dispatch to a temporary file called *temp_source*. GPU source breakpoints can be set by specifying the line number from the *temp_source* GPU kernel source file. The *temp_source* file is overwritten by rocm-gdb on every GPU dispatch.
+
+Once you hit a kernel function breakpoint, you can view the *temp_source* file and choose a line number. You can set the source breakpoint using the syntax
+* `break rocm:`
+
+For example, this will set a breakpoint at line 150 in the *temp_source*
+
+```
+(ROCm-gdb) b rocm:150
+GPU breakpoint 1 (PC:0x08d0 mad_u32 $s0, $s1, $s0, $s3; temp_source@line 150)
+```
+
+When you continue the program's execution, the application will stop when any work-item reaches line 150 in *temp_source*.
+
+
+#### Setting Conditional GPU kernel source breakpoints
+Conditional GPU breakpoints allow you to stop the application only when a particular work-item hits a breakpoint. You can set a conditional source breakpoint by specifying the a work-item using the syntax:
+* `break rocm:line_number if wg:x,y,z wi:x,y,z`
+For example, this will set a breakpoint at line 150 and only stop the application if the work-item in workgroup 2,0,0 and local work-item 1,0,0
+```
+(ROCm-gdb) b rocm:150 if wg:2,0,0 wi:16,0,0
+GPU breakpoint 1 (PC:0x08d0 mad_u32 $s0, $s1, $s0, $s3; temp_source@line 150)
+```
+When the application is executed, the dispatch will stop when line 150 is executed for the above work-item as shown below:
+
+```
+[ROCm-gdb]: Switching to work-group (2,0,0) and work-item (1,0,0)
+[ROCm-gdb]: Condition: active work-group: 2, 0, 0 @ work-item: 1, 0, 0
+[ROCm-gdb]: Breakpoint 2 at mad_u32 $s0, $s1, $s0, $s3; temp_source@line 150
+Stopped on GPU breakpoint
+```
+
+#### Managing GPU breakpoints
+* You can use the same gdb commands such as `info bre` to view information about the active GPU and host breakpoints
+The command `info bre` shows multiple GPU kernel source breakpoints, an GPU function breakpoint and a host breakpoint
+
+```
+(ROCm-gdb) info bre
+Num Type Disp Enb Address What
+1 GPU breakpoint keep y --- Every GPU dispatch(*)
+breakpoint already hit 2 times
+4 GPU breakpoint keep y PC:0x06d8 add_u32 $s3, $s3, 1; temp_source@line 150
+breakpoint already hit 320 times
+5 GPU breakpoint keep y --- &__Gdt_vectoradd_kernel
+6 breakpoint keep y 0x0000000000407105 in RunTest() at MultiKernelDispatch.cpp:100
+```
+
+* You can also delete GPU breakpoints using the same command as GDB's host breakpoints `del breakpoint_number`
+
+
+### How do I single step in a GPU kernel?
+You can single step in a GPU dispatch using the conventional `step` command.
+Only a single step is supported at a time.
+
+The following shows how rocm-gdb steps 4 source lines after hitting a kernel source breakpoint
+
+```
+(ROCm-gdb) b rocm:64
+GPU breakpoint 2 (PC:0x02a0 workitemabsid_u32 $s0, 0; temp_source@line 64)
+(ROCm-gdb) c
+Continuing.
+[New Thread 0x7fffef286700 (LWP 2776)]
+[New Thread 0x7fffeea85700 (LWP 2777)]
+Waiting for completion...
+[Switching to Thread 0x7fffeea85700 (LWP 2777)]
+[ROCm-gdb]: Switching to work-group (5,4,0) and work-item (0,8,0)
+[ROCm-gdb]: Breakpoint 2 at PC:0x02a0 workitemabsid_u32 $s0, 0; temp_source@line 64
+Stopped on GPU breakpoint
+
+(ROCm-gdb) step
+[ROCm-gdb]: PC:0x02ac cvt_u64_u32 $d5, $s0; temp_source@line 65
+Stopped on GPU breakpoint
+
+(ROCm-gdb) s
+[ROCm-gdb]: PC:0x02d0 workitemabsid_u32 $s0, 1; temp_source@line 66
+Stopped on GPU breakpoint
+
+(ROCm-gdb) s
+[ROCm-gdb]: PC:0x02dc ld_kernarg_align(8)_width(all)_u64 $d6, [%__global_offset_0]; temp_source@line 67
+Stopped on GPU breakpoint
+
+(ROCm-gdb) s
+[ROCm-gdb]: PC:0x0304 add_u64 $d0, $d5, $d6; temp_source@line 68
+Stopped on GPU breakpoint
+
+(ROCm-gdb) c
+Continuing.
+```
+
+
+### How do I print GPU registers?
+To print registers in a GPU kernel, the gdb `print` command has been extended. To print GPU registers.
+* `print rocm:$register_name`
+
+This will print the value *$register_name* for a single work-item. For example, printing GPU register *$s0* will provide the value of register *$s0*
+
+```
+(ROCm-gdb) print rocm:$s0
+$4 = 0
+```
+
+To view the data of a different work-item, you need switch focus between different work-items. The `rocm thread` command allows you to set the focus on a different work-item by specifying its work-item and work-group ID. It should be noted that you cannot switch focus to work-items not scheduled on the device.
+
+Switching the focus to another work-item and printing *$s0* allows us to view data for the other work-item.
+
+```
+(ROCm-gdb) rocm thread wg:0,0,0 wi:1,0,0
+[ROCm-gdb]: Switching to work-group (0,0,0) and work-item (1,0,0)
+
+(ROCm-gdb) print rocm:$s0
+$3 = 1
+```
+
+
+###How do I view the GPU ISA disassembly?
+To view the GPU ISA disassembly, you can use the standard gdb *disassemble* command while gdb stops at the GPU function breakpoint or GPU kernel source breakpoint.
+
+While gdb stops at a GPU kernel source breakpoint, the program counter of the focus wave is shown with a (=>) prefix and some ISA instructions above and below the program counter are shown.
+
+```
+[ROCm-gdb]: Breakpoint 1 at GPU Kernel, &ZZ4mainEN3_EC__219__cxxamp_trampolineEPfiiiiiiifS0_iiiiiii()
+GPU kernel saved to temp_source
+Stopped on GPU breakpoint
+
+(ROCm-gdb) s
+[New Thread 0x7fffee0e9700 (LWP 3190)]
+[ROCm-gdb]: Switching to work-group (486,0,0) and work-item (256,0,0)
+[ROCm-gdb]: Breakpoint: at line 24
+Stopped on GPU breakpoint
+[Switching to Thread 0x7fffee0e9700 (LWP 3190)]
+
+(ROCm-gdb) disassemble
+Disassembly:
+ s_lshr_b32 s16, s16, 16 // 000000000144: 8F109010
+ s_mul_i32 s18, s12, s13 // 000000000148: 92120D0C
+ s_mul_i32 s20, s5, s15 // 00000000014C: 92140F05
+ s_movk_i32 s19, 0x0000 // 000000000150: B0130000
+ s_movk_i32 s21, 0x0000 // 000000000154: B0150000
+ s_add_u32 s18, s18, s20 // 000000000158: 80121412
+ s_addc_u32 s19, s19, s21 // 00000000015C: 82131513
+ s_movk_i32 s17, 0x0000 // 000000000160: B0110000
+ s_add_u32 s16, s16, s18 // 000000000164: 80101210
+ s_addc_u32 s17, s17, s19 // 000000000168: 82111311
+ s_lshr_b64 s[16:17], s[16:17], 16 // 00000000016C: 8F909010
+ s_mul_i32 s5, s5, s13 // 000000000170: 92050D05
+ s_add_u32 s5, s5, s16 // 000000000174: 80051005
+ s_mul_i32 s4, s4, s8 // 000000000178: 92040804
+ v_add_u32 v3, vcc, s4, v0 // 00000000017C: 32060004
+=> s_nop 0x0000 // 000000000180: BF800000
+ s_load_dword s4, s[6:7], 0x18 // 000000000184: C0020103 00000018
+ s_nop 0x0000 // 00000000018C: BF800000
+ s_load_dword s5, s[6:7], 0x40 // 000000000190: C0020143 00000040
+ s_nop 0x0000 // 000000000198: BF800000
+ s_load_dword s12, s[6:7], 0x20 // 00000000019C: C0020303 00000020
+ s_nop 0x0000 // 0000000001A4: BF800000
+ s_load_dword s13, s[6:7], 0x48 // 0000000001A8: C0020343 00000048
+ s_waitcnt lgkmcnt(0) // 0000000001B0: BF8C007F
+ s_nop 0x0000 // 0000000001B4: BF800000
+ v_add_u32 v9, vcc, s4, v3 // 0000000001B8: 32120604
+ s_nop 0x0000 // 0000000001BC: BF800000
+ v_add_u32 v13, vcc, s5, v3 // 0000000001C0: 321A0605
+ v_mov_b32 v5, s8 // 0000000001C4: 7E0A0208
+ s_nop 0x0000 // 0000000001C8: BF800000
+ v_ashrrev_i32 v10, 31, v9 // 0000000001CC: 2214129F
+...
+...
+Remaining GPU ISA saved to temp_isa
+```
+
+If you want to view the complete ISA for the GPU kernel, the ISA is saved to *temp_isa*.
+The *temp_isa* also provides important information about the kernel such as the number of registers used, compiler flags used and the GPU ISA version.
+
+An alternative method of viewing the ISA for every kernel is the `set rocm` option to save the ISA to a file whenever a GPU kernel is active.
+This can be enabled using the `set rocm show-isa` as shown below.
+
+```
+(ROCm-gdb) set rocm show-isa on
+```
+
+With this option, ROCm-gdb saves the ISA for the active kernel to *temp_isa* whenever a GPU kernel is active.
+
+
+### How do I view GPU dispatch info?
+The `info` command has been extended to `info rocm`.
+The `info rocm` command allows you to view the present state of the GPU dispatch and also allows you to view information about the GPU dispatches that have executed over the lifetime of the application.
+* `(ROCm-gdb) info rocm`
+
+This will print all the possible options for `info rocm`. The `info rocm` command allows you to view information about the active dispatch, active work-groups and active work-items on the device.
+The possible inputs to `info rocm` are below
+
+```
+info rocm kernels Print all GPU kernel dispatches
+info rocm kernel Print all GPU kernel dispatches with a specific
+info rocm [work-groups|wgs] Print all GPU work-group items
+info rocm [work-group|wg] [|] Print a specific GPU work-group item
+info rocm [work-item|wi|work-items|wis] Print the focus GPU work-item
+info rocm [work-item|wi] Print a specific GPU work-item
+```
+
+For example, `info rocm kernels` on an application that dispatches two kernels shows
+```
+(ROCm-gdb) info rocm kernels
+Kernels info
+Index KernelName DispatchCount # of Work-groups Work-group Dimensions
+ 0 &__Gdt_vectoradd_kernel 1 1,1,1 64,1,1
+ *1 &__OpenCL_matrixMul_kernel 1 8,5,1 16,16,1
+
+```
+
+The `info rocm work-groups` command will show the active work-groups for the active dispatch
+
+```
+(ROCm-gdb) info rocm work-groups
+Index Work-group ID Flattened Work-group ID
+ *0 0,0,0 0
+ 1 1,0,0 1
+ 2 2,0,0 2
+```
+
+The `info rocm wg 0` command will show the information of work-group 0 for the active dispatch
+
+```
+Information for Work-group 0
+Index Wave ID {SE,SH,CU,SIMD,Wave} Work-item ID Abs Work-item ID PC Source line
+ 0 0x408001c0 { 0, 0, 1, 0, 0} [0,12, 0 - 15,15, 0] [0,12, 0 - 15,15, 0] 0x2a8 temp_source@line 64
+ 1 0x408001d0 { 0, 0, 1, 1, 0} [0, 4, 0 - 15, 7, 0] [0, 4, 0 - 15, 7, 0] 0x2a8 temp_source@line 64
+ 2 0x408001e0 { 0, 0, 1, 2, 0} [0, 0, 0 - 15, 3, 0] [0, 0, 0 - 15, 3, 0] 0x2a8 temp_source@line 64
+ 3 0x408001f0 { 0, 0, 1, 3, 0} [0, 8, 0 - 15,11, 0] [0, 8, 0 - 15,11, 0] 0x2a8 temp_source@line 64
+```
+Wave ID contains the hardware slot ids where SE is the Shader Engine id, SH is the shader array id, CU is the Compute Unit id, SIMD is the SIMD id, and Wave is the wave slot id.
+
+The `info rocm work-item` command will show the focus work-item for the active dispatch
+
+```
+(ROCm-gdb) info rocm wi
+Information for Work-item
+Index Wave ID {SE,SH,CU,SIMD,Wave} Work-item ID Abs Work-item ID PC Source line
+ *0 0x408002d0 { 0, 0, 2, 1, 0} [0, 0, 0] [16, 0, 0] 0x68 temp_source@line 150
+```
+
+
+## How do I view a trace of GPU dispatches
+ROCm-gdb helps developers to view information about kernels that have been launched on the GPU using the rocm trace commands.
+ROCm-gdb can save a trace of all the GPU kernel launches to a Comma Separated Value (CSV) file using the `set rocm trace` command. The following commands enable tracing GPU kernel launches to `mytrace.csv`.
+```
+(ROCm-gdb) set rocm trace mytrace.csv
+
+(ROCm-gdb) set rocm trace on
+```
+
+You can now execute and debug the application within ROCm-gdb. Anytime during the application’s execution you can view `my_trace.csv` to see the kernels have been dispatched. A sample trace for an application that dispatches a vector add kernel followed by a matrix multiplication kernel in a loop is shown below.
+
+| index | queue_id | packet_id | kernel_name | header | setup | workgroup_size | reserved0 | grid_size | private_segment_size | group_segment_size | kernel_object | kernarg_address | reserved2 | completion_signal |
+|-------|-----------|-----------|----------------------------|--------|-------|----------------|-----------|------------|----------------------|--------------------|-----------------|-----------------|-----------|-------------------|
+| 0 | 380095252 | 0 | &__Gdt_vectoradd_kernel | 5122 | 1 | {64 1 1} | 0 | {64 1 1} | 0 | 0 | 140737353981952 | 0x713000 | 0 | 7513216 |
+| 1 | 380095252 | 1 | &__OpenCL_matrixMul_kernel | 5122 | 2 | {16 16 1} | 0 | {128 80 1} | 0 | 0 | 140737353983488 | 0x6ca000 | 0 | 7910848 |
+| 2 | 380095252 | 2 | &__Gdt_vectoradd_kernel | 5122 | 1 | {64 1 1} | 0 | {64 1 1} | 0 | 0 | 140737353977856 | 0x6e2000 | 0 | 7858432 |
+| 3 | 380095252 | 3 | &__OpenCL_matrixMul_kernel | 5122 | 2 | {16 16 1} | 0 | {128 80 1} | 0 | 0 | 140737353979392 | 0x6a3000 | 0 | 7177152 |
+| 4 | 380095252 | 4 | &__Gdt_vectoradd_kernel | 5122 | 1 | {64 1 1} | 0 | {64 1 1} | 0 | 0 | 140737353973760 | 0x666000 | 0 | 7981376 |
+| 5 | 380095252 | 5 | &__OpenCL_matrixMul_kernel | 5122 | 2 | {16 16 1} | 0 | {128 80 1} | 0 | 0 | 140737353975296 | 0x7a3000 | 0 | 7192640 |
+| 6 | 380095252 | 6 | &__Gdt_vectoradd_kernel | 5122 | 1 | {64 1 1} | 0 | {64 1 1} | 0 | 0 | 140737353969664 | 0x7a3000 | 0 | 7940224 |
+| 7 | 380095252 | 7 | &__OpenCL_matrixMul_kernel | 5122 | 2 | {16 16 1} | 0 | {128 80 1} | 0 | 0 | 140737353971200 | 0x697000 | 0 | 7765760 |
+| 8 | 380095252 | 8 | &__Gdt_vectoradd_kernel | 5122 | 1 | {64 1 1} | 0 | {64 1 1} | 0 | 0 | 140737353965568 | 0x70f000 | 0 | 6968192 |
+| 9 | 380095252 | 9 | &__OpenCL_matrixMul_kernel | 5122 | 2 | {16 16 1} | 0 | {128 80 1} | 0 | 0 | 140737353967104 | 0x708000 | 0 | 7081216 |
+
+
+
+### How do I compile GPU kernels for debug?
+To debug GPU kernels that target ROCm, you need to compile the kernels for debug and embed the HSAIL kernel source in the resulting code object. Debug flags can be passed to high level compiler and the finalizer using environment variables. To simplify this process, the `rocm-gdb-debug-flags.sh` script is included in the `/opt/rocm/gpudebugsdk/bin` directory.
+
+It should be noted that the `rocm-gdb-debug-flags.sh` should be called as `source rocm-gdb-debug-flags.sh` and not executed as `./rocm-gdb-debug-flags.sh` since the script sets environment variables and the variables need to be visible for the subsequent build commands.
+
+* For HCC-HSAIL based applications, you can call `source rocm-gdb-debug-flags.sh` before compiling the application or include the environment variables in the script as part of your application's build.
+* For applications using libHSAIL to compile their GPU kernels `source rocm-gdb-debug-flags.sh` should be called when the application is compiled.
+* For SNACK applications, you can call `source rocm-gdb-debug-flags.sh` before calling the buildrun.sh script for the SNACK applications.
+
+Once the application has been built using the environment variables specified in `rocm-gdb-debug-flags.sh`, you can debug HCC-HSAIL / SNACK / libHSAIL applications as described in this tutorial.
+
+
+### Generating logs for reporting issues in rocm-gdb
+Additional log files can be generated by rocm-gdb. These log files should be sent to the rocm-gdb developers to allow them to diagnose issues.
+Logging is enabled with the `ROCM_GDB_ENABLE_LOG` environment variable as shown below
+
+```
+export ROCM_GDB_ENABLE_LOG='DebugLogs'
+rocm-gdb MatrixMul
+```
+
+The environment variable enables logging and provides a prefix for the log file names.
+As the `MatrixMul` application executes, log files with the prefix `DebugLogs_` will be generated.
+The log files generated include logs from GDB, the HSA Debug Agent and the HSA code objects used in the applications. Each debug session's log file's name will include a unique `SessionID`.
+
+
+### Others
+A useful tutorial on how to use GDB can be found on [RMS's site](http://www.unknownroad.com/rtfm/gdbtut/).
diff --git a/gdb/LICENSE.txt b/gdb/LICENSE.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/gdb/LICENSE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/gdb/bin/x86_64/.gdbinit b/gdb/bin/x86_64/.gdbinit
new file mode 100644
index 0000000..4f5ee90
--- /dev/null
+++ b/gdb/bin/x86_64/.gdbinit
@@ -0,0 +1,42 @@
+# Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+
+# Enable this when debugging a gdb
+
+add-auto-load-safe-path /
+
+
+define ROCmConfigure
+# Enable logging, the file will be deleted by the high level script
+# if logging isnt desired as per the env variable
+set logging on
+
+#give a warning of the evil that has been done
+echo ROCm Configure Steps Done\n
+echo ....Certain GDB signals have been changed\n
+
+set pagination off
+handle SIGUSR1 nostop pass noprint
+set mi-async on
+end
+
+document ROCmConfigure
+This command configures GDB internals for debugging ROCm kernels
+end
+
+define ROCmReset
+
+echo Undoing ROCm configuration steps\n
+echo ROCm applications will not work anymore\n
+
+handle SIGCHLD nostop pass noprint
+handle SIGUSR1 stop pass print
+set pagination on
+set mi-async off
+end
+
+ROCmConfigure
+
+# Enable this to save the last gdb session's commands into ./gdb_history.
+#shell rm ./gdb_history
+#set history filename ./gdb_history
+#set history save
diff --git a/gdb/bin/x86_64/amd-gdb b/gdb/bin/x86_64/amd-gdb
new file mode 100755
index 0000000..a5b2016
Binary files /dev/null and b/gdb/bin/x86_64/amd-gdb differ
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/FrameDecorator.py b/gdb/bin/x86_64/data-directory/python/gdb/FrameDecorator.py
new file mode 100644
index 0000000..d6bfa1e
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/FrameDecorator.py
@@ -0,0 +1,302 @@
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb
+
+# This small code snippet deals with problem of strings in Python 2.x
+# and Python 3.x. Python 2.x has str and unicode classes which are
+# sub-classes of basestring. In Python 3.x all strings are encoded
+# and basestring has been removed.
+try:
+ basestring
+except NameError:
+ basestring = str
+
+class FrameDecorator(object):
+ """Basic implementation of a Frame Decorator"""
+
+ """ This base frame decorator decorates a frame or another frame
+ decorator, and provides convenience methods. If this object is
+ wrapping a frame decorator, defer to that wrapped object's method
+ if it has one. This allows for frame decorators that have
+ sub-classed FrameDecorator object, but also wrap other frame
+ decorators on the same frame to correctly execute.
+
+ E.g
+
+ If the result of frame filters running means we have one gdb.Frame
+ wrapped by multiple frame decorators, all sub-classed from
+ FrameDecorator, the resulting hierarchy will be:
+
+ Decorator1
+ -- (wraps) Decorator2
+ -- (wraps) FrameDecorator
+ -- (wraps) gdb.Frame
+
+ In this case we have two frame decorators, both of which are
+ sub-classed from FrameDecorator. If Decorator1 just overrides the
+ 'function' method, then all of the other methods are carried out
+ by the super-class FrameDecorator. But Decorator2 may have
+ overriden other methods, so FrameDecorator will look at the
+ 'base' parameter and defer to that class's methods. And so on,
+ down the chain."""
+
+ # 'base' can refer to a gdb.Frame or another frame decorator. In
+ # the latter case, the child class will have called the super
+ # method and _base will be an object conforming to the Frame Filter
+ # class.
+ def __init__(self, base):
+ self._base = base
+
+ @staticmethod
+ def _is_limited_frame(frame):
+ """Internal utility to determine if the frame is special or
+ limited."""
+ sal = frame.find_sal()
+
+ if (not sal.symtab or not sal.symtab.filename
+ or frame.type() == gdb.DUMMY_FRAME
+ or frame.type() == gdb.SIGTRAMP_FRAME):
+
+ return True
+
+ return False
+
+ def elided(self):
+ """Return any elided frames that this class might be
+ wrapping, or None."""
+ if hasattr(self._base, "elided"):
+ return self._base.elided()
+
+ return None
+
+ def function(self):
+ """ Return the name of the frame's function or an address of
+ the function of the frame. First determine if this is a
+ special frame. If not, try to determine filename from GDB's
+ frame internal function API. Finally, if a name cannot be
+ determined return the address. If this function returns an
+ address, GDB will attempt to determine the function name from
+ its internal minimal symbols store (for example, for inferiors
+ without debug-info)."""
+
+ # Both gdb.Frame, and FrameDecorator have a method called
+ # "function", so determine which object this is.
+ if not isinstance(self._base, gdb.Frame):
+ if hasattr(self._base, "function"):
+ # If it is not a gdb.Frame, and there is already a
+ # "function" method, use that.
+ return self._base.function()
+
+ frame = self.inferior_frame()
+
+ if frame.type() == gdb.DUMMY_FRAME:
+ return ""
+ elif frame.type() == gdb.SIGTRAMP_FRAME:
+ return ""
+
+ func = frame.function()
+
+ # If we cannot determine the function name, return the
+ # address. If GDB detects an integer value from this function
+ # it will attempt to find the function name from minimal
+ # symbols via its own internal functions.
+ if func == None:
+ pc = frame.pc()
+ return pc
+
+ return str(func)
+
+ def address(self):
+ """ Return the address of the frame's pc"""
+
+ if hasattr(self._base, "address"):
+ return self._base.address()
+
+ frame = self.inferior_frame()
+ return frame.pc()
+
+ def filename(self):
+ """ Return the filename associated with this frame, detecting
+ and returning the appropriate library name is this is a shared
+ library."""
+
+ if hasattr(self._base, "filename"):
+ return self._base.filename()
+
+ frame = self.inferior_frame()
+ sal = frame.find_sal()
+ if not sal.symtab or not sal.symtab.filename:
+ pc = frame.pc()
+ return gdb.solib_name(pc)
+ else:
+ return sal.symtab.filename
+
+ def frame_args(self):
+ """ Return an iterable of frame arguments for this frame, if
+ any. The iterable object contains objects conforming with the
+ Symbol/Value interface. If there are no frame arguments, or
+ if this frame is deemed to be a special case, return None."""
+
+ if hasattr(self._base, "frame_args"):
+ return self._base.frame_args()
+
+ frame = self.inferior_frame()
+ if self._is_limited_frame(frame):
+ return None
+
+ args = FrameVars(frame)
+ return args.fetch_frame_args()
+
+ def frame_locals(self):
+ """ Return an iterable of local variables for this frame, if
+ any. The iterable object contains objects conforming with the
+ Symbol/Value interface. If there are no frame locals, or if
+ this frame is deemed to be a special case, return None."""
+
+ if hasattr(self._base, "frame_locals"):
+ return self._base.frame_locals()
+
+ frame = self.inferior_frame()
+ if self._is_limited_frame(frame):
+ return None
+
+ args = FrameVars(frame)
+ return args.fetch_frame_locals()
+
+ def line(self):
+ """ Return line number information associated with the frame's
+ pc. If symbol table/line information does not exist, or if
+ this frame is deemed to be a special case, return None"""
+
+ if hasattr(self._base, "line"):
+ return self._base.line()
+
+ frame = self.inferior_frame()
+ if self._is_limited_frame(frame):
+ return None
+
+ sal = frame.find_sal()
+ if (sal):
+ return sal.line
+ else:
+ return None
+
+ def inferior_frame(self):
+ """ Return the gdb.Frame underpinning this frame decorator."""
+
+ # If 'base' is a frame decorator, we want to call its inferior
+ # frame method. If '_base' is a gdb.Frame, just return that.
+ if hasattr(self._base, "inferior_frame"):
+ return self._base.inferior_frame()
+ return self._base
+
+class SymValueWrapper(object):
+ """A container class conforming to the Symbol/Value interface
+ which holds frame locals or frame arguments."""
+ def __init__(self, symbol, value):
+ self.sym = symbol
+ self.val = value
+
+ def value(self):
+ """ Return the value associated with this symbol, or None"""
+ return self.val
+
+ def symbol(self):
+ """ Return the symbol, or Python text, associated with this
+ symbol, or None"""
+ return self.sym
+
+class FrameVars(object):
+
+ """Utility class to fetch and store frame local variables, or
+ frame arguments."""
+
+ def __init__(self, frame):
+ self.frame = frame
+ self.symbol_class = {
+ gdb.SYMBOL_LOC_STATIC: True,
+ gdb.SYMBOL_LOC_REGISTER: True,
+ gdb.SYMBOL_LOC_ARG: True,
+ gdb.SYMBOL_LOC_REF_ARG: True,
+ gdb.SYMBOL_LOC_LOCAL: True,
+ gdb.SYMBOL_LOC_REGPARM_ADDR: True,
+ gdb.SYMBOL_LOC_COMPUTED: True
+ }
+
+ def fetch_b(self, sym):
+ """ Local utility method to determine if according to Symbol
+ type whether it should be included in the iterator. Not all
+ symbols are fetched, and only symbols that return
+ True from this method should be fetched."""
+
+ # SYM may be a string instead of a symbol in the case of
+ # synthetic local arguments or locals. If that is the case,
+ # always fetch.
+ if isinstance(sym, basestring):
+ return True
+
+ sym_type = sym.addr_class
+
+ return self.symbol_class.get(sym_type, False)
+
+ def fetch_frame_locals(self):
+ """Public utility method to fetch frame local variables for
+ the stored frame. Frame arguments are not fetched. If there
+ are no frame local variables, return an empty list."""
+ lvars = []
+
+ try:
+ block = self.frame.block()
+ except RuntimeError:
+ block = None
+
+ while block != None:
+ if block.is_global or block.is_static:
+ break
+ for sym in block:
+ if sym.is_argument:
+ continue;
+ if self.fetch_b(sym):
+ lvars.append(SymValueWrapper(sym, None))
+
+ block = block.superblock
+
+ return lvars
+
+ def fetch_frame_args(self):
+ """Public utility method to fetch frame arguments for the
+ stored frame. Frame arguments are the only type fetched. If
+ there are no frame argument variables, return an empty list."""
+
+ args = []
+
+ try:
+ block = self.frame.block()
+ except RuntimeError:
+ block = None
+
+ while block != None:
+ if block.function != None:
+ break
+ block = block.superblock
+
+ if block != None:
+ for sym in block:
+ if not sym.is_argument:
+ continue;
+ args.append(SymValueWrapper(sym, None))
+
+ return args
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/FrameIterator.py b/gdb/bin/x86_64/data-directory/python/gdb/FrameIterator.py
new file mode 100644
index 0000000..70dfaf3
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/FrameIterator.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb
+import itertools
+
+class FrameIterator(object):
+ """A gdb.Frame iterator. Iterates over gdb.Frames or objects that
+ conform to that interface."""
+
+ def __init__(self, frame_obj):
+ """Initialize a FrameIterator.
+
+ Arguments:
+ frame_obj the starting frame."""
+
+ super(FrameIterator, self).__init__()
+ self.frame = frame_obj
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """next implementation.
+
+ Returns:
+ The next oldest frame."""
+
+ result = self.frame
+ if result is None:
+ raise StopIteration
+ self.frame = result.older()
+ return result
+
+ # Python 3.x requires __next__(self) while Python 2.x requires
+ # next(self). Define next(self), and for Python 3.x create this
+ # wrapper.
+ def __next__(self):
+ return self.next()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/__init__.py b/gdb/bin/x86_64/data-directory/python/gdb/__init__.py
new file mode 100644
index 0000000..5205cc9
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/__init__.py
@@ -0,0 +1,165 @@
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import traceback
+import os
+import sys
+import _gdb
+
+if sys.version_info[0] > 2:
+ # Python 3 moved "reload"
+ from imp import reload
+
+from _gdb import *
+
+class _GdbFile (object):
+ # These two are needed in Python 3
+ encoding = "UTF-8"
+ errors = "strict"
+
+ def close(self):
+ # Do nothing.
+ return None
+
+ def isatty(self):
+ return False
+
+ def writelines(self, iterable):
+ for line in iterable:
+ self.write(line)
+
+ def flush(self):
+ flush()
+
+class GdbOutputFile (_GdbFile):
+ def write(self, s):
+ write(s, stream=STDOUT)
+
+sys.stdout = GdbOutputFile()
+
+class GdbOutputErrorFile (_GdbFile):
+ def write(self, s):
+ write(s, stream=STDERR)
+
+sys.stderr = GdbOutputErrorFile()
+
+# Default prompt hook does nothing.
+prompt_hook = None
+
+# Ensure that sys.argv is set to something.
+# We do not use PySys_SetArgvEx because it did not appear until 2.6.6.
+sys.argv = ['']
+
+# Initial pretty printers.
+pretty_printers = []
+
+# Initial type printers.
+type_printers = []
+# Initial xmethod matchers.
+xmethods = []
+# Initial frame filters.
+frame_filters = {}
+# Initial frame unwinders.
+frame_unwinders = []
+
+def execute_unwinders(pending_frame):
+ """Internal function called from GDB to execute all unwinders.
+
+ Runs each currently enabled unwinder until it finds the one that
+ can unwind given frame.
+
+ Arguments:
+ pending_frame: gdb.PendingFrame instance.
+ Returns:
+ gdb.UnwindInfo instance or None.
+ """
+ for objfile in _gdb.objfiles():
+ for unwinder in objfile.frame_unwinders:
+ if unwinder.enabled:
+ unwind_info = unwinder(pending_frame)
+ if unwind_info is not None:
+ return unwind_info
+
+ current_progspace = _gdb.current_progspace()
+ for unwinder in current_progspace.frame_unwinders:
+ if unwinder.enabled:
+ unwind_info = unwinder(pending_frame)
+ if unwind_info is not None:
+ return unwind_info
+
+ for unwinder in frame_unwinders:
+ if unwinder.enabled:
+ unwind_info = unwinder(pending_frame)
+ if unwind_info is not None:
+ return unwind_info
+
+ return None
+
+
+# Convenience variable to GDB's python directory
+PYTHONDIR = os.path.dirname(os.path.dirname(__file__))
+
+# Auto-load all functions/commands.
+
+# Packages to auto-load.
+
+packages = [
+ 'function',
+ 'command',
+ 'printer'
+]
+
+# pkgutil.iter_modules is not available prior to Python 2.6. Instead,
+# manually iterate the list, collating the Python files in each module
+# path. Construct the module name, and import.
+
+def auto_load_packages():
+ for package in packages:
+ location = os.path.join(os.path.dirname(__file__), package)
+ if os.path.exists(location):
+ py_files = filter(lambda x: x.endswith('.py')
+ and x != '__init__.py',
+ os.listdir(location))
+
+ for py_file in py_files:
+ # Construct from foo.py, gdb.module.foo
+ modname = "%s.%s.%s" % ( __name__, package, py_file[:-3] )
+ try:
+ if modname in sys.modules:
+ # reload modules with duplicate names
+ reload(__import__(modname))
+ else:
+ __import__(modname)
+ except:
+ sys.stderr.write (traceback.format_exc() + "\n")
+
+auto_load_packages()
+
+def GdbSetPythonDirectory(dir):
+ """Update sys.path, reload gdb and auto-load packages."""
+ global PYTHONDIR
+
+ try:
+ sys.path.remove(PYTHONDIR)
+ except ValueError:
+ pass
+ sys.path.insert(0, dir)
+
+ PYTHONDIR = dir
+
+ # note that reload overwrites the gdb module without deleting existing
+ # attributes
+ reload(__import__(__name__))
+ auto_load_packages()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/__init__.py b/gdb/bin/x86_64/data-directory/python/gdb/command/__init__.py
new file mode 100644
index 0000000..8433d50
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/__init__.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/explore.py b/gdb/bin/x86_64/data-directory/python/gdb/command/explore.py
new file mode 100644
index 0000000..6c9f17b
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/explore.py
@@ -0,0 +1,760 @@
+# GDB 'explore' command.
+# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Implementation of the GDB 'explore' command using the GDB Python API."""
+
+import gdb
+import sys
+
+if sys.version_info[0] > 2:
+ # Python 3 renamed raw_input to input
+ raw_input = input
+
+class Explorer(object):
+ """Internal class which invokes other explorers."""
+
+ # This map is filled by the Explorer.init_env() function
+ type_code_to_explorer_map = { }
+
+ _SCALAR_TYPE_LIST = (
+ gdb.TYPE_CODE_CHAR,
+ gdb.TYPE_CODE_INT,
+ gdb.TYPE_CODE_BOOL,
+ gdb.TYPE_CODE_FLT,
+ gdb.TYPE_CODE_VOID,
+ gdb.TYPE_CODE_ENUM,
+ )
+
+ @staticmethod
+ def guard_expr(expr):
+ length = len(expr)
+ guard = False
+
+ if expr[0] == '(' and expr[length-1] == ')':
+ pass
+ else:
+ i = 0
+ while i < length:
+ c = expr[i]
+ if (c == '_' or ('a' <= c and c <= 'z') or
+ ('A' <= c and c <= 'Z') or ('0' <= c and c <= '9')):
+ pass
+ else:
+ guard = True
+ break
+ i += 1
+
+ if guard:
+ return "(" + expr + ")"
+ else:
+ return expr
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Main function to explore an expression value.
+
+ Arguments:
+ expr: The expression string that is being explored.
+ value: The gdb.Value value of the expression.
+ is_child: Boolean value to indicate if the expression is a child.
+ An expression is a child if it is derived from the main
+ expression entered by the user. For example, if the user
+ entered an expression which evaluates to a struct, then
+ when exploring the fields of the struct, is_child is set
+ to True internally.
+
+ Returns:
+ No return value.
+ """
+ type_code = value.type.code
+ if type_code in Explorer.type_code_to_explorer_map:
+ explorer_class = Explorer.type_code_to_explorer_map[type_code]
+ while explorer_class.explore_expr(expr, value, is_child):
+ pass
+ else:
+ print ("Explorer for type '%s' not yet available.\n" %
+ str(value.type))
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Main function to explore a data type.
+
+ Arguments:
+ name: The string representing the path to the data type being
+ explored.
+ datatype: The gdb.Type value of the data type being explored.
+ is_child: Boolean value to indicate if the name is a child.
+ A name is a child if it is derived from the main name
+ entered by the user. For example, if the user entered
+ the name of struct type, then when exploring the fields
+ of the struct, is_child is set to True internally.
+
+ Returns:
+ No return value.
+ """
+ type_code = datatype.code
+ if type_code in Explorer.type_code_to_explorer_map:
+ explorer_class = Explorer.type_code_to_explorer_map[type_code]
+ while explorer_class.explore_type(name, datatype, is_child):
+ pass
+ else:
+ print ("Explorer for type '%s' not yet available.\n" %
+ str(datatype))
+
+ @staticmethod
+ def init_env():
+ """Initializes the Explorer environment.
+ This function should be invoked before starting any exploration. If
+ invoked before an exploration, it need not be invoked for subsequent
+ explorations.
+ """
+ Explorer.type_code_to_explorer_map = {
+ gdb.TYPE_CODE_CHAR : ScalarExplorer,
+ gdb.TYPE_CODE_INT : ScalarExplorer,
+ gdb.TYPE_CODE_BOOL : ScalarExplorer,
+ gdb.TYPE_CODE_FLT : ScalarExplorer,
+ gdb.TYPE_CODE_VOID : ScalarExplorer,
+ gdb.TYPE_CODE_ENUM : ScalarExplorer,
+ gdb.TYPE_CODE_STRUCT : CompoundExplorer,
+ gdb.TYPE_CODE_UNION : CompoundExplorer,
+ gdb.TYPE_CODE_PTR : PointerExplorer,
+ gdb.TYPE_CODE_REF : ReferenceExplorer,
+ gdb.TYPE_CODE_TYPEDEF : TypedefExplorer,
+ gdb.TYPE_CODE_ARRAY : ArrayExplorer
+ }
+
+ @staticmethod
+ def is_scalar_type(type):
+ """Checks whether a type is a scalar type.
+ A type is a scalar type of its type is
+ gdb.TYPE_CODE_CHAR or
+ gdb.TYPE_CODE_INT or
+ gdb.TYPE_CODE_BOOL or
+ gdb.TYPE_CODE_FLT or
+ gdb.TYPE_CODE_VOID or
+ gdb.TYPE_CODE_ENUM.
+
+ Arguments:
+ type: The type to be checked.
+
+ Returns:
+ 'True' if 'type' is a scalar type. 'False' otherwise.
+ """
+ return type.code in Explorer._SCALAR_TYPE_LIST
+
+ @staticmethod
+ def return_to_parent_value():
+ """A utility function which prints that the current exploration session
+ is returning to the parent value. Useful when exploring values.
+ """
+ print ("\nReturning to parent value...\n")
+
+ @staticmethod
+ def return_to_parent_value_prompt():
+ """A utility function which prompts the user to press the 'enter' key
+ so that the exploration session can shift back to the parent value.
+ Useful when exploring values.
+ """
+ raw_input("\nPress enter to return to parent value: ")
+
+ @staticmethod
+ def return_to_enclosing_type():
+ """A utility function which prints that the current exploration session
+ is returning to the enclosing type. Useful when exploring types.
+ """
+ print ("\nReturning to enclosing type...\n")
+
+ @staticmethod
+ def return_to_enclosing_type_prompt():
+ """A utility function which prompts the user to press the 'enter' key
+ so that the exploration session can shift back to the enclosing type.
+ Useful when exploring types.
+ """
+ raw_input("\nPress enter to return to enclosing type: ")
+
+
+class ScalarExplorer(object):
+ """Internal class used to explore scalar values."""
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore scalar values.
+ See Explorer.explore_expr and Explorer.is_scalar_type for more
+ information.
+ """
+ print ("'%s' is a scalar value of type '%s'." %
+ (expr, value.type))
+ print ("%s = %s" % (expr, str(value)))
+
+ if is_child:
+ Explorer.return_to_parent_value_prompt()
+ Explorer.return_to_parent_value()
+
+ return False
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore scalar types.
+ See Explorer.explore_type and Explorer.is_scalar_type for more
+ information.
+ """
+ if datatype.code == gdb.TYPE_CODE_ENUM:
+ if is_child:
+ print ("%s is of an enumerated type '%s'." %
+ (name, str(datatype)))
+ else:
+ print ("'%s' is an enumerated type." % name)
+ else:
+ if is_child:
+ print ("%s is of a scalar type '%s'." %
+ (name, str(datatype)))
+ else:
+ print ("'%s' is a scalar type." % name)
+
+ if is_child:
+ Explorer.return_to_enclosing_type_prompt()
+ Explorer.return_to_enclosing_type()
+
+ return False
+
+
+class PointerExplorer(object):
+ """Internal class used to explore pointer values."""
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore pointer values.
+ See Explorer.explore_expr for more information.
+ """
+ print ("'%s' is a pointer to a value of type '%s'" %
+ (expr, str(value.type.target())))
+ option = raw_input("Continue exploring it as a pointer to a single "
+ "value [y/n]: ")
+ if option == "y":
+ deref_value = None
+ try:
+ deref_value = value.dereference()
+ str(deref_value)
+ except gdb.MemoryError:
+ print ("'%s' a pointer pointing to an invalid memory "
+ "location." % expr)
+ if is_child:
+ Explorer.return_to_parent_value_prompt()
+ return False
+ Explorer.explore_expr("*%s" % Explorer.guard_expr(expr),
+ deref_value, is_child)
+ return False
+
+ option = raw_input("Continue exploring it as a pointer to an "
+ "array [y/n]: ")
+ if option == "y":
+ while True:
+ index = 0
+ try:
+ index = int(raw_input("Enter the index of the element you "
+ "want to explore in '%s': " % expr))
+ except ValueError:
+ break
+ element_expr = "%s[%d]" % (Explorer.guard_expr(expr), index)
+ element = value[index]
+ try:
+ str(element)
+ except gdb.MemoryError:
+ print ("Cannot read value at index %d." % index)
+ continue
+ Explorer.explore_expr(element_expr, element, True)
+ return False
+
+ if is_child:
+ Explorer.return_to_parent_value()
+ return False
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore pointer types.
+ See Explorer.explore_type for more information.
+ """
+ target_type = datatype.target()
+ print ("\n%s is a pointer to a value of type '%s'." %
+ (name, str(target_type)))
+
+ Explorer.explore_type("the pointee type of %s" % name,
+ target_type,
+ is_child)
+ return False
+
+
+class ReferenceExplorer(object):
+ """Internal class used to explore reference (TYPE_CODE_REF) values."""
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore array values.
+ See Explorer.explore_expr for more information.
+ """
+ referenced_value = value.referenced_value()
+ Explorer.explore_expr(expr, referenced_value, is_child)
+ return False
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore pointer types.
+ See Explorer.explore_type for more information.
+ """
+ target_type = datatype.target()
+ Explorer.explore_type(name, target_type, is_child)
+ return False
+
+
+class ArrayExplorer(object):
+ """Internal class used to explore arrays."""
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore array values.
+ See Explorer.explore_expr for more information.
+ """
+ target_type = value.type.target()
+ print ("'%s' is an array of '%s'." % (expr, str(target_type)))
+ index = 0
+ try:
+ index = int(raw_input("Enter the index of the element you want to "
+ "explore in '%s': " % expr))
+ except ValueError:
+ if is_child:
+ Explorer.return_to_parent_value()
+ return False
+
+ element = None
+ try:
+ element = value[index]
+ str(element)
+ except gdb.MemoryError:
+ print ("Cannot read value at index %d." % index)
+ raw_input("Press enter to continue... ")
+ return True
+
+ Explorer.explore_expr("%s[%d]" % (Explorer.guard_expr(expr), index),
+ element, True)
+ return True
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore array types.
+ See Explorer.explore_type for more information.
+ """
+ target_type = datatype.target()
+ print ("%s is an array of '%s'." % (name, str(target_type)))
+
+ Explorer.explore_type("the array element of %s" % name, target_type,
+ is_child)
+ return False
+
+
+class CompoundExplorer(object):
+ """Internal class used to explore struct, classes and unions."""
+
+ @staticmethod
+ def _print_fields(print_list):
+ """Internal function which prints the fields of a struct/class/union.
+ """
+ max_field_name_length = 0
+ for pair in print_list:
+ if max_field_name_length < len(pair[0]):
+ max_field_name_length = len(pair[0])
+
+ for pair in print_list:
+ print (" %*s = %s" % (max_field_name_length, pair[0], pair[1]))
+
+ @staticmethod
+ def _get_real_field_count(fields):
+ real_field_count = 0;
+ for field in fields:
+ if not field.artificial:
+ real_field_count = real_field_count + 1
+
+ return real_field_count
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore structs/classes and union values.
+ See Explorer.explore_expr for more information.
+ """
+ datatype = value.type
+ type_code = datatype.code
+ fields = datatype.fields()
+
+ if type_code == gdb.TYPE_CODE_STRUCT:
+ type_desc = "struct/class"
+ else:
+ type_desc = "union"
+
+ if CompoundExplorer._get_real_field_count(fields) == 0:
+ print ("The value of '%s' is a %s of type '%s' with no fields." %
+ (expr, type_desc, str(value.type)))
+ if is_child:
+ Explorer.return_to_parent_value_prompt()
+ return False
+
+ print ("The value of '%s' is a %s of type '%s' with the following "
+ "fields:\n" % (expr, type_desc, str(value.type)))
+
+ has_explorable_fields = False
+ choice_to_compound_field_map = { }
+ current_choice = 0
+ print_list = [ ]
+ for field in fields:
+ if field.artificial:
+ continue
+ field_full_name = Explorer.guard_expr(expr) + "." + field.name
+ if field.is_base_class:
+ field_value = value.cast(field.type)
+ else:
+ field_value = value[field.name]
+ literal_value = ""
+ if type_code == gdb.TYPE_CODE_UNION:
+ literal_value = ("" % (current_choice, str(field.type)))
+ has_explorable_fields = True
+ else:
+ if Explorer.is_scalar_type(field.type):
+ literal_value = ("%s .. (Value of type '%s')" %
+ (str(field_value), str(field.type)))
+ else:
+ if field.is_base_class:
+ field_desc = "base class"
+ else:
+ field_desc = "field"
+ literal_value = ("" %
+ (current_choice, field_desc,
+ str(field.type)))
+ has_explorable_fields = True
+
+ choice_to_compound_field_map[str(current_choice)] = (
+ field_full_name, field_value)
+ current_choice = current_choice + 1
+
+ print_list.append((field.name, literal_value))
+
+ CompoundExplorer._print_fields(print_list)
+ print ("")
+
+ if has_explorable_fields:
+ choice = raw_input("Enter the field number of choice: ")
+ if choice in choice_to_compound_field_map:
+ Explorer.explore_expr(choice_to_compound_field_map[choice][0],
+ choice_to_compound_field_map[choice][1],
+ True)
+ return True
+ else:
+ if is_child:
+ Explorer.return_to_parent_value()
+ else:
+ if is_child:
+ Explorer.return_to_parent_value_prompt()
+
+ return False
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore struct/class and union types.
+ See Explorer.explore_type for more information.
+ """
+ type_code = datatype.code
+ type_desc = ""
+ if type_code == gdb.TYPE_CODE_STRUCT:
+ type_desc = "struct/class"
+ else:
+ type_desc = "union"
+
+ fields = datatype.fields()
+ if CompoundExplorer._get_real_field_count(fields) == 0:
+ if is_child:
+ print ("%s is a %s of type '%s' with no fields." %
+ (name, type_desc, str(datatype)))
+ Explorer.return_to_enclosing_type_prompt()
+ else:
+ print ("'%s' is a %s with no fields." % (name, type_desc))
+ return False
+
+ if is_child:
+ print ("%s is a %s of type '%s' "
+ "with the following fields:\n" %
+ (name, type_desc, str(datatype)))
+ else:
+ print ("'%s' is a %s with the following "
+ "fields:\n" %
+ (name, type_desc))
+
+ has_explorable_fields = False
+ current_choice = 0
+ choice_to_compound_field_map = { }
+ print_list = [ ]
+ for field in fields:
+ if field.artificial:
+ continue
+ if field.is_base_class:
+ field_desc = "base class"
+ else:
+ field_desc = "field"
+ rhs = ("" %
+ (current_choice, field_desc, str(field.type)))
+ print_list.append((field.name, rhs))
+ choice_to_compound_field_map[str(current_choice)] = (
+ field.name, field.type, field_desc)
+ current_choice = current_choice + 1
+
+ CompoundExplorer._print_fields(print_list)
+ print ("")
+
+ if len(choice_to_compound_field_map) > 0:
+ choice = raw_input("Enter the field number of choice: ")
+ if choice in choice_to_compound_field_map:
+ if is_child:
+ new_name = ("%s '%s' of %s" %
+ (choice_to_compound_field_map[choice][2],
+ choice_to_compound_field_map[choice][0],
+ name))
+ else:
+ new_name = ("%s '%s' of '%s'" %
+ (choice_to_compound_field_map[choice][2],
+ choice_to_compound_field_map[choice][0],
+ name))
+ Explorer.explore_type(new_name,
+ choice_to_compound_field_map[choice][1], True)
+ return True
+ else:
+ if is_child:
+ Explorer.return_to_enclosing_type()
+ else:
+ if is_child:
+ Explorer.return_to_enclosing_type_prompt()
+
+ return False
+
+
+class TypedefExplorer(object):
+ """Internal class used to explore values whose type is a typedef."""
+
+ @staticmethod
+ def explore_expr(expr, value, is_child):
+ """Function to explore typedef values.
+ See Explorer.explore_expr for more information.
+ """
+ actual_type = value.type.strip_typedefs()
+ print ("The value of '%s' is of type '%s' "
+ "which is a typedef of type '%s'" %
+ (expr, str(value.type), str(actual_type)))
+
+ Explorer.explore_expr(expr, value.cast(actual_type), is_child)
+ return False
+
+ @staticmethod
+ def explore_type(name, datatype, is_child):
+ """Function to explore typedef types.
+ See Explorer.explore_type for more information.
+ """
+ actual_type = datatype.strip_typedefs()
+ if is_child:
+ print ("The type of %s is a typedef of type '%s'." %
+ (name, str(actual_type)))
+ else:
+ print ("The type '%s' is a typedef of type '%s'." %
+ (name, str(actual_type)))
+
+ Explorer.explore_type(name, actual_type, is_child)
+ return False
+
+
+class ExploreUtils(object):
+ """Internal class which provides utilities for the main command classes."""
+
+ @staticmethod
+ def check_args(name, arg_str):
+ """Utility to check if adequate number of arguments are passed to an
+ explore command.
+
+ Arguments:
+ name: The name of the explore command.
+ arg_str: The argument string passed to the explore command.
+
+ Returns:
+ True if adequate arguments are passed, false otherwise.
+
+ Raises:
+ gdb.GdbError if adequate arguments are not passed.
+ """
+ if len(arg_str) < 1:
+ raise gdb.GdbError("ERROR: '%s' requires an argument."
+ % name)
+ return False
+ else:
+ return True
+
+ @staticmethod
+ def get_type_from_str(type_str):
+ """A utility function to deduce the gdb.Type value from a string
+ representing the type.
+
+ Arguments:
+ type_str: The type string from which the gdb.Type value should be
+ deduced.
+
+ Returns:
+ The deduced gdb.Type value if possible, None otherwise.
+ """
+ try:
+ # Assume the current language to be C/C++ and make a try.
+ return gdb.parse_and_eval("(%s *)0" % type_str).type.target()
+ except RuntimeError:
+ # If assumption of current language to be C/C++ was wrong, then
+ # lookup the type using the API.
+ try:
+ return gdb.lookup_type(type_str)
+ except RuntimeError:
+ return None
+
+ @staticmethod
+ def get_value_from_str(value_str):
+ """A utility function to deduce the gdb.Value value from a string
+ representing the value.
+
+ Arguments:
+ value_str: The value string from which the gdb.Value value should
+ be deduced.
+
+ Returns:
+ The deduced gdb.Value value if possible, None otherwise.
+ """
+ try:
+ return gdb.parse_and_eval(value_str)
+ except RuntimeError:
+ return None
+
+
+class ExploreCommand(gdb.Command):
+ """Explore a value or a type valid in the current context.
+
+ Usage:
+
+ explore ARG
+
+ - ARG is either a valid expression or a type name.
+ - At any stage of exploration, hit the return key (instead of a
+ choice, if any) to return to the enclosing type or value.
+ """
+
+ def __init__(self):
+ super(ExploreCommand, self).__init__(name = "explore",
+ command_class = gdb.COMMAND_DATA,
+ prefix = True)
+
+ def invoke(self, arg_str, from_tty):
+ if ExploreUtils.check_args("explore", arg_str) == False:
+ return
+
+ # Check if it is a value
+ value = ExploreUtils.get_value_from_str(arg_str)
+ if value is not None:
+ Explorer.explore_expr(arg_str, value, False)
+ return
+
+ # If it is not a value, check if it is a type
+ datatype = ExploreUtils.get_type_from_str(arg_str)
+ if datatype is not None:
+ Explorer.explore_type(arg_str, datatype, False)
+ return
+
+ # If it is neither a value nor a type, raise an error.
+ raise gdb.GdbError(
+ ("'%s' neither evaluates to a value nor is a type "
+ "in the current context." %
+ arg_str))
+
+
+class ExploreValueCommand(gdb.Command):
+ """Explore value of an expression valid in the current context.
+
+ Usage:
+
+ explore value ARG
+
+ - ARG is a valid expression.
+ - At any stage of exploration, hit the return key (instead of a
+ choice, if any) to return to the enclosing value.
+ """
+
+ def __init__(self):
+ super(ExploreValueCommand, self).__init__(
+ name = "explore value", command_class = gdb.COMMAND_DATA)
+
+ def invoke(self, arg_str, from_tty):
+ if ExploreUtils.check_args("explore value", arg_str) == False:
+ return
+
+ value = ExploreUtils.get_value_from_str(arg_str)
+ if value is None:
+ raise gdb.GdbError(
+ (" '%s' does not evaluate to a value in the current "
+ "context." %
+ arg_str))
+ return
+
+ Explorer.explore_expr(arg_str, value, False)
+
+
+class ExploreTypeCommand(gdb.Command):
+ """Explore a type or the type of an expression valid in the current
+ context.
+
+ Usage:
+
+ explore type ARG
+
+ - ARG is a valid expression or a type name.
+ - At any stage of exploration, hit the return key (instead of a
+ choice, if any) to return to the enclosing type.
+ """
+
+ def __init__(self):
+ super(ExploreTypeCommand, self).__init__(
+ name = "explore type", command_class = gdb.COMMAND_DATA)
+
+ def invoke(self, arg_str, from_tty):
+ if ExploreUtils.check_args("explore type", arg_str) == False:
+ return
+
+ datatype = ExploreUtils.get_type_from_str(arg_str)
+ if datatype is not None:
+ Explorer.explore_type(arg_str, datatype, False)
+ return
+
+ value = ExploreUtils.get_value_from_str(arg_str)
+ if value is not None:
+ print ("'%s' is of type '%s'." % (arg_str, str(value.type)))
+ Explorer.explore_type(str(value.type), value.type, False)
+ return
+
+ raise gdb.GdbError(("'%s' is not a type or value in the current "
+ "context." % arg_str))
+
+
+Explorer.init_env()
+
+ExploreCommand()
+ExploreValueCommand()
+ExploreTypeCommand()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/frame_filters.py b/gdb/bin/x86_64/data-directory/python/gdb/command/frame_filters.py
new file mode 100644
index 0000000..c9d4f3e
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/frame_filters.py
@@ -0,0 +1,467 @@
+# Frame-filter commands.
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""GDB commands for working with frame-filters."""
+
+import sys
+import gdb
+import copy
+from gdb.FrameIterator import FrameIterator
+from gdb.FrameDecorator import FrameDecorator
+import gdb.frames
+import itertools
+
+# GDB Commands.
+class SetFilterPrefixCmd(gdb.Command):
+ """Prefix command for 'set' frame-filter related operations."""
+
+ def __init__(self):
+ super(SetFilterPrefixCmd, self).__init__("set frame-filter",
+ gdb.COMMAND_OBSCURE,
+ gdb.COMPLETE_NONE, True)
+
+class ShowFilterPrefixCmd(gdb.Command):
+ """Prefix command for 'show' frame-filter related operations."""
+ def __init__(self):
+ super(ShowFilterPrefixCmd, self).__init__("show frame-filter",
+ gdb.COMMAND_OBSCURE,
+ gdb.COMPLETE_NONE, True)
+class InfoFrameFilter(gdb.Command):
+ """List all registered Python frame-filters.
+
+ Usage: info frame-filters
+ """
+
+ def __init__(self):
+ super(InfoFrameFilter, self).__init__("info frame-filter",
+ gdb.COMMAND_DATA)
+ @staticmethod
+ def enabled_string(state):
+ """Return "Yes" if filter is enabled, otherwise "No"."""
+ if state:
+ return "Yes"
+ else:
+ return "No"
+
+ def list_frame_filters(self, frame_filters):
+ """ Internal worker function to list and print frame filters
+ in a dictionary.
+
+ Arguments:
+ frame_filters: The name of the dictionary, as
+ specified by GDB user commands.
+ """
+
+ sorted_frame_filters = sorted(frame_filters.items(),
+ key=lambda i: gdb.frames.get_priority(i[1]),
+ reverse=True)
+
+ if len(sorted_frame_filters) == 0:
+ print(" No frame filters registered.")
+ else:
+ print(" Priority Enabled Name")
+ for frame_filter in sorted_frame_filters:
+ name = frame_filter[0]
+ try:
+ priority = '{:<8}'.format(
+ str(gdb.frames.get_priority(frame_filter[1])))
+ enabled = '{:<7}'.format(
+ self.enabled_string(gdb.frames.get_enabled(frame_filter[1])))
+ except Exception:
+ e = sys.exc_info()[1]
+ print(" Error printing filter '"+name+"': "+str(e))
+ else:
+ print(" %s %s %s" % (priority, enabled, name))
+
+ def print_list(self, title, filter_list, blank_line):
+ print(title)
+ self.list_frame_filters(filter_list)
+ if blank_line:
+ print("")
+
+ def invoke(self, arg, from_tty):
+ self.print_list("global frame-filters:", gdb.frame_filters, True)
+
+ cp = gdb.current_progspace()
+ self.print_list("progspace %s frame-filters:" % cp.filename,
+ cp.frame_filters, True)
+
+ for objfile in gdb.objfiles():
+ self.print_list("objfile %s frame-filters:" % objfile.filename,
+ objfile.frame_filters, False)
+
+# Internal enable/disable functions.
+
+def _enable_parse_arg(cmd_name, arg):
+ """ Internal worker function to take an argument from
+ enable/disable and return a tuple of arguments.
+
+ Arguments:
+ cmd_name: Name of the command invoking this function.
+ args: The argument as a string.
+
+ Returns:
+ A tuple containing the dictionary, and the argument, or just
+ the dictionary in the case of "all".
+ """
+
+ argv = gdb.string_to_argv(arg);
+ argc = len(argv)
+ if argv[0] == "all" and argc > 1:
+ raise gdb.GdbError(cmd_name + ": with 'all' " \
+ "you may not specify a filter.")
+ else:
+ if argv[0] != "all" and argc != 2:
+ raise gdb.GdbError(cmd_name + " takes exactly two arguments.")
+
+ return argv
+
+def _do_enable_frame_filter(command_tuple, flag):
+ """Worker for enabling/disabling frame_filters.
+
+ Arguments:
+ command_type: A tuple with the first element being the
+ frame filter dictionary, and the second being
+ the frame filter name.
+ flag: True for Enable, False for Disable.
+ """
+
+ list_op = command_tuple[0]
+ op_list = gdb.frames.return_list(list_op)
+
+ if list_op == "all":
+ for item in op_list:
+ gdb.frames.set_enabled(item, flag)
+ else:
+ frame_filter = command_tuple[1]
+ try:
+ ff = op_list[frame_filter]
+ except KeyError:
+ msg = "frame-filter '" + str(name) + "' not found."
+ raise gdb.GdbError(msg)
+
+ gdb.frames.set_enabled(ff, flag)
+
+def _complete_frame_filter_list(text, word, all_flag):
+ """Worker for frame filter dictionary name completion.
+
+ Arguments:
+ text: The full text of the command line.
+ word: The most recent word of the command line.
+ all_flag: Whether to include the word "all" in completion.
+
+ Returns:
+ A list of suggested frame filter dictionary name completions
+ from text/word analysis. This list can be empty when there
+ are no suggestions for completion.
+ """
+ if all_flag == True:
+ filter_locations = ["all", "global", "progspace"]
+ else:
+ filter_locations = ["global", "progspace"]
+ for objfile in gdb.objfiles():
+ filter_locations.append(objfile.filename)
+
+ # If the user just asked for completions with no completion
+ # hints, just return all the frame filter dictionaries we know
+ # about.
+ if (text == ""):
+ return filter_locations
+
+ # Otherwise filter on what we know.
+ flist = filter(lambda x,y=text:x.startswith(y), filter_locations)
+
+ # If we only have one completion, complete it and return it.
+ if len(flist) == 1:
+ flist[0] = flist[0][len(text)-len(word):]
+
+ # Otherwise, return an empty list, or a list of frame filter
+ # dictionaries that the previous filter operation returned.
+ return flist
+
+def _complete_frame_filter_name(word, printer_dict):
+ """Worker for frame filter name completion.
+
+ Arguments:
+
+ word: The most recent word of the command line.
+
+ printer_dict: The frame filter dictionary to search for frame
+ filter name completions.
+
+ Returns: A list of suggested frame filter name completions
+ from word analysis of the frame filter dictionary. This list
+ can be empty when there are no suggestions for completion.
+ """
+
+ printer_keys = printer_dict.keys()
+ if (word == ""):
+ return printer_keys
+
+ flist = filter(lambda x,y=word:x.startswith(y), printer_keys)
+ return flist
+
+class EnableFrameFilter(gdb.Command):
+ """GDB command to disable the specified frame-filter.
+
+ Usage: enable frame-filter enable DICTIONARY [NAME]
+
+ DICTIONARY is the name of the frame filter dictionary on which to
+ operate. If dictionary is set to "all", perform operations on all
+ dictionaries. Named dictionaries are: "global" for the global
+ frame filter dictionary, "progspace" for the program space's frame
+ filter dictionary. If either all, or the two named dictionaries
+ are not specified, the dictionary name is assumed to be the name
+ of the object-file name.
+
+ NAME matches the name of the frame-filter to operate on. If
+ DICTIONARY is "all", NAME is ignored.
+ """
+ def __init__(self):
+ super(EnableFrameFilter, self).__init__("enable frame-filter",
+ gdb.COMMAND_DATA)
+ def complete(self, text, word):
+ """Completion function for both frame filter dictionary, and
+ frame filter name."""
+ if text.count(" ") == 0:
+ return _complete_frame_filter_list(text, word, True)
+ else:
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip())
+ return _complete_frame_filter_name(word, printer_list)
+
+ def invoke(self, arg, from_tty):
+ command_tuple = _enable_parse_arg("enable frame-filter", arg)
+ _do_enable_frame_filter(command_tuple, True)
+
+
+class DisableFrameFilter(gdb.Command):
+ """GDB command to disable the specified frame-filter.
+
+ Usage: disable frame-filter disable DICTIONARY [NAME]
+
+ DICTIONARY is the name of the frame filter dictionary on which to
+ operate. If dictionary is set to "all", perform operations on all
+ dictionaries. Named dictionaries are: "global" for the global
+ frame filter dictionary, "progspace" for the program space's frame
+ filter dictionary. If either all, or the two named dictionaries
+ are not specified, the dictionary name is assumed to be the name
+ of the object-file name.
+
+ NAME matches the name of the frame-filter to operate on. If
+ DICTIONARY is "all", NAME is ignored.
+ """
+ def __init__(self):
+ super(DisableFrameFilter, self).__init__("disable frame-filter",
+ gdb.COMMAND_DATA)
+
+ def complete(self, text, word):
+ """Completion function for both frame filter dictionary, and
+ frame filter name."""
+ if text.count(" ") == 0:
+ return _complete_frame_filter_list(text, word, True)
+ else:
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip())
+ return _complete_frame_filter_name(word, printer_list)
+
+ def invoke(self, arg, from_tty):
+ command_tuple = _enable_parse_arg("disable frame-filter", arg)
+ _do_enable_frame_filter(command_tuple, False)
+
+class SetFrameFilterPriority(gdb.Command):
+ """GDB command to set the priority of the specified frame-filter.
+
+ Usage: set frame-filter priority DICTIONARY NAME PRIORITY
+
+ DICTIONARY is the name of the frame filter dictionary on which to
+ operate. Named dictionaries are: "global" for the global frame
+ filter dictionary, "progspace" for the program space's framefilter
+ dictionary. If either of these two are not specified, the
+ dictionary name is assumed to be the name of the object-file name.
+
+ NAME matches the name of the frame filter to operate on.
+
+ PRIORITY is the an integer to assign the new priority to the frame
+ filter.
+ """
+
+ def __init__(self):
+ super(SetFrameFilterPriority, self).__init__("set frame-filter " \
+ "priority",
+ gdb.COMMAND_DATA)
+
+ def _parse_pri_arg(self, arg):
+ """Internal worker to parse a priority from a tuple.
+
+ Arguments:
+ arg: Tuple which contains the arguments from the command.
+
+ Returns:
+ A tuple containing the dictionary, name and priority from
+ the arguments.
+
+ Raises:
+ gdb.GdbError: An error parsing the arguments.
+ """
+
+ argv = gdb.string_to_argv(arg);
+ argc = len(argv)
+ if argc != 3:
+ print("set frame-filter priority " \
+ "takes exactly three arguments.")
+ return None
+
+ return argv
+
+ def _set_filter_priority(self, command_tuple):
+ """Internal worker for setting priority of frame-filters, by
+ parsing a tuple and calling _set_priority with the parsed
+ tuple.
+
+ Arguments:
+ command_tuple: Tuple which contains the arguments from the
+ command.
+ """
+
+ list_op = command_tuple[0]
+ frame_filter = command_tuple[1]
+
+ # GDB returns arguments as a string, so convert priority to
+ # a number.
+ priority = int(command_tuple[2])
+
+ op_list = gdb.frames.return_list(list_op)
+
+ try:
+ ff = op_list[frame_filter]
+ except KeyError:
+ msg = "frame-filter '" + str(name) + "' not found."
+ raise gdb.GdbError(msg)
+
+ gdb.frames.set_priority(ff, priority)
+
+ def complete(self, text, word):
+ """Completion function for both frame filter dictionary, and
+ frame filter name."""
+ if text.count(" ") == 0:
+ return _complete_frame_filter_list(text, word, False)
+ else:
+ printer_list = gdb.frames.return_list(text.split()[0].rstrip())
+ return _complete_frame_filter_name(word, printer_list)
+
+ def invoke(self, arg, from_tty):
+ command_tuple = self._parse_pri_arg(arg)
+ if command_tuple != None:
+ self._set_filter_priority(command_tuple)
+
+class ShowFrameFilterPriority(gdb.Command):
+ """GDB command to show the priority of the specified frame-filter.
+
+ Usage: show frame-filter priority DICTIONARY NAME
+
+ DICTIONARY is the name of the frame filter dictionary on which to
+ operate. Named dictionaries are: "global" for the global frame
+ filter dictionary, "progspace" for the program space's framefilter
+ dictionary. If either of these two are not specified, the
+ dictionary name is assumed to be the name of the object-file name.
+
+ NAME matches the name of the frame-filter to operate on.
+ """
+
+ def __init__(self):
+ super(ShowFrameFilterPriority, self).__init__("show frame-filter " \
+ "priority",
+ gdb.COMMAND_DATA)
+
+ def _parse_pri_arg(self, arg):
+ """Internal worker to parse a dictionary and name from a
+ tuple.
+
+ Arguments:
+ arg: Tuple which contains the arguments from the command.
+
+ Returns:
+ A tuple containing the dictionary, and frame filter name.
+
+ Raises:
+ gdb.GdbError: An error parsing the arguments.
+ """
+
+ argv = gdb.string_to_argv(arg);
+ argc = len(argv)
+ if argc != 2:
+ print("show frame-filter priority " \
+ "takes exactly two arguments.")
+ return None
+
+ return argv
+
+ def get_filter_priority(self, frame_filters, name):
+ """Worker for retrieving the priority of frame_filters.
+
+ Arguments:
+ frame_filters: Name of frame filter dictionary.
+ name: object to select printers.
+
+ Returns:
+ The priority of the frame filter.
+
+ Raises:
+ gdb.GdbError: A frame filter cannot be found.
+ """
+
+ op_list = gdb.frames.return_list(frame_filters)
+
+ try:
+ ff = op_list[name]
+ except KeyError:
+ msg = "frame-filter '" + str(name) + "' not found."
+ raise gdb.GdbError(msg)
+
+ return gdb.frames.get_priority(ff)
+
+ def complete(self, text, word):
+ """Completion function for both frame filter dictionary, and
+ frame filter name."""
+
+ if text.count(" ") == 0:
+ return _complete_frame_filter_list(text, word, False)
+ else:
+ printer_list = frame._return_list(text.split()[0].rstrip())
+ return _complete_frame_filter_name(word, printer_list)
+
+ def invoke(self, arg, from_tty):
+ command_tuple = self._parse_pri_arg(arg)
+ if command_tuple == None:
+ return
+ filter_name = command_tuple[1]
+ list_name = command_tuple[0]
+ try:
+ priority = self.get_filter_priority(list_name, filter_name);
+ except Exception:
+ e = sys.exc_info()[1]
+ print("Error printing filter priority for '"+name+"':"+str(e))
+ else:
+ print("Priority of filter '" + filter_name + "' in list '" \
+ + list_name + "' is: " + str(priority))
+
+# Register commands
+SetFilterPrefixCmd()
+ShowFilterPrefixCmd()
+InfoFrameFilter()
+EnableFrameFilter()
+DisableFrameFilter()
+SetFrameFilterPriority()
+ShowFrameFilterPriority()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/pretty_printers.py b/gdb/bin/x86_64/data-directory/python/gdb/command/pretty_printers.py
new file mode 100644
index 0000000..21bb0d6
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/pretty_printers.py
@@ -0,0 +1,368 @@
+# Pretty-printer commands.
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""GDB commands for working with pretty-printers."""
+
+import copy
+import gdb
+import re
+
+
+def parse_printer_regexps(arg):
+ """Internal utility to parse a pretty-printer command argv.
+
+ Arguments:
+ arg: The arguments to the command. The format is:
+ [object-regexp [name-regexp]].
+ Individual printers in a collection are named as
+ printer-name;subprinter-name.
+
+ Returns:
+ The result is a 3-tuple of compiled regular expressions, except that
+ the resulting compiled subprinter regexp is None if not provided.
+
+ Raises:
+ SyntaxError: an error processing ARG
+ """
+
+ argv = gdb.string_to_argv(arg);
+ argc = len(argv)
+ object_regexp = "" # match everything
+ name_regexp = "" # match everything
+ subname_regexp = None
+ if argc > 3:
+ raise SyntaxError("too many arguments")
+ if argc >= 1:
+ object_regexp = argv[0]
+ if argc >= 2:
+ name_subname = argv[1].split(";", 1)
+ name_regexp = name_subname[0]
+ if len(name_subname) == 2:
+ subname_regexp = name_subname[1]
+ # That re.compile raises SyntaxError was determined empirically.
+ # We catch it and reraise it to provide a slightly more useful
+ # error message for the user.
+ try:
+ object_re = re.compile(object_regexp)
+ except SyntaxError:
+ raise SyntaxError("invalid object regexp: %s" % object_regexp)
+ try:
+ name_re = re.compile (name_regexp)
+ except SyntaxError:
+ raise SyntaxError("invalid name regexp: %s" % name_regexp)
+ if subname_regexp is not None:
+ try:
+ subname_re = re.compile(subname_regexp)
+ except SyntaxError:
+ raise SyntaxError("invalid subname regexp: %s" % subname_regexp)
+ else:
+ subname_re = None
+ return(object_re, name_re, subname_re)
+
+
+def printer_enabled_p(printer):
+ """Internal utility to see if printer (or subprinter) is enabled."""
+ if hasattr(printer, "enabled"):
+ return printer.enabled
+ else:
+ return True
+
+
+class InfoPrettyPrinter(gdb.Command):
+ """GDB command to list all registered pretty-printers.
+
+ Usage: info pretty-printer [object-regexp [name-regexp]]
+
+ OBJECT-REGEXP is a regular expression matching the objects to list.
+ Objects are "global", the program space's file, and the objfiles within
+ that program space.
+
+ NAME-REGEXP matches the name of the pretty-printer.
+ Individual printers in a collection are named as
+ printer-name;subprinter-name.
+ """
+
+ def __init__ (self):
+ super(InfoPrettyPrinter, self).__init__("info pretty-printer",
+ gdb.COMMAND_DATA)
+
+ @staticmethod
+ def enabled_string(printer):
+ """Return "" if PRINTER is enabled, otherwise " [disabled]"."""
+ if printer_enabled_p(printer):
+ return ""
+ else:
+ return " [disabled]"
+
+ @staticmethod
+ def printer_name(printer):
+ """Return the printer's name."""
+ if hasattr(printer, "name"):
+ return printer.name
+ if hasattr(printer, "__name__"):
+ return printer.__name__
+ # This "shouldn't happen", but the public API allows for
+ # direct additions to the pretty-printer list, and we shouldn't
+ # crash because someone added a bogus printer.
+ # Plus we want to give the user a way to list unknown printers.
+ return "unknown"
+
+ def list_pretty_printers(self, pretty_printers, name_re, subname_re):
+ """Print a list of pretty-printers."""
+ # A potential enhancement is to provide an option to list printers in
+ # "lookup order" (i.e. unsorted).
+ sorted_pretty_printers = sorted (copy.copy(pretty_printers),
+ key = self.printer_name)
+ for printer in sorted_pretty_printers:
+ name = self.printer_name(printer)
+ enabled = self.enabled_string(printer)
+ if name_re.match(name):
+ print (" %s%s" % (name, enabled))
+ if (hasattr(printer, "subprinters") and
+ printer.subprinters is not None):
+ sorted_subprinters = sorted (copy.copy(printer.subprinters),
+ key = self.printer_name)
+ for subprinter in sorted_subprinters:
+ if (not subname_re or
+ subname_re.match(subprinter.name)):
+ print (" %s%s" %
+ (subprinter.name,
+ self.enabled_string(subprinter)))
+
+ def invoke1(self, title, printer_list,
+ obj_name_to_match, object_re, name_re, subname_re):
+ """Subroutine of invoke to simplify it."""
+ if printer_list and object_re.match(obj_name_to_match):
+ print (title)
+ self.list_pretty_printers(printer_list, name_re, subname_re)
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ (object_re, name_re, subname_re) = parse_printer_regexps(arg)
+ self.invoke1("global pretty-printers:", gdb.pretty_printers,
+ "global", object_re, name_re, subname_re)
+ cp = gdb.current_progspace()
+ self.invoke1("progspace %s pretty-printers:" % cp.filename,
+ cp.pretty_printers, "progspace",
+ object_re, name_re, subname_re)
+ for objfile in gdb.objfiles():
+ self.invoke1(" objfile %s pretty-printers:" % objfile.filename,
+ objfile.pretty_printers, objfile.filename,
+ object_re, name_re, subname_re)
+
+
+def count_enabled_printers(pretty_printers):
+ """Return a 2-tuple of number of enabled and total printers."""
+ enabled = 0
+ total = 0
+ for printer in pretty_printers:
+ if (hasattr(printer, "subprinters")
+ and printer.subprinters is not None):
+ if printer_enabled_p(printer):
+ for subprinter in printer.subprinters:
+ if printer_enabled_p(subprinter):
+ enabled += 1
+ total += len(printer.subprinters)
+ else:
+ if printer_enabled_p(printer):
+ enabled += 1
+ total += 1
+ return (enabled, total)
+
+
+def count_all_enabled_printers():
+ """Return a 2-tuble of the enabled state and total number of all printers.
+ This includes subprinters.
+ """
+ enabled_count = 0
+ total_count = 0
+ (t_enabled, t_total) = count_enabled_printers(gdb.pretty_printers)
+ enabled_count += t_enabled
+ total_count += t_total
+ (t_enabled, t_total) = count_enabled_printers(gdb.current_progspace().pretty_printers)
+ enabled_count += t_enabled
+ total_count += t_total
+ for objfile in gdb.objfiles():
+ (t_enabled, t_total) = count_enabled_printers(objfile.pretty_printers)
+ enabled_count += t_enabled
+ total_count += t_total
+ return (enabled_count, total_count)
+
+
+def pluralize(text, n, suffix="s"):
+ """Return TEXT pluralized if N != 1."""
+ if n != 1:
+ return "%s%s" % (text, suffix)
+ else:
+ return text
+
+
+def show_pretty_printer_enabled_summary():
+ """Print the number of printers enabled/disabled.
+ We count subprinters individually.
+ """
+ (enabled_count, total_count) = count_all_enabled_printers()
+ print ("%d of %d printers enabled" % (enabled_count, total_count))
+
+
+def do_enable_pretty_printer_1 (pretty_printers, name_re, subname_re, flag):
+ """Worker for enabling/disabling pretty-printers.
+
+ Arguments:
+ pretty_printers: list of pretty-printers
+ name_re: regular-expression object to select printers
+ subname_re: regular expression object to select subprinters or None
+ if all are affected
+ flag: True for Enable, False for Disable
+
+ Returns:
+ The number of printers affected.
+ This is just for informational purposes for the user.
+ """
+ total = 0
+ for printer in pretty_printers:
+ if (hasattr(printer, "name") and name_re.match(printer.name) or
+ hasattr(printer, "__name__") and name_re.match(printer.__name__)):
+ if (hasattr(printer, "subprinters") and
+ printer.subprinters is not None):
+ if not subname_re:
+ # Only record printers that change state.
+ if printer_enabled_p(printer) != flag:
+ for subprinter in printer.subprinters:
+ if printer_enabled_p(subprinter):
+ total += 1
+ # NOTE: We preserve individual subprinter settings.
+ printer.enabled = flag
+ else:
+ # NOTE: Whether this actually disables the subprinter
+ # depends on whether the printer's lookup function supports
+ # the "enable" API. We can only assume it does.
+ for subprinter in printer.subprinters:
+ if subname_re.match(subprinter.name):
+ # Only record printers that change state.
+ if (printer_enabled_p(printer) and
+ printer_enabled_p(subprinter) != flag):
+ total += 1
+ subprinter.enabled = flag
+ else:
+ # This printer has no subprinters.
+ # If the user does "disable pretty-printer .* .* foo"
+ # should we disable printers that don't have subprinters?
+ # How do we apply "foo" in this context? Since there is no
+ # "foo" subprinter it feels like we should skip this printer.
+ # There's still the issue of how to handle
+ # "disable pretty-printer .* .* .*", and every other variation
+ # that can match everything. For now punt and only support
+ # "disable pretty-printer .* .*" (i.e. subname is elided)
+ # to disable everything.
+ if not subname_re:
+ # Only record printers that change state.
+ if printer_enabled_p(printer) != flag:
+ total += 1
+ printer.enabled = flag
+ return total
+
+
+def do_enable_pretty_printer (arg, flag):
+ """Internal worker for enabling/disabling pretty-printers."""
+ (object_re, name_re, subname_re) = parse_printer_regexps(arg)
+
+ total = 0
+ if object_re.match("global"):
+ total += do_enable_pretty_printer_1(gdb.pretty_printers,
+ name_re, subname_re, flag)
+ cp = gdb.current_progspace()
+ if object_re.match("progspace"):
+ total += do_enable_pretty_printer_1(cp.pretty_printers,
+ name_re, subname_re, flag)
+ for objfile in gdb.objfiles():
+ if object_re.match(objfile.filename):
+ total += do_enable_pretty_printer_1(objfile.pretty_printers,
+ name_re, subname_re, flag)
+
+ if flag:
+ state = "enabled"
+ else:
+ state = "disabled"
+ print ("%d %s %s" % (total, pluralize("printer", total), state))
+
+ # Print the total list of printers currently enabled/disabled.
+ # This is to further assist the user in determining whether the result
+ # is expected. Since we use regexps to select it's useful.
+ show_pretty_printer_enabled_summary()
+
+
+# Enable/Disable one or more pretty-printers.
+#
+# This is intended for use when a broken pretty-printer is shipped/installed
+# and the user wants to disable that printer without disabling all the other
+# printers.
+#
+# A useful addition would be -v (verbose) to show each printer affected.
+
+class EnablePrettyPrinter (gdb.Command):
+ """GDB command to enable the specified pretty-printer.
+
+ Usage: enable pretty-printer [object-regexp [name-regexp]]
+
+ OBJECT-REGEXP is a regular expression matching the objects to examine.
+ Objects are "global", the program space's file, and the objfiles within
+ that program space.
+
+ NAME-REGEXP matches the name of the pretty-printer.
+ Individual printers in a collection are named as
+ printer-name;subprinter-name.
+ """
+
+ def __init__(self):
+ super(EnablePrettyPrinter, self).__init__("enable pretty-printer",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ do_enable_pretty_printer(arg, True)
+
+
+class DisablePrettyPrinter (gdb.Command):
+ """GDB command to disable the specified pretty-printer.
+
+ Usage: disable pretty-printer [object-regexp [name-regexp]]
+
+ OBJECT-REGEXP is a regular expression matching the objects to examine.
+ Objects are "global", the program space's file, and the objfiles within
+ that program space.
+
+ NAME-REGEXP matches the name of the pretty-printer.
+ Individual printers in a collection are named as
+ printer-name;subprinter-name.
+ """
+
+ def __init__(self):
+ super(DisablePrettyPrinter, self).__init__("disable pretty-printer",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ do_enable_pretty_printer(arg, False)
+
+
+def register_pretty_printer_commands():
+ """Call from a top level script to install the pretty-printer commands."""
+ InfoPrettyPrinter()
+ EnablePrettyPrinter()
+ DisablePrettyPrinter()
+
+register_pretty_printer_commands()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/prompt.py b/gdb/bin/x86_64/data-directory/python/gdb/command/prompt.py
new file mode 100644
index 0000000..c7fc0d8
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/prompt.py
@@ -0,0 +1,65 @@
+# Extended prompt.
+# Copyright (C) 2011-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""GDB command for working with extended prompts."""
+
+import gdb
+import gdb.prompt
+
+class _ExtendedPrompt(gdb.Parameter):
+
+ """Set the extended prompt.
+
+Usage: set extended-prompt VALUE
+
+Substitutions are applied to VALUE to compute the real prompt.
+
+The currently defined substitutions are:
+
+"""
+ # Add the prompt library's dynamically generated help to the
+ # __doc__ string.
+ __doc__ = __doc__ + gdb.prompt.prompt_help()
+
+ set_doc = "Set the extended prompt."
+ show_doc = "Show the extended prompt."
+
+ def __init__(self):
+ super(_ExtendedPrompt, self).__init__("extended-prompt",
+ gdb.COMMAND_SUPPORT,
+ gdb.PARAM_STRING_NOESCAPE)
+ self.value = ''
+ self.hook_set = False
+
+ def get_show_string (self, pvalue):
+ if self.value is not '':
+ return "The extended prompt is: " + self.value
+ else:
+ return "The extended prompt is not set."
+
+ def get_set_string (self):
+ if self.hook_set == False:
+ gdb.prompt_hook = self.before_prompt_hook
+ self.hook_set = True
+ return ""
+
+ def before_prompt_hook(self, current):
+ if self.value is not '':
+ return gdb.prompt.substitute_prompt(self.value)
+ else:
+ return None
+
+_ExtendedPrompt()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/type_printers.py b/gdb/bin/x86_64/data-directory/python/gdb/command/type_printers.py
new file mode 100644
index 0000000..c83ed35
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/type_printers.py
@@ -0,0 +1,125 @@
+# Type printer commands.
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import copy
+import gdb
+
+"""GDB commands for working with type-printers."""
+
+class InfoTypePrinter(gdb.Command):
+ """GDB command to list all registered type-printers.
+
+ Usage: info type-printers
+ """
+
+ def __init__ (self):
+ super(InfoTypePrinter, self).__init__("info type-printers",
+ gdb.COMMAND_DATA)
+
+ def list_type_printers(self, type_printers):
+ """Print a list of type printers."""
+ # A potential enhancement is to provide an option to list printers in
+ # "lookup order" (i.e. unsorted).
+ sorted_type_printers = sorted (copy.copy(type_printers),
+ key = lambda x: x.name)
+ for printer in sorted_type_printers:
+ if printer.enabled:
+ enabled = ''
+ else:
+ enabled = " [disabled]"
+ print (" %s%s" % (printer.name, enabled))
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ sep = ''
+ for objfile in gdb.objfiles():
+ if objfile.type_printers:
+ print ("%sType printers for %s:" % (sep, objfile.filename))
+ self.list_type_printers(objfile.type_printers)
+ sep = '\n'
+ if gdb.current_progspace().type_printers:
+ print ("%sType printers for program space:" % sep)
+ self.list_type_printers(gdb.current_progspace().type_printers)
+ sep = '\n'
+ if gdb.type_printers:
+ print ("%sGlobal type printers:" % sep)
+ self.list_type_printers(gdb.type_printers)
+
+class _EnableOrDisableCommand(gdb.Command):
+ def __init__(self, setting, name):
+ super(_EnableOrDisableCommand, self).__init__(name, gdb.COMMAND_DATA)
+ self.setting = setting
+
+ def set_some(self, name, printers):
+ result = False
+ for p in printers:
+ if name == p.name:
+ p.enabled = self.setting
+ result = True
+ return result
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ for name in arg.split():
+ ok = False
+ for objfile in gdb.objfiles():
+ if self.set_some(name, objfile.type_printers):
+ ok = True
+ if self.set_some(name, gdb.current_progspace().type_printers):
+ ok = True
+ if self.set_some(name, gdb.type_printers):
+ ok = True
+ if not ok:
+ print ("No type printer named '%s'" % name)
+
+ def add_some(self, result, word, printers):
+ for p in printers:
+ if p.name.startswith(word):
+ result.append(p.name)
+
+ def complete(self, text, word):
+ result = []
+ for objfile in gdb.objfiles():
+ self.add_some(result, word, objfile.type_printers)
+ self.add_some(result, word, gdb.current_progspace().type_printers)
+ self.add_some(result, word, gdb.type_printers)
+ return result
+
+class EnableTypePrinter(_EnableOrDisableCommand):
+ """GDB command to enable the specified type printer.
+
+ Usage: enable type-printer NAME
+
+ NAME is the name of the type-printer.
+ """
+
+ def __init__(self):
+ super(EnableTypePrinter, self).__init__(True, "enable type-printer")
+
+class DisableTypePrinter(_EnableOrDisableCommand):
+ """GDB command to disable the specified type-printer.
+
+ Usage: disable type-printer NAME
+
+ NAME is the name of the type-printer.
+ """
+
+ def __init__(self):
+ super(DisableTypePrinter, self).__init__(False, "disable type-printer")
+
+InfoTypePrinter()
+EnableTypePrinter()
+DisableTypePrinter()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/unwinders.py b/gdb/bin/x86_64/data-directory/python/gdb/command/unwinders.py
new file mode 100644
index 0000000..a9b9d8a
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/unwinders.py
@@ -0,0 +1,198 @@
+# Unwinder commands.
+# Copyright 2015-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb
+import re
+
+
+def validate_regexp(exp, idstring):
+ try:
+ return re.compile(exp)
+ except SyntaxError:
+ raise SyntaxError("Invalid %s regexp: %s." % (idstring, exp))
+
+
+def parse_unwinder_command_args(arg):
+ """Internal utility to parse unwinder command argv.
+
+ Arguments:
+ arg: The arguments to the command. The format is:
+ [locus-regexp [name-regexp]]
+
+ Returns:
+ A 2-tuple of compiled regular expressions.
+
+ Raises:
+ SyntaxError: an error processing ARG
+ """
+
+ argv = gdb.string_to_argv(arg)
+ argc = len(argv)
+ if argc > 2:
+ raise SyntaxError("Too many arguments.")
+ locus_regexp = ""
+ name_regexp = ""
+ if argc >= 1:
+ locus_regexp = argv[0]
+ if argc >= 2:
+ name_regexp = argv[1]
+ return (validate_regexp(locus_regexp, "locus"),
+ validate_regexp(name_regexp, "unwinder"))
+
+
+class InfoUnwinder(gdb.Command):
+ """GDB command to list unwinders.
+
+ Usage: info unwinder [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression matching the location of the
+ unwinder. If it is omitted, all registered unwinders from all
+ loci are listed. A locus can be 'global', 'progspace' to list
+ the unwinders from the current progspace, or a regular expression
+ matching filenames of objfiles.
+
+ NAME-REGEXP is a regular expression to filter unwinder names. If
+ this omitted for a specified locus, then all registered unwinders
+ in the locus are listed.
+ """
+
+ def __init__(self):
+ super(InfoUnwinder, self).__init__("info unwinder",
+ gdb.COMMAND_STACK)
+
+ def list_unwinders(self, title, unwinders, name_re):
+ """Lists the unwinders whose name matches regexp.
+
+ Arguments:
+ title: The line to print before the list.
+ unwinders: The list of the unwinders.
+ name_re: unwinder name filter.
+ """
+ if not unwinders:
+ return
+ print(title)
+ for unwinder in unwinders:
+ if name_re.match(unwinder.name):
+ print(" %s%s" % (unwinder.name,
+ "" if unwinder.enabled else " [disabled]"))
+
+ def invoke(self, arg, from_tty):
+ locus_re, name_re = parse_unwinder_command_args(arg)
+ if locus_re.match("global"):
+ self.list_unwinders("Global:", gdb.frame_unwinders,
+ name_re)
+ if locus_re.match("progspace"):
+ cp = gdb.current_progspace()
+ self.list_unwinders("Progspace %s:" % cp.filename,
+ cp.frame_unwinders, name_re)
+ for objfile in gdb.objfiles():
+ if locus_re.match(objfile.filename):
+ self.list_unwinders("Objfile %s:" % objfile.filename,
+ objfile.frame_unwinders, name_re)
+
+
+def do_enable_unwinder1(unwinders, name_re, flag):
+ """Enable/disable unwinders whose names match given regex.
+
+ Arguments:
+ unwinders: The list of unwinders.
+ name_re: Unwinder name filter.
+ flag: Enable/disable.
+
+ Returns:
+ The number of unwinders affected.
+ """
+ total = 0
+ for unwinder in unwinders:
+ if name_re.match(unwinder.name):
+ unwinder.enabled = flag
+ total += 1
+ return total
+
+
+def do_enable_unwinder(arg, flag):
+ """Enable/disable unwinder(s)."""
+ (locus_re, name_re) = parse_unwinder_command_args(arg)
+ total = 0
+ if locus_re.match("global"):
+ total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag)
+ if locus_re.match("progspace"):
+ total += do_enable_unwinder1(gdb.current_progspace().frame_unwinders,
+ name_re, flag)
+ for objfile in gdb.objfiles():
+ if locus_re.match(objfile.filename):
+ total += do_enable_unwinder1(objfile.frame_unwinders, name_re,
+ flag)
+ print("%d unwinder%s %s" % (total, "" if total == 1 else "s",
+ "enabled" if flag else "disabled"))
+
+
+class EnableUnwinder(gdb.Command):
+ """GDB command to enable unwinders.
+
+ Usage: enable unwinder [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression specifying the unwinders to
+ enable. It can 'global', 'progspace', or the name of an objfile
+ within that progspace.
+
+ NAME_REGEXP is a regular expression to filter unwinder names. If
+ this omitted for a specified locus, then all registered unwinders
+ in the locus are affected.
+
+ """
+
+ def __init__(self):
+ super(EnableUnwinder, self).__init__("enable unwinder",
+ gdb.COMMAND_STACK)
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ do_enable_unwinder(arg, True)
+
+
+class DisableUnwinder(gdb.Command):
+ """GDB command to disable the specified unwinder.
+
+ Usage: disable unwinder [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression specifying the unwinders to
+ disable. It can 'global', 'progspace', or the name of an objfile
+ within that progspace.
+
+ NAME_REGEXP is a regular expression to filter unwinder names. If
+ this omitted for a specified locus, then all registered unwinders
+ in the locus are affected.
+
+ """
+
+ def __init__(self):
+ super(DisableUnwinder, self).__init__("disable unwinder",
+ gdb.COMMAND_STACK)
+
+ def invoke(self, arg, from_tty):
+ """GDB calls this to perform the command."""
+ do_enable_unwinder(arg, False)
+
+
+def register_unwinder_commands():
+ """Installs the unwinder commands."""
+ InfoUnwinder()
+ EnableUnwinder()
+ DisableUnwinder()
+
+
+register_unwinder_commands()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/command/xmethods.py b/gdb/bin/x86_64/data-directory/python/gdb/command/xmethods.py
new file mode 100644
index 0000000..46f7b66
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/command/xmethods.py
@@ -0,0 +1,274 @@
+# Xmethod commands.
+# Copyright 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb
+import re
+
+"""GDB commands for working with xmethods."""
+
+
+def validate_xm_regexp(part_name, regexp):
+ try:
+ return re.compile(regexp)
+ except SyntaxError:
+ raise SyntaxError("Invalid %s regexp: %s", part_name, regexp)
+
+
+def parse_xm_command_args(arg):
+ """Parses the arguments passed to a xmethod command.
+
+ Arguments:
+ arg: The argument string passed to a xmethod command.
+
+ Returns:
+ A 3-tuple: (,
+ ,
+ )
+ """
+ argv = gdb.string_to_argv(arg)
+ argc = len(argv)
+ if argc > 2:
+ raise SyntaxError("Too many arguments to command.")
+ locus_regexp = ""
+ matcher_name_regexp = ""
+ xm_name_regexp = None
+ if argc >= 1:
+ locus_regexp = argv[0]
+ if argc == 2:
+ parts = argv[1].split(";", 1)
+ matcher_name_regexp = parts[0]
+ if len(parts) > 1:
+ xm_name_regexp = parts[1]
+ if xm_name_regexp:
+ name_re = validate_xm_regexp("xmethod name", xm_name_regexp)
+ else:
+ name_re = None
+ return (validate_xm_regexp("locus", locus_regexp),
+ validate_xm_regexp("matcher name", matcher_name_regexp),
+ name_re)
+
+
+def get_global_method_matchers(locus_re, matcher_re):
+ """Returns a dict of matching globally registered xmethods.
+
+ Arguments:
+ locus_re: Even though only globally registered xmethods are
+ looked up, they will be looked up only if 'global' matches
+ LOCUS_RE.
+ matcher_re: The regular expression matching the names of xmethods.
+
+ Returns:
+ A dict of matching globally registered xmethod matchers. The only
+ key in the dict will be 'global'.
+ """
+ locus_str = "global"
+ xm_dict = { locus_str: [] }
+ if locus_re.match("global"):
+ xm_dict[locus_str].extend(
+ [m for m in gdb.xmethods if matcher_re.match(m.name)])
+ return xm_dict
+
+
+def get_method_matchers_in_loci(loci, locus_re, matcher_re):
+ """Returns a dict of matching registered xmethods in the LOCI.
+
+ Arguments:
+ loci: The list of loci to lookup matching xmethods in.
+ locus_re: If a locus is an objfile, then xmethod matchers will be
+ looked up in it only if its filename matches the regular
+ expression LOCUS_RE. If a locus is the current progspace,
+ then xmethod matchers will be looked up in it only if the
+ string "progspace" matches LOCUS_RE.
+ matcher_re: The regular expression to match the xmethod matcher
+ names.
+
+ Returns:
+ A dict of matching xmethod matchers. The keys of the dict are the
+ filenames of the loci the xmethod matchers belong to.
+ """
+ xm_dict = {}
+ for locus in loci:
+ if isinstance(locus, gdb.Progspace):
+ if not locus_re.match('progspace'):
+ continue
+ locus_type = "progspace"
+ else:
+ if not locus_re.match(locus.filename):
+ continue
+ locus_type = "objfile"
+ locus_str = "%s %s" % (locus_type, locus.filename)
+ xm_dict[locus_str] = [
+ m for m in locus.xmethods if matcher_re.match(m.name)]
+ return xm_dict
+
+
+def print_xm_info(xm_dict, name_re):
+ """Print a dictionary of xmethods."""
+ def get_status_string(m):
+ if not m.enabled:
+ return " [disabled]"
+ else:
+ return ""
+
+ if not xm_dict:
+ return
+ for locus_str in xm_dict:
+ if not xm_dict[locus_str]:
+ continue
+ print ("Xmethods in %s:" % locus_str)
+ for matcher in xm_dict[locus_str]:
+ print (" %s%s" % (matcher.name, get_status_string(matcher)))
+ if not matcher.methods:
+ continue
+ for m in matcher.methods:
+ if name_re is None or name_re.match(m.name):
+ print (" %s%s" % (m.name, get_status_string(m)))
+
+
+def set_xm_status1(xm_dict, name_re, status):
+ """Set the status (enabled/disabled) of a dictionary of xmethods."""
+ for locus_str, matchers in xm_dict.items():
+ for matcher in matchers:
+ if not name_re:
+ # If the name regex is missing, then set the status of the
+ # matcher and move on.
+ matcher.enabled = status
+ continue
+ if not matcher.methods:
+ # The methods attribute could be None. Move on.
+ continue
+ for m in matcher.methods:
+ if name_re.match(m.name):
+ m.enabled = status
+
+
+def set_xm_status(arg, status):
+ """Set the status (enabled/disabled) of xmethods matching ARG.
+ This is a helper function for enable/disable commands. ARG is the
+ argument string passed to the commands.
+ """
+ locus_re, matcher_re, name_re = parse_xm_command_args(arg)
+ set_xm_status1(get_global_method_matchers(locus_re, matcher_re), name_re,
+ status)
+ set_xm_status1(
+ get_method_matchers_in_loci(
+ [gdb.current_progspace()], locus_re, matcher_re),
+ name_re,
+ status)
+ set_xm_status1(
+ get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
+ name_re,
+ status)
+
+
+class InfoXMethod(gdb.Command):
+ """GDB command to list registered xmethod matchers.
+
+ Usage: info xmethod [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression matching the location of the
+ xmethod matchers. If it is omitted, all registered xmethod matchers
+ from all loci are listed. A locus could be 'global', a regular expression
+ matching the current program space's filename, or a regular expression
+ matching filenames of objfiles. Locus could be 'progspace' to specify that
+ only xmethods from the current progspace should be listed.
+
+ NAME-REGEXP is a regular expression matching the names of xmethod
+ matchers. If this omitted for a specified locus, then all registered
+ xmethods in the locus are listed. To list only a certain xmethods
+ managed by a single matcher, the name regexp can be specified as
+ matcher-name-regexp;xmethod-name-regexp.
+ """
+
+ def __init__(self):
+ super(InfoXMethod, self).__init__("info xmethod",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ locus_re, matcher_re, name_re = parse_xm_command_args(arg)
+ print_xm_info(get_global_method_matchers(locus_re, matcher_re),
+ name_re)
+ print_xm_info(
+ get_method_matchers_in_loci(
+ [gdb.current_progspace()], locus_re, matcher_re),
+ name_re)
+ print_xm_info(
+ get_method_matchers_in_loci(gdb.objfiles(), locus_re, matcher_re),
+ name_re)
+
+
+class EnableXMethod(gdb.Command):
+ """GDB command to enable a specified (group of) xmethod(s).
+
+ Usage: enable xmethod [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression matching the location of the
+ xmethod matchers. If it is omitted, all registered xmethods matchers
+ from all loci are enabled. A locus could be 'global', a regular expression
+ matching the current program space's filename, or a regular expression
+ matching filenames of objfiles. Locus could be 'progspace' to specify that
+ only xmethods from the current progspace should be enabled.
+
+ NAME-REGEXP is a regular expression matching the names of xmethods
+ within a given locus. If this omitted for a specified locus, then all
+ registered xmethod matchers in the locus are enabled. To enable only
+ a certain xmethods managed by a single matcher, the name regexp can be
+ specified as matcher-name-regexp;xmethod-name-regexp.
+ """
+
+ def __init__(self):
+ super(EnableXMethod, self).__init__("enable xmethod",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ set_xm_status(arg, True)
+
+
+class DisableXMethod(gdb.Command):
+ """GDB command to disable a specified (group of) xmethod(s).
+
+ Usage: disable xmethod [locus-regexp [name-regexp]]
+
+ LOCUS-REGEXP is a regular expression matching the location of the
+ xmethod matchers. If it is omitted, all registered xmethod matchers
+ from all loci are disabled. A locus could be 'global', a regular
+ expression matching the current program space's filename, or a regular
+ expression filenames of objfiles. Locus could be 'progspace' to specify
+ that only xmethods from the current progspace should be disabled.
+
+ NAME-REGEXP is a regular expression matching the names of xmethods
+ within a given locus. If this omitted for a specified locus, then all
+ registered xmethod matchers in the locus are disabled. To disable
+ only a certain xmethods managed by a single matcher, the name regexp
+ can be specified as matcher-name-regexp;xmethod-name-regexp.
+ """
+
+ def __init__(self):
+ super(DisableXMethod, self).__init__("disable xmethod",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ set_xm_status(arg, False)
+
+
+def register_xmethod_commands():
+ """Installs the xmethod commands."""
+ InfoXMethod()
+ EnableXMethod()
+ DisableXMethod()
+
+
+register_xmethod_commands()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/frames.py b/gdb/bin/x86_64/data-directory/python/gdb/frames.py
new file mode 100644
index 0000000..6ae92ed
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/frames.py
@@ -0,0 +1,228 @@
+# Frame-filter commands.
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Internal functions for working with frame-filters."""
+
+import gdb
+from gdb.FrameIterator import FrameIterator
+from gdb.FrameDecorator import FrameDecorator
+import itertools
+import collections
+
+def get_priority(filter_item):
+ """ Internal worker function to return the frame-filter's priority
+ from a frame filter object. This is a fail free function as it is
+ used in sorting and filtering. If a badly implemented frame
+ filter does not implement the priority attribute, return zero
+ (otherwise sorting/filtering will fail and prevent other frame
+ filters from executing).
+
+ Arguments:
+ filter_item: An object conforming to the frame filter
+ interface.
+
+ Returns:
+ The priority of the frame filter from the "priority"
+ attribute, or zero.
+ """
+ # Do not fail here, as the sort will fail. If a filter has not
+ # (incorrectly) set a priority, set it to zero.
+ return getattr(filter_item, "priority", 0)
+
+def set_priority(filter_item, priority):
+ """ Internal worker function to set the frame-filter's priority.
+
+ Arguments:
+ filter_item: An object conforming to the frame filter
+ interface.
+ priority: The priority to assign as an integer.
+ """
+
+ filter_item.priority = priority
+
+def get_enabled(filter_item):
+ """ Internal worker function to return a filter's enabled state
+ from a frame filter object. This is a fail free function as it is
+ used in sorting and filtering. If a badly implemented frame
+ filter does not implement the enabled attribute, return False
+ (otherwise sorting/filtering will fail and prevent other frame
+ filters from executing).
+
+ Arguments:
+ filter_item: An object conforming to the frame filter
+ interface.
+
+ Returns:
+ The enabled state of the frame filter from the "enabled"
+ attribute, or False.
+ """
+
+ # If the filter class is badly implemented when called from the
+ # Python filter command, do not cease filter operations, just set
+ # enabled to False.
+ return getattr(filter_item, "enabled", False)
+
+def set_enabled(filter_item, state):
+ """ Internal Worker function to set the frame-filter's enabled
+ state.
+
+ Arguments:
+ filter_item: An object conforming to the frame filter
+ interface.
+ state: True or False, depending on desired state.
+ """
+
+ filter_item.enabled = state
+
+def return_list(name):
+ """ Internal Worker function to return the frame filter
+ dictionary, depending on the name supplied as an argument. If the
+ name is not "all", "global" or "progspace", it is assumed to name
+ an object-file.
+
+ Arguments:
+ name: The name of the list, as specified by GDB user commands.
+
+ Returns:
+ A dictionary object for a single specified dictionary, or a
+ list containing all the items for "all"
+
+ Raises:
+ gdb.GdbError: A dictionary of that name cannot be found.
+ """
+
+ # If all dictionaries are wanted in the case of "all" we
+ # cannot return a combined dictionary as keys() may clash in
+ # between different dictionaries. As we just want all the frame
+ # filters to enable/disable them all, just return the combined
+ # items() as a chained iterator of dictionary values.
+ if name == "all":
+ glob = gdb.frame_filters.values()
+ prog = gdb.current_progspace().frame_filters.values()
+ return_iter = itertools.chain(glob, prog)
+ for objfile in gdb.objfiles():
+ return_iter = itertools.chain(return_iter, objfile.frame_filters.values())
+
+ return return_iter
+
+ if name == "global":
+ return gdb.frame_filters
+ else:
+ if name == "progspace":
+ cp = gdb.current_progspace()
+ return cp.frame_filters
+ else:
+ for objfile in gdb.objfiles():
+ if name == objfile.filename:
+ return objfile.frame_filters
+
+ msg = "Cannot find frame-filter dictionary for '" + name + "'"
+ raise gdb.GdbError(msg)
+
+def _sort_list():
+ """ Internal Worker function to merge all known frame-filter
+ lists, prune any filters with the state set to "disabled", and
+ sort the list on the frame-filter's "priority" attribute.
+
+ Returns:
+ sorted_list: A sorted, pruned list of frame filters to
+ execute.
+ """
+
+ all_filters = return_list("all")
+ sorted_frame_filters = sorted(all_filters, key = get_priority,
+ reverse = True)
+
+ sorted_frame_filters = filter(get_enabled,
+ sorted_frame_filters)
+
+ return sorted_frame_filters
+
+def execute_frame_filters(frame, frame_low, frame_high):
+ """ Internal function called from GDB that will execute the chain
+ of frame filters. Each filter is executed in priority order.
+ After the execution completes, slice the iterator to frame_low -
+ frame_high range.
+
+ Arguments:
+ frame: The initial frame.
+
+ frame_low: The low range of the slice. If this is a negative
+ integer then it indicates a backward slice (ie bt -4) which
+ counts backward from the last frame in the backtrace.
+
+ frame_high: The high range of the slice. If this is -1 then
+ it indicates all frames until the end of the stack from
+ frame_low.
+
+ Returns:
+ frame_iterator: The sliced iterator after all frame
+ filters have had a change to execute, or None if no frame
+ filters are registered.
+ """
+
+ # Get a sorted list of frame filters.
+ sorted_list = list(_sort_list())
+
+ # Check to see if there are any frame-filters. If not, just
+ # return None and let default backtrace printing occur.
+ if len(sorted_list) == 0:
+ return None
+
+ frame_iterator = FrameIterator(frame)
+
+ # Apply a basic frame decorator to all gdb.Frames. This unifies
+ # the interface. Python 3.x moved the itertools.imap
+ # functionality to map(), so check if it is available.
+ if hasattr(itertools,"imap"):
+ frame_iterator = itertools.imap(FrameDecorator, frame_iterator)
+ else:
+ frame_iterator = map(FrameDecorator, frame_iterator)
+
+ for ff in sorted_list:
+ frame_iterator = ff.filter(frame_iterator)
+
+ # Slicing
+
+ # Is this a slice from the end of the backtrace, ie bt -2?
+ if frame_low < 0:
+ count = 0
+ slice_length = abs(frame_low)
+ # We cannot use MAXLEN argument for deque as it is 2.6 onwards
+ # and some GDB versions might be < 2.6.
+ sliced = collections.deque()
+
+ for frame_item in frame_iterator:
+ if count >= slice_length:
+ sliced.popleft();
+ count = count + 1
+ sliced.append(frame_item)
+
+ return iter(sliced)
+
+ # -1 for frame_high means until the end of the backtrace. Set to
+ # None if that is the case, to indicate to itertools.islice to
+ # slice to the end of the iterator.
+ if frame_high == -1:
+ frame_high = None
+ else:
+ # As frames start from 0, add one to frame_high so islice
+ # correctly finds the end
+ frame_high = frame_high + 1;
+
+ sliced = itertools.islice(frame_iterator, frame_low, frame_high)
+
+ return sliced
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/function/__init__.py b/gdb/bin/x86_64/data-directory/python/gdb/function/__init__.py
new file mode 100644
index 0000000..5220787
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/function/__init__.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/function/caller_is.py b/gdb/bin/x86_64/data-directory/python/gdb/function/caller_is.py
new file mode 100644
index 0000000..5b89191
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/function/caller_is.py
@@ -0,0 +1,160 @@
+# Caller-is functions.
+# Copyright (C) 2008-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb
+import re
+
+class CallerIs(gdb.Function):
+ """Check the calling function's name.
+
+Usage:
+ $_caller_is(name [, number_of_frames])
+
+Arguments:
+
+ name: The name of the function to search for.
+
+ number_of_frames: How many stack frames to traverse back from the currently
+ selected frame to compare with. If the value is greater than the depth of
+ the stack from that point then the result is False.
+ The default is 1.
+
+Returns:
+ True if the function's name at the specified frame is equal to name.
+"""
+
+ def __init__(self):
+ super(CallerIs, self).__init__("_caller_is")
+
+ def invoke(self, name, nframes = 1):
+ if nframes < 0:
+ raise ValueError("nframes must be >= 0")
+ frame = gdb.selected_frame()
+ while nframes > 0:
+ frame = frame.older()
+ if frame is None:
+ return False
+ nframes = nframes - 1
+ return frame.name() == name.string()
+
+class CallerMatches(gdb.Function):
+ """Compare the calling function's name with a regexp.
+
+Usage:
+ $_caller_matches(regex [, number_of_frames])
+
+Arguments:
+
+ regex: The regular expression to compare the function's name with.
+
+ number_of_frames: How many stack frames to traverse back from the currently
+ selected frame to compare with. If the value is greater than the depth of
+ the stack from that point then the result is False.
+ The default is 1.
+
+Returns:
+ True if the function's name at the specified frame matches regex.
+"""
+
+ def __init__(self):
+ super(CallerMatches, self).__init__("_caller_matches")
+
+ def invoke(self, name, nframes = 1):
+ if nframes < 0:
+ raise ValueError("nframes must be >= 0")
+ frame = gdb.selected_frame()
+ while nframes > 0:
+ frame = frame.older()
+ if frame is None:
+ return False
+ nframes = nframes - 1
+ return re.match(name.string(), frame.name()) is not None
+
+class AnyCallerIs(gdb.Function):
+ """Check all calling function's names.
+
+Usage:
+ $_any_caller_is(name [, number_of_frames])
+
+Arguments:
+
+ name: The name of the function to search for.
+
+ number_of_frames: How many stack frames to traverse back from the currently
+ selected frame to compare with. If the value is greater than the depth of
+ the stack from that point then the result is False.
+ The default is 1.
+
+Returns:
+ True if any function's name is equal to name.
+"""
+
+ def __init__(self):
+ super(AnyCallerIs, self).__init__("_any_caller_is")
+
+ def invoke(self, name, nframes = 1):
+ if nframes < 0:
+ raise ValueError("nframes must be >= 0")
+ frame = gdb.selected_frame()
+ while nframes >= 0:
+ if frame.name() == name.string():
+ return True
+ frame = frame.older()
+ if frame is None:
+ return False
+ nframes = nframes - 1
+ return False
+
+class AnyCallerMatches(gdb.Function):
+ """Compare all calling function's names with a regexp.
+
+Usage:
+ $_any_caller_matches(regex [, number_of_frames])
+
+Arguments:
+
+ regex: The regular expression to compare the function's name with.
+
+ number_of_frames: How many stack frames to traverse back from the currently
+ selected frame to compare with. If the value is greater than the depth of
+ the stack from that point then the result is False.
+ The default is 1.
+
+Returns:
+ True if any function's name matches regex.
+"""
+
+ def __init__(self):
+ super(AnyCallerMatches, self).__init__("_any_caller_matches")
+
+ def invoke(self, name, nframes = 1):
+ if nframes < 0:
+ raise ValueError("nframes must be >= 0")
+ frame = gdb.selected_frame()
+ name_re = re.compile(name.string())
+ while nframes >= 0:
+ if name_re.match(frame.name()) is not None:
+ return True
+ frame = frame.older()
+ if frame is None:
+ return False
+ nframes = nframes - 1
+ return False
+
+CallerIs()
+CallerMatches()
+AnyCallerIs()
+AnyCallerMatches()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/function/strfns.py b/gdb/bin/x86_64/data-directory/python/gdb/function/strfns.py
new file mode 100644
index 0000000..06a37ad
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/function/strfns.py
@@ -0,0 +1,108 @@
+# Useful gdb string convenience functions.
+# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""$_memeq, $_strlen, $_streq, $_regex"""
+
+import gdb
+import re
+
+
+class _MemEq(gdb.Function):
+ """$_memeq - compare bytes of memory
+
+Usage:
+ $_memeq(a, b, len)
+
+Returns:
+ True if len bytes at a and b compare equally.
+"""
+ def __init__(self):
+ super(_MemEq, self).__init__("_memeq")
+
+ def invoke(self, a, b, length):
+ if length < 0:
+ raise ValueError("length must be non-negative")
+ if length == 0:
+ return True
+ # The argument(s) to vector are [low_bound,]high_bound.
+ byte_vector = gdb.lookup_type("char").vector(length - 1)
+ ptr_byte_vector = byte_vector.pointer()
+ a_ptr = a.reinterpret_cast(ptr_byte_vector)
+ b_ptr = b.reinterpret_cast(ptr_byte_vector)
+ return a_ptr.dereference() == b_ptr.dereference()
+
+
+class _StrLen(gdb.Function):
+ """$_strlen - compute string length
+
+Usage:
+ $_strlen(a)
+
+Returns:
+ Length of string a, assumed to be a string in the current language.
+"""
+ def __init__(self):
+ super(_StrLen, self).__init__("_strlen")
+
+ def invoke(self, a):
+ s = a.string()
+ return len(s)
+
+
+class _StrEq(gdb.Function):
+ """$_streq - check string equality
+
+Usage:
+ $_streq(a, b)
+
+Returns:
+ True if a and b are identical strings in the current language.
+
+Example (amd64-linux):
+ catch syscall open
+ cond $bpnum $_streq((char*) $rdi, "foo")
+"""
+ def __init__(self):
+ super(_StrEq, self).__init__("_streq")
+
+ def invoke(self, a, b):
+ return a.string() == b.string()
+
+
+class _RegEx(gdb.Function):
+ """$_regex - check if a string matches a regular expression
+
+Usage:
+ $_regex(string, regex)
+
+Returns:
+ True if string str (in the current language) matches the
+ regular expression regex.
+"""
+ def __init__(self):
+ super(_RegEx, self).__init__("_regex")
+
+ def invoke(self, string, regex):
+ s = string.string()
+ r = re.compile(regex.string())
+ return bool(r.match(s))
+
+
+# GDB will import us automagically via gdb/__init__.py.
+_MemEq()
+_StrLen()
+_StrEq()
+_RegEx()
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/printer/__init__.py b/gdb/bin/x86_64/data-directory/python/gdb/printer/__init__.py
new file mode 100644
index 0000000..a8ac8bc
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/printer/__init__.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/printer/bound_registers.py b/gdb/bin/x86_64/data-directory/python/gdb/printer/bound_registers.py
new file mode 100644
index 0000000..9ff94aa
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/printer/bound_registers.py
@@ -0,0 +1,36 @@
+# Pretty-printers for bounds registers.
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import gdb.printing
+
+class MpxBound128Printer:
+ """Adds size field to a mpx __gdb_builtin_type_bound128 type."""
+
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ upper = self.val["ubound"]
+ lower = self.val["lbound"]
+ size = (long) ((upper) - (lower))
+ if size > -1:
+ size = size + 1
+ result = '{lbound = %s, ubound = %s} : size %s' % (lower, upper, size)
+ return result
+
+gdb.printing.add_builtin_pretty_printer ('mpx_bound128',
+ '^__gdb_builtin_type_bound128',
+ MpxBound128Printer)
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/printing.py b/gdb/bin/x86_64/data-directory/python/gdb/printing.py
new file mode 100644
index 0000000..63c3aeb
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/printing.py
@@ -0,0 +1,285 @@
+# Pretty-printer utilities.
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Utilities for working with pretty-printers."""
+
+import gdb
+import gdb.types
+import re
+import sys
+
+if sys.version_info[0] > 2:
+ # Python 3 removed basestring and long
+ basestring = str
+ long = int
+
+class PrettyPrinter(object):
+ """A basic pretty-printer.
+
+ Attributes:
+ name: A unique string among all printers for the context in which
+ it is defined (objfile, progspace, or global(gdb)), and should
+ meaningfully describe what can be pretty-printed.
+ E.g., "StringPiece" or "protobufs".
+ subprinters: An iterable object with each element having a `name'
+ attribute, and, potentially, "enabled" attribute.
+ Or this is None if there are no subprinters.
+ enabled: A boolean indicating if the printer is enabled.
+
+ Subprinters are for situations where "one" pretty-printer is actually a
+ collection of several printers. E.g., The libstdc++ pretty-printer has
+ a pretty-printer for each of several different types, based on regexps.
+ """
+
+ # While one might want to push subprinters into the subclass, it's
+ # present here to formalize such support to simplify
+ # commands/pretty_printers.py.
+
+ def __init__(self, name, subprinters=None):
+ self.name = name
+ self.subprinters = subprinters
+ self.enabled = True
+
+ def __call__(self, val):
+ # The subclass must define this.
+ raise NotImplementedError("PrettyPrinter __call__")
+
+
+class SubPrettyPrinter(object):
+ """Baseclass for sub-pretty-printers.
+
+ Sub-pretty-printers needn't use this, but it formalizes what's needed.
+
+ Attributes:
+ name: The name of the subprinter.
+ enabled: A boolean indicating if the subprinter is enabled.
+ """
+
+ def __init__(self, name):
+ self.name = name
+ self.enabled = True
+
+
+def register_pretty_printer(obj, printer, replace=False):
+ """Register pretty-printer PRINTER with OBJ.
+
+ The printer is added to the front of the search list, thus one can override
+ an existing printer if one needs to. Use a different name when overriding
+ an existing printer, otherwise an exception will be raised; multiple
+ printers with the same name are disallowed.
+
+ Arguments:
+ obj: Either an objfile, progspace, or None (in which case the printer
+ is registered globally).
+ printer: Either a function of one argument (old way) or any object
+ which has attributes: name, enabled, __call__.
+ replace: If True replace any existing copy of the printer.
+ Otherwise if the printer already exists raise an exception.
+
+ Returns:
+ Nothing.
+
+ Raises:
+ TypeError: A problem with the type of the printer.
+ ValueError: The printer's name contains a semicolon ";".
+ RuntimeError: A printer with the same name is already registered.
+
+ If the caller wants the printer to be listable and disableable, it must
+ follow the PrettyPrinter API. This applies to the old way (functions) too.
+ If printer is an object, __call__ is a method of two arguments:
+ self, and the value to be pretty-printed. See PrettyPrinter.
+ """
+
+ # Watch for both __name__ and name.
+ # Functions get the former for free, but we don't want to use an
+ # attribute named __foo__ for pretty-printers-as-objects.
+ # If printer has both, we use `name'.
+ if not hasattr(printer, "__name__") and not hasattr(printer, "name"):
+ raise TypeError("printer missing attribute: name")
+ if hasattr(printer, "name") and not hasattr(printer, "enabled"):
+ raise TypeError("printer missing attribute: enabled")
+ if not hasattr(printer, "__call__"):
+ raise TypeError("printer missing attribute: __call__")
+
+ if hasattr(printer, "name"):
+ name = printer.name
+ else:
+ name = printer.__name__
+ if obj is None or obj is gdb:
+ if gdb.parameter("verbose"):
+ gdb.write("Registering global %s pretty-printer ...\n" % name)
+ obj = gdb
+ else:
+ if gdb.parameter("verbose"):
+ gdb.write("Registering %s pretty-printer for %s ...\n" % (
+ name, obj.filename))
+
+ # Printers implemented as functions are old-style. In order to not risk
+ # breaking anything we do not check __name__ here.
+ if hasattr(printer, "name"):
+ if not isinstance(printer.name, basestring):
+ raise TypeError("printer name is not a string")
+ # If printer provides a name, make sure it doesn't contain ";".
+ # Semicolon is used by the info/enable/disable pretty-printer commands
+ # to delimit subprinters.
+ if printer.name.find(";") >= 0:
+ raise ValueError("semicolon ';' in printer name")
+ # Also make sure the name is unique.
+ # Alas, we can't do the same for functions and __name__, they could
+ # all have a canonical name like "lookup_function".
+ # PERF: gdb records printers in a list, making this inefficient.
+ i = 0
+ for p in obj.pretty_printers:
+ if hasattr(p, "name") and p.name == printer.name:
+ if replace:
+ del obj.pretty_printers[i]
+ break
+ else:
+ raise RuntimeError("pretty-printer already registered: %s" %
+ printer.name)
+ i = i + 1
+
+ obj.pretty_printers.insert(0, printer)
+
+
+class RegexpCollectionPrettyPrinter(PrettyPrinter):
+ """Class for implementing a collection of regular-expression based pretty-printers.
+
+ Intended usage:
+
+ pretty_printer = RegexpCollectionPrettyPrinter("my_library")
+ pretty_printer.add_printer("myclass1", "^myclass1$", MyClass1Printer)
+ ...
+ pretty_printer.add_printer("myclassN", "^myclassN$", MyClassNPrinter)
+ register_pretty_printer(obj, pretty_printer)
+ """
+
+ class RegexpSubprinter(SubPrettyPrinter):
+ def __init__(self, name, regexp, gen_printer):
+ super(RegexpCollectionPrettyPrinter.RegexpSubprinter, self).__init__(name)
+ self.regexp = regexp
+ self.gen_printer = gen_printer
+ self.compiled_re = re.compile(regexp)
+
+ def __init__(self, name):
+ super(RegexpCollectionPrettyPrinter, self).__init__(name, [])
+
+ def add_printer(self, name, regexp, gen_printer):
+ """Add a printer to the list.
+
+ The printer is added to the end of the list.
+
+ Arguments:
+ name: The name of the subprinter.
+ regexp: The regular expression, as a string.
+ gen_printer: A function/method that given a value returns an
+ object to pretty-print it.
+
+ Returns:
+ Nothing.
+ """
+
+ # NOTE: A previous version made the name of each printer the regexp.
+ # That makes it awkward to pass to the enable/disable commands (it's
+ # cumbersome to make a regexp of a regexp). So now the name is a
+ # separate parameter.
+
+ self.subprinters.append(self.RegexpSubprinter(name, regexp,
+ gen_printer))
+
+ def __call__(self, val):
+ """Lookup the pretty-printer for the provided value."""
+
+ # Get the type name.
+ typename = gdb.types.get_basic_type(val.type).tag
+ if not typename:
+ typename = val.type.name
+ if not typename:
+ return None
+
+ # Iterate over table of type regexps to determine
+ # if a printer is registered for that type.
+ # Return an instantiation of the printer if found.
+ for printer in self.subprinters:
+ if printer.enabled and printer.compiled_re.search(typename):
+ return printer.gen_printer(val)
+
+ # Cannot find a pretty printer. Return None.
+ return None
+
+# A helper class for printing enum types. This class is instantiated
+# with a list of enumerators to print a particular Value.
+class _EnumInstance:
+ def __init__(self, enumerators, val):
+ self.enumerators = enumerators
+ self.val = val
+
+ def to_string(self):
+ flag_list = []
+ v = long(self.val)
+ any_found = False
+ for (e_name, e_value) in self.enumerators:
+ if v & e_value != 0:
+ flag_list.append(e_name)
+ v = v & ~e_value
+ any_found = True
+ if not any_found or v != 0:
+ # Leftover value.
+ flag_list.append('' % v)
+ return "0x%x [%s]" % (int(self.val), " | ".join(flag_list))
+
+class FlagEnumerationPrinter(PrettyPrinter):
+ """A pretty-printer which can be used to print a flag-style enumeration.
+ A flag-style enumeration is one where the enumerators are or'd
+ together to create values. The new printer will print these
+ symbolically using '|' notation. The printer must be registered
+ manually. This printer is most useful when an enum is flag-like,
+ but has some overlap. GDB's built-in printing will not handle
+ this case, but this printer will attempt to."""
+
+ def __init__(self, enum_type):
+ super(FlagEnumerationPrinter, self).__init__(enum_type)
+ self.initialized = False
+
+ def __call__(self, val):
+ if not self.initialized:
+ self.initialized = True
+ flags = gdb.lookup_type(self.name)
+ self.enumerators = []
+ for field in flags.fields():
+ self.enumerators.append((field.name, field.enumval))
+ # Sorting the enumerators by value usually does the right
+ # thing.
+ self.enumerators.sort(key = lambda x: x[1])
+
+ if self.enabled:
+ return _EnumInstance(self.enumerators, val)
+ else:
+ return None
+
+
+# Builtin pretty-printers.
+# The set is defined as empty, and files in printing/*.py add their printers
+# to this with add_builtin_pretty_printer.
+
+_builtin_pretty_printers = RegexpCollectionPrettyPrinter("builtin")
+
+register_pretty_printer(None, _builtin_pretty_printers)
+
+# Add a builtin pretty-printer.
+
+def add_builtin_pretty_printer(name, regexp, printer):
+ _builtin_pretty_printers.add_printer(name, regexp, printer)
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/prompt.py b/gdb/bin/x86_64/data-directory/python/gdb/prompt.py
new file mode 100644
index 0000000..15f4a1d
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/prompt.py
@@ -0,0 +1,148 @@
+# Extended prompt utilities.
+# Copyright (C) 2011-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+""" Extended prompt library functions."""
+
+import gdb
+import os
+
+def _prompt_pwd(ignore):
+ "The current working directory."
+ return os.getcwd()
+
+def _prompt_object_attr(func, what, attr, nattr):
+ """Internal worker for fetching GDB attributes."""
+ if attr is None:
+ attr = nattr
+ try:
+ obj = func()
+ except gdb.error:
+ return '' % what
+ if hasattr(obj, attr):
+ result = getattr(obj, attr)
+ if callable(result):
+ result = result()
+ return result
+ else:
+ return '' % (attr, what)
+
+def _prompt_frame(attr):
+ "The selected frame; an argument names a frame parameter."
+ return _prompt_object_attr(gdb.selected_frame, 'frame', attr, 'name')
+
+def _prompt_thread(attr):
+ "The selected thread; an argument names a thread parameter."
+ return _prompt_object_attr(gdb.selected_thread, 'thread', attr, 'num')
+
+def _prompt_version(attr):
+ "The version of GDB."
+ return gdb.VERSION
+
+def _prompt_esc(attr):
+ "The ESC character."
+ return '\033'
+
+def _prompt_bs(attr):
+ "A backslash."
+ return '\\'
+
+def _prompt_n(attr):
+ "A newline."
+ return '\n'
+
+def _prompt_r(attr):
+ "A carriage return."
+ return '\r'
+
+def _prompt_param(attr):
+ "A parameter's value; the argument names the parameter."
+ return gdb.parameter(attr)
+
+def _prompt_noprint_begin(attr):
+ "Begins a sequence of non-printing characters."
+ return '\001'
+
+def _prompt_noprint_end(attr):
+ "Ends a sequence of non-printing characters."
+ return '\002'
+
+prompt_substitutions = {
+ 'e': _prompt_esc,
+ '\\': _prompt_bs,
+ 'n': _prompt_n,
+ 'r': _prompt_r,
+ 'v': _prompt_version,
+ 'w': _prompt_pwd,
+ 'f': _prompt_frame,
+ 't': _prompt_thread,
+ 'p': _prompt_param,
+ '[': _prompt_noprint_begin,
+ ']': _prompt_noprint_end
+}
+
+def prompt_help():
+ """Generate help dynamically from the __doc__ strings of attribute
+ functions."""
+
+ result = ''
+ keys = sorted (prompt_substitutions.keys())
+ for key in keys:
+ result += ' \\%s\t%s\n' % (key, prompt_substitutions[key].__doc__)
+ result += """
+A substitution can be used in a simple form, like "\\f".
+An argument can also be passed to it, like "\\f{name}".
+The meaning of the argument depends on the particular substitution."""
+ return result
+
+def substitute_prompt(prompt):
+ "Perform substitutions on PROMPT."
+
+ result = ''
+ plen = len(prompt)
+ i = 0
+ while i < plen:
+ if prompt[i] == '\\':
+ i = i + 1
+ if i >= plen:
+ break
+ cmdch = prompt[i]
+
+ if cmdch in prompt_substitutions:
+ cmd = prompt_substitutions[cmdch]
+
+ if i + 1 < plen and prompt[i + 1] == '{':
+ j = i + 1
+ while j < plen and prompt[j] != '}':
+ j = j + 1
+ # Just ignore formatting errors.
+ if j >= plen or prompt[j] != '}':
+ arg = None
+ else:
+ arg = prompt[i + 2 : j]
+ i = j
+ else:
+ arg = None
+ result += str(cmd(arg))
+ else:
+ # Unrecognized escapes are turned into the escaped
+ # character itself.
+ result += prompt[i]
+ else:
+ result += prompt[i]
+
+ i = i + 1
+
+ return result
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/types.py b/gdb/bin/x86_64/data-directory/python/gdb/types.py
new file mode 100644
index 0000000..c22e8a9
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/types.py
@@ -0,0 +1,176 @@
+# Type utilities.
+# Copyright (C) 2010-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Utilities for working with gdb.Types."""
+
+import gdb
+
+
+def get_basic_type(type_):
+ """Return the "basic" type of a type.
+
+ Arguments:
+ type_: The type to reduce to its basic type.
+
+ Returns:
+ type_ with const/volatile is stripped away,
+ and typedefs/references converted to the underlying type.
+ """
+
+ while (type_.code == gdb.TYPE_CODE_REF or
+ type_.code == gdb.TYPE_CODE_TYPEDEF):
+ if type_.code == gdb.TYPE_CODE_REF:
+ type_ = type_.target()
+ else:
+ type_ = type_.strip_typedefs()
+ return type_.unqualified()
+
+
+def has_field(type_, field):
+ """Return True if a type has the specified field.
+
+ Arguments:
+ type_: The type to examine.
+ It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION.
+ field: The name of the field to look up.
+
+ Returns:
+ True if the field is present either in type_ or any baseclass.
+
+ Raises:
+ TypeError: The type is not a struct or union.
+ """
+
+ type_ = get_basic_type(type_)
+ if (type_.code != gdb.TYPE_CODE_STRUCT and
+ type_.code != gdb.TYPE_CODE_UNION):
+ raise TypeError("not a struct or union")
+ for f in type_.fields():
+ if f.is_base_class:
+ if has_field(f.type, field):
+ return True
+ else:
+ # NOTE: f.name could be None
+ if f.name == field:
+ return True
+ return False
+
+
+def make_enum_dict(enum_type):
+ """Return a dictionary from a program's enum type.
+
+ Arguments:
+ enum_type: The enum to compute the dictionary for.
+
+ Returns:
+ The dictionary of the enum.
+
+ Raises:
+ TypeError: The type is not an enum.
+ """
+
+ if enum_type.code != gdb.TYPE_CODE_ENUM:
+ raise TypeError("not an enum type")
+ enum_dict = {}
+ for field in enum_type.fields():
+ # The enum's value is stored in "enumval".
+ enum_dict[field.name] = field.enumval
+ return enum_dict
+
+
+def deep_items (type_):
+ """Return an iterator that recursively traverses anonymous fields.
+
+ Arguments:
+ type_: The type to traverse. It should be one of
+ gdb.TYPE_CODE_STRUCT or gdb.TYPE_CODE_UNION.
+
+ Returns:
+ an iterator similar to gdb.Type.iteritems(), i.e., it returns
+ pairs of key, value, but for any anonymous struct or union
+ field that field is traversed recursively, depth-first.
+ """
+ for k, v in type_.iteritems ():
+ if k:
+ yield k, v
+ else:
+ for i in deep_items (v.type):
+ yield i
+
+class TypePrinter(object):
+ """The base class for type printers.
+
+ Instances of this type can be used to substitute type names during
+ 'ptype'.
+
+ A type printer must have at least 'name' and 'enabled' attributes,
+ and supply an 'instantiate' method.
+
+ The 'instantiate' method must either return None, or return an
+ object which has a 'recognize' method. This method must accept a
+ gdb.Type argument and either return None, meaning that the type
+ was not recognized, or a string naming the type.
+ """
+
+ def __init__(self, name):
+ self.name = name
+ self.enabled = True
+
+ def instantiate(self):
+ return None
+
+# Helper function for computing the list of type recognizers.
+def _get_some_type_recognizers(result, plist):
+ for printer in plist:
+ if printer.enabled:
+ inst = printer.instantiate()
+ if inst is not None:
+ result.append(inst)
+ return None
+
+def get_type_recognizers():
+ "Return a list of the enabled type recognizers for the current context."
+ result = []
+
+ # First try the objfiles.
+ for objfile in gdb.objfiles():
+ _get_some_type_recognizers(result, objfile.type_printers)
+ # Now try the program space.
+ _get_some_type_recognizers(result, gdb.current_progspace().type_printers)
+ # Finally, globals.
+ _get_some_type_recognizers(result, gdb.type_printers)
+
+ return result
+
+def apply_type_recognizers(recognizers, type_obj):
+ """Apply the given list of type recognizers to the type TYPE_OBJ.
+ If any recognizer in the list recognizes TYPE_OBJ, returns the name
+ given by the recognizer. Otherwise, this returns None."""
+ for r in recognizers:
+ result = r.recognize(type_obj)
+ if result is not None:
+ return result
+ return None
+
+def register_type_printer(locus, printer):
+ """Register a type printer.
+ PRINTER is the type printer instance.
+ LOCUS is either an objfile, a program space, or None, indicating
+ global registration."""
+
+ if locus is None:
+ locus = gdb
+ locus.type_printers.insert(0, printer)
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/unwinder.py b/gdb/bin/x86_64/data-directory/python/gdb/unwinder.py
new file mode 100644
index 0000000..14b2758
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/unwinder.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Unwinder class and register_unwinder function."""
+
+import gdb
+
+
+class Unwinder(object):
+ """Base class (or a template) for frame unwinders written in Python.
+
+ An unwinder has a single method __call__ and the attributes
+ described below.
+
+ Attributes:
+ name: The name of the unwinder.
+ enabled: A boolean indicating whether the unwinder is enabled.
+ """
+
+ def __init__(self, name):
+ """Constructor.
+
+ Args:
+ name: An identifying name for the unwinder.
+ """
+ self.name = name
+ self.enabled = True
+
+ def __call__(self, pending_frame):
+ """GDB calls this method to unwind a frame.
+
+ Arguments:
+ pending_frame: gdb.PendingFrame instance.
+
+ Returns:
+ gdb.UnwindInfo instance.
+ """
+ raise NotImplementedError("Unwinder __call__.")
+
+
+def register_unwinder(locus, unwinder, replace=False):
+ """Register unwinder in given locus.
+
+ The unwinder is prepended to the locus's unwinders list. Unwinder
+ name should be unique.
+
+ Arguments:
+ locus: Either an objfile, progspace, or None (in which case
+ the unwinder is registered globally).
+ unwinder: An object of a gdb.Unwinder subclass
+ replace: If True, replaces existing unwinder with the same name.
+ Otherwise, raises exception if unwinder with the same
+ name already exists.
+
+ Returns:
+ Nothing.
+
+ Raises:
+ RuntimeError: Unwinder name is not unique
+ TypeError: Bad locus type
+ """
+ if locus is None:
+ if gdb.parameter("verbose"):
+ gdb.write("Registering global %s unwinder ...\n" % unwinder.name)
+ locus = gdb
+ elif isinstance(locus, gdb.Objfile) or isinstance(locus, gdb.Progspace):
+ if gdb.parameter("verbose"):
+ gdb.write("Registering %s unwinder for %s ...\n" %
+ (unwinder.name, locus.filename))
+ else:
+ raise TypeError("locus should be gdb.Objfile or gdb.Progspace or None")
+
+ i = 0
+ for needle in locus.frame_unwinders:
+ if needle.name == unwinder.name:
+ if replace:
+ del locus.frame_unwinders[i]
+ else:
+ raise RuntimeError("Unwinder %s already exists." %
+ unwinder.name)
+ i += 1
+ locus.frame_unwinders.insert(0, unwinder)
diff --git a/gdb/bin/x86_64/data-directory/python/gdb/xmethod.py b/gdb/bin/x86_64/data-directory/python/gdb/xmethod.py
new file mode 100644
index 0000000..aa0cf0a
--- /dev/null
+++ b/gdb/bin/x86_64/data-directory/python/gdb/xmethod.py
@@ -0,0 +1,275 @@
+# Python side of the support for xmethods.
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""Utilities for defining xmethods"""
+
+import gdb
+import re
+import sys
+
+
+if sys.version_info[0] > 2:
+ # Python 3 removed basestring and long
+ basestring = str
+ long = int
+
+
+class XMethod(object):
+ """Base class (or a template) for an xmethod description.
+
+ Currently, the description requires only the 'name' and 'enabled'
+ attributes. Description objects are managed by 'XMethodMatcher'
+ objects (see below). Note that this is only a template for the
+ interface of the XMethodMatcher.methods objects. One could use
+ this class or choose to use an object which supports this exact same
+ interface. Also, an XMethodMatcher can choose not use it 'methods'
+ attribute. In such cases this class (or an equivalent) is not used.
+
+ Attributes:
+ name: The name of the xmethod.
+ enabled: A boolean indicating if the xmethod is enabled.
+ """
+
+ def __init__(self, name):
+ self.name = name
+ self.enabled = True
+
+
+class XMethodMatcher(object):
+ """Abstract base class for matching an xmethod.
+
+ When looking for xmethods, GDB invokes the `match' method of a
+ registered xmethod matcher to match the object type and method name.
+ The `match' method in concrete classes derived from this class should
+ return an `XMethodWorker' object, or a list of `XMethodWorker'
+ objects if there is a match (see below for 'XMethodWorker' class).
+
+ Attributes:
+ name: The name of the matcher.
+ enabled: A boolean indicating if the matcher is enabled.
+ methods: A sequence of objects of type 'XMethod', or objects
+ which have at least the attributes of an 'XMethod' object.
+ This list is used by the 'enable'/'disable'/'info' commands to
+ enable/disable/list the xmethods registered with GDB. See
+ the 'match' method below to know how this sequence is used.
+ This attribute is None if the matcher chooses not have any
+ xmethods managed by it.
+ """
+
+ def __init__(self, name):
+ """
+ Args:
+ name: An identifying name for the xmethod or the group of
+ xmethods returned by the `match' method.
+ """
+ self.name = name
+ self.enabled = True
+ self.methods = None
+
+ def match(self, class_type, method_name):
+ """Match class type and method name.
+
+ In derived classes, it should return an XMethodWorker object, or a
+ sequence of 'XMethodWorker' objects. Only those xmethod workers
+ whose corresponding 'XMethod' descriptor object is enabled should be
+ returned.
+
+ Args:
+ class_type: The class type (gdb.Type object) to match.
+ method_name: The name (string) of the method to match.
+ """
+ raise NotImplementedError("XMethodMatcher match")
+
+
+class XMethodWorker(object):
+ """Base class for all xmethod workers defined in Python.
+
+ An xmethod worker is an object which matches the method arguments, and
+ invokes the method when GDB wants it to. Internally, GDB first invokes the
+ 'get_arg_types' method to perform overload resolution. If GDB selects to
+ invoke this Python xmethod, then it invokes it via the overridden
+ '__call__' method. The 'get_result_type' method is used to implement
+ 'ptype' on the xmethod.
+
+ Derived classes should override the 'get_arg_types', 'get_result_type'
+ and '__call__' methods.
+ """
+
+ def get_arg_types(self):
+ """Return arguments types of an xmethod.
+
+ A sequence of gdb.Type objects corresponding to the arguments of the
+ xmethod are returned. If the xmethod takes no arguments, then 'None'
+ or an empty sequence is returned. If the xmethod takes only a single
+ argument, then a gdb.Type object or a sequence with a single gdb.Type
+ element is returned.
+ """
+ raise NotImplementedError("XMethodWorker get_arg_types")
+
+ def get_result_type(self, *args):
+ """Return the type of the result of the xmethod.
+
+ Args:
+ args: Arguments to the method. Each element of the tuple is a
+ gdb.Value object. The first element is the 'this' pointer
+ value. These are the same arguments passed to '__call__'.
+
+ Returns:
+ A gdb.Type object representing the type of the result of the
+ xmethod.
+ """
+ raise NotImplementedError("XMethodWorker get_result_type")
+
+ def __call__(self, *args):
+ """Invoke the xmethod.
+
+ Args:
+ args: Arguments to the method. Each element of the tuple is a
+ gdb.Value object. The first element is the 'this' pointer
+ value.
+
+ Returns:
+ A gdb.Value corresponding to the value returned by the xmethod.
+ Returns 'None' if the method does not return anything.
+ """
+ raise NotImplementedError("XMethodWorker __call__")
+
+
+class SimpleXMethodMatcher(XMethodMatcher):
+ """A utility class to implement simple xmethod mathers and workers.
+
+ See the __init__ method below for information on how instances of this
+ class can be used.
+
+ For simple classes and methods, one can choose to use this class. For
+ complex xmethods, which need to replace/implement template methods on
+ possibly template classes, one should implement their own xmethod
+ matchers and workers. See py-xmethods.py in testsuite/gdb.python
+ directory of the GDB source tree for examples.
+ """
+
+ class SimpleXMethodWorker(XMethodWorker):
+ def __init__(self, method_function, arg_types):
+ self._arg_types = arg_types
+ self._method_function = method_function
+
+ def get_arg_types(self):
+ return self._arg_types
+
+ def __call__(self, *args):
+ return self._method_function(*args)
+
+
+ def __init__(self, name, class_matcher, method_matcher, method_function,
+ *arg_types):
+ """
+ Args:
+ name: Name of the xmethod matcher.
+ class_matcher: A regular expression used to match the name of the
+ class whose method this xmethod is implementing/replacing.
+ method_matcher: A regular expression used to match the name of the
+ method this xmethod is implementing/replacing.
+ method_function: A Python callable which would be called via the
+ 'invoke' method of the worker returned by the objects of this
+ class. This callable should accept the object (*this) as the
+ first argument followed by the rest of the arguments to the
+ method. All arguments to this function should be gdb.Value
+ objects.
+ arg_types: The gdb.Type objects corresponding to the arguments that
+ this xmethod takes. It can be None, or an empty sequence,
+ or a single gdb.Type object, or a sequence of gdb.Type objects.
+ """
+ XMethodMatcher.__init__(self, name)
+ assert callable(method_function), (
+ "The 'method_function' argument to 'SimpleXMethodMatcher' "
+ "__init__ method should be a callable.")
+ self._method_function = method_function
+ self._class_matcher = class_matcher
+ self._method_matcher = method_matcher
+ self._arg_types = arg_types
+
+ def match(self, class_type, method_name):
+ cm = re.match(self._class_matcher, str(class_type.unqualified().tag))
+ mm = re.match(self._method_matcher, method_name)
+ if cm and mm:
+ return SimpleXMethodMatcher.SimpleXMethodWorker(
+ self._method_function, self._arg_types)
+
+
+# A helper function for register_xmethod_matcher which returns an error
+# object if MATCHER is not having the requisite attributes in the proper
+# format.
+
+def _validate_xmethod_matcher(matcher):
+ if not hasattr(matcher, "match"):
+ return TypeError("Xmethod matcher is missing method: match")
+ if not hasattr(matcher, "name"):
+ return TypeError("Xmethod matcher is missing attribute: name")
+ if not hasattr(matcher, "enabled"):
+ return TypeError("Xmethod matcher is missing attribute: enabled")
+ if not isinstance(matcher.name, basestring):
+ return TypeError("Attribute 'name' of xmethod matcher is not a "
+ "string")
+ if matcher.name.find(";") >= 0:
+ return ValueError("Xmethod matcher name cannot contain ';' in it")
+
+
+# A helper function for register_xmethod_matcher which looks up an
+# xmethod matcher with NAME in LOCUS. Returns the index of the xmethod
+# matcher in 'xmethods' sequence attribute of the LOCUS. If NAME is not
+# found in LOCUS, then -1 is returned.
+
+def _lookup_xmethod_matcher(locus, name):
+ for i in range(0, len(locus.xmethods)):
+ if locus.xmethods[i].name == name:
+ return i
+ return -1
+
+
+def register_xmethod_matcher(locus, matcher, replace=False):
+ """Registers a xmethod matcher MATCHER with a LOCUS.
+
+ Arguments:
+ locus: The locus in which the xmethods should be registered.
+ It can be 'None' to indicate that the xmethods should be
+ registered globally. Or, it could be a gdb.Objfile or a
+ gdb.Progspace object in which the xmethods should be
+ registered.
+ matcher: The xmethod matcher to register with the LOCUS. It
+ should be an instance of 'XMethodMatcher' class.
+ replace: If True, replace any existing xmethod matcher with the
+ same name in the locus. Otherwise, if a matcher with the same name
+ exists in the locus, raise an exception.
+ """
+ err = _validate_xmethod_matcher(matcher)
+ if err:
+ raise err
+ if not locus:
+ locus = gdb
+ if locus == gdb:
+ locus_name = "global"
+ else:
+ locus_name = locus.filename
+ index = _lookup_xmethod_matcher(locus, matcher.name)
+ if index >= 0:
+ if replace:
+ del locus.xmethods[index]
+ else:
+ raise RuntimeError("Xmethod matcher already registered with "
+ "%s: %s" % (locus_name, matcher.name))
+ if gdb.parameter("verbose"):
+ gdb.write("Registering xmethod matcher '%s' with %s' ...\n")
+ locus.xmethods.insert(0, matcher)
diff --git a/gdb/bin/x86_64/rocm-gdb b/gdb/bin/x86_64/rocm-gdb
new file mode 100755
index 0000000..05fbaa9
--- /dev/null
+++ b/gdb/bin/x86_64/rocm-gdb
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+# **************************************************************************************************/
+# ROCM-GDB Driver script
+#
+# Copyright (c) 2015-2016 ADVANCED MICRO DEVICES, INC. All rights reserved.
+# This file includes code originally published under
+#
+# Copyright (C) 1986-2014 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see . */
+# ****************************************************************************************************
+
+# A wrapper script to check for the environment and call amd-gdb.
+
+# Concatenate all arguments in a single variable
+GDB_ARGS="$*"
+
+# Get the full path to the script
+SOURCE="${BASH_SOURCE[0]}"
+ROOTDIR="$( dirname "$SOURCE" )"
+# If any part of the path is a symbolic link
+# replace it with the full path
+while [ -h "$SOURCE" ]; do
+ TARGET="$( readlink "$SOURCE" )"
+ if [[ $SOURCE == /* ]]; then
+ SOURCE="$TARGET"
+ else
+ DIR="$( dirname "$SOURCE" )"
+ SOURCE="$DIR/$TARGET"
+ fi
+ if [[ $SOURCE == \.* ]]; then
+ SOURCE="$ROOTDIR/$SOURCE"
+ fi
+done
+REALPATH="$( dirname "$SOURCE" )"
+
+IPCResourceCleanup()
+{
+ # Done in case GDB didnt exit cleanly
+ ipcrm -M 4567 2> /dev/null
+ ipcrm -M 1234 2> /dev/null
+ ipcrm -M 2222 2> /dev/null
+ ipcrm -M 1111 2> /dev/null
+
+ # The FIFO will be created in the same directory that the script is in
+ rm -f fifo-agent-w-gdb-r 2> /dev/null
+ rm -f fifo-gdb-w-agent-r 2> /dev/null
+
+ # remove temp_source file and any other left-over files
+ rm -f temp_source 2> /dev/null
+ rm -f .temp_source* 2> /dev/null
+ rm -f temp_isa 2> /dev/null
+ rm -f .temp_isa* 2> /dev/null
+ rm -f /tmp/debugger_isa_dump 2> /dev/null
+}
+
+IPCResourceCleanup
+
+# Enable SoftCP mode in the HSA runtime
+export HSA_EMULATE_AQL=1
+export HSA_TOOLS_LIB="libhsa-runtime-tools64.so.1 libAMDHSADebugAgent-x64.so"
+
+# Enable Finalizer's workaround to use code segment offsets for the isa line table
+export HSA_USE_OFFSETS_FOR_DWARF_CODE_ADDRESSES=1
+
+
+if [ ! -f $REALPATH/amd-gdb ]; then
+ echo amd-gdb executable not found in folder $REALPATH
+ exit -1
+fi
+
+# Add a possible path to amdhsacod
+export PATH=$PATH:'/opt/rocm/bin'
+
+# These flags will be used by libhsail
+export LIBHSAIL_OPTIONS_APPEND="-g -include-source"
+# This flag will be used by runtime to process the debug info when the brig module is added to create a program
+export PROGRAM_CREATE_OPTIONS_APPEND="-g"
+export PROGRAM_FINALIZE_OPTIONS_APPEND="-g -O0 -amd-reserved-num-vgprs=4 "
+
+# Set and export the LD_LIBRARY_PATH for gpudebugsdk
+# This assumes a specific directory structure with ROCm-gdb and gpudebugsdk folders are in the same directory
+SDK="gpudebugsdk"
+# If the user has specified the SDK path already, use that
+# otherwise look for the SDK folder relative to the rocm-gdb folder
+if [[ ! "$LD_LIBRARY_PATH" == *$SDK* ]]; then
+ for fileName in $( ls $REALPATH/../../.. ); do
+ if [[ "$fileName" == *$SDK* ]]; then
+ if [[ ! "$fileName" == *tar* ]]; then
+ export LD_LIBRARY_PATH=$REALPATH/../../../$fileName/lib/x86_64:${LD_LIBRARY_PATH}
+ fi
+ fi
+ done
+ if [[ ! "$LD_LIBRARY_PATH" == *$SDK* ]]; then
+ echo The $SDK folder cannot be found. Please use the directory structure shown in the README and make sure the $SDK folder is specified in the LD_LIBRARY_PATH environment variable.
+ exit -1
+ fi
+fi
+
+# Remove any stale FIFO files
+if [ -p fifo-agent-w-gdb-r ]; then
+ rm -f fifo-agent-w-gdb-r
+fi
+if [ -p fifo-gdb-w-agent-r ]; then
+ rm -f fifo-gdb-w-agent-r
+fi
+
+# Define a session ID, if logging is enabled by the user
+if [ -z "$ROCM_GDB_ENABLE_LOG" ]; then
+ export ROCM_GDB_DEBUG_SESSION_ID=""
+else
+ export ROCM_GDB_DEBUG_SESSION_ID=$$
+fi
+
+# We can now call gdb
+export ROCM_ENABLE_GDB=1
+
+$REALPATH/amd-gdb -data-directory $REALPATH/data-directory -iex "add-auto-load-safe-path $REALPATH" -ix $REALPATH/.gdbinit $GDB_ARGS
+# Capture GDB's return code to send to the terminal,
+# we are not interested in the subsequent IPC cleanup and logging return codes
+GDB_RETURN_CODE=$?
+
+#cp $REALPATH/amd-gdb $REALPATH/gdb
+#gdb --args $REALPATH/gdb -data-directory $REALPATH/data-directory $GDB_ARGS
+#GDB_RETURN_CODE=$?
+
+#valgrind --tool=memcheck --log-file=valgrind_log $REALPATH/amd-gdb -data-directory $REALPATH/data-directory -iex "add-auto-load-safe-path $REALPATH" -ix $REALPATH/.gdbinit $GDB_ARGS
+
+
+# Steps to run after amd-gdb exits
+unset ROCM_ENABLE_GDB
+
+# If the ROCM loggging variable was not defined, remove the gdb log
+# else save it with the session id
+if [ -z "$ROCM_GDB_ENABLE_LOG" ]; then
+ rm -f gdb.txt
+else
+ GDBLOGFILENAME=$ROCM_GDB_ENABLE_LOG"_rocm_gdb_log_"$ROCM_GDB_DEBUG_SESSION_ID
+
+ echo "GDB Log saved to " $GDBLOGFILENAME
+ mv gdb.txt $GDBLOGFILENAME 2> /dev/null
+fi
+
+# There is an issue with how we terminate gdb when we call quit
+#
+# Some internal ncurses state is getting messed up when we call the quit functionality twice in gdb
+# As a temporary workaround we use the below command
+# http://unix.stackexchange.com/questions/79684/fix-terminal-after-displaying-a-binary-file
+# This does not seem to clear the full terminal like the "reset" command and seems to have no other side effect
+#
+# If we want to clear the terminal of all previous OP, we should add "tput rs1"
+# tput and stty together seem to have the same functionality as reset
+stty sane 2> /dev/null
+
+IPCResourceCleanup
+
+# Return with GDB's return code
+exit $GDB_RETURN_CODE
diff --git a/gpudebugsdk/LICENSE.txt b/gpudebugsdk/LICENSE.txt
new file mode 100644
index 0000000..67f1a61
--- /dev/null
+++ b/gpudebugsdk/LICENSE.txt
@@ -0,0 +1,282 @@
+IMPORTANT-READ CAREFULLY: DO NOT INSTALL, COPY OR USE THE LICENSED MATERIALS
+(AS DEFINED BELOW), OR ANY PORTION THEREOF, (COLLECTIVELY “LICENSED
+MATERIALS”) UNTIL YOU HAVE CAREFULLY READ AND AGREED TO THE FOLLOWING TERMS
+AND CONDITIONS. THIS IS A LEGAL AGREEMENT (“AGREEMENT”) BETWEEN YOU (EITHER AN
+INDIVIDUAL OR AN ENTITY) (“YOU”) AND ADVANCED MICRO DEVICES, INC. (“AMD”).
+
+IF YOU DO NOT AGREE TO THE TERMS OF THIS AGREEMENT, DO NOT INSTALL, COPY OR
+USE THIS SOFTWARE. BY INSTALLING, COPYING OR USING THE LICENSED MATERIALS YOU
+AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT.
+
+1. DEFINITIONS.
+
+1.1 “Derivative Works” means any work, revision, modification or
+adaptation made to or derived from the Sample Code in whole or in part.
+
+1.2 “Documentation” means documentation, associated, included, or provided in
+connection with the Licensed Materials, or any portion thereof, including but
+not limited to information provided online, electronically, or as install
+scripts.
+
+1.3 “Free Software License” means an open source or other license that
+requires, as a condition of use, modification or distribution, that any
+resulting software must be (a) disclosed or distributed in source code form;
+(b) licensed for the purpose of making derivative works; or (c)
+redistributable at no charge.
+
+1.4 “Intellectual Property Rights” means all copyrights, trademarks, trade
+secrets, patents, mask works, and all related, similar, or other intellectual
+property rights recognized in any jurisdiction worldwide, including all
+applications and registrations with respect thereto.
+
+1.5 “Licensed Materials” means the Software Development Kits(s) including (a)
+Documentation; (b) Sample Code; (c) tools and utilities; and (d) Libraries.
+
+1.6 “Licensed Purpose” means the creation of Licensee Software that works with
+AMD hardware products.
+
+1.7 “Licensee Software” means any software developed or modified by You using
+the Licensed Materials, and which may include any Libraries and/or Derivative
+Works.
+
+1.8 “Libraries” means library files in the Licensed Materials that may be
+statically or dynamically linked into Licensee Software for the Licensed
+Purpose.
+
+1.9 “Object Code” means the machine readable form of the Licensed Software (as
+opposed to the human readable form of computer programming code) created by or
+for You by compiling the Source Code, or as delivered by AMD, including the
+object code version of any Derivative Work.
+
+1.10 “Sample Code” means the header files and Source Code identified within
+the Licensed Materials as sample code.
+
+1.11 “Source Code” means computer programming code in the human readable
+form and related system level documentation, including all associated
+comments, symbols and any procedural code such as job control language.
+
+2. LICENSE. Subject to the terms and conditions of this Agreement, AMD
+hereby grants You a non-exclusive, royalty-free, revocable, non-transferable,
+non-assignable limited copyright license solely for the Licensed Purpose, to:
+
+ a) install, use and copy the Licensed Materials internally at Your
+site(s);
+ b) create Derivative Works solely for internal use; and
+ c) distribute and sublicense the Object Code of the Sample Code,
+Derivative Works and Libraries as incorporated in Licensee Software to
+customers and end users (collectively, “Distribution Channel”) subject to
+an end user license agreement that meets the requirements in Section 3
+herein.
+
+3. END USER LICENSE AGREEMENT. Distribution of the Licensee Software by
+You and Your Distribution Channel will be pursuant to an enforceable end user
+license agreement (“End User License Agreement”) with terms and conditions
+that at a minimum are substantially similar to those set forth in Sections 4,
+15, 16 and 17 herein and the following provisions: (a) Licensee Software may
+not be transferred or duplicated (except for reasonable backup); (b) Licensee
+Software may not be reverse engineered, disassembled or de-compiled; (c) all
+warranties must be disclaimed and AMD’s liability must be limited as set forth
+in Section 11 herein; (d) the end user must comply fully with all relevant
+export laws and regulations of the United States and other applicable export
+and import laws; (e) the end user must be notified that the Licensee Software
+is subject to a restricted license and can only be used for the Licensed
+Purpose; and (f) AMD is a third party beneficiary of all End User License
+Agreements.
+
+4. RESTRICTIONS. Except for the limited copyright license expressly granted
+in Section 2 herein, You have no other rights in the Licensed Materials,
+whether express, implied, arising by estoppel or otherwise. Further
+restrictions regarding Your use of the Licensed Materials are set forth
+below. Except as expressly authorized herein, You may not:
+
+a) distribute, publish, display, sublicense, assign or otherwise transfer the
+Licensed Materials (except when built into the Licensee Software);
+b) decompile, reverse engineer, disassemble or otherwise reduce the Licensed
+Materials in Object Code to a human-perceivable form (except as expressly
+allowed by applicable law but then only to the limited extent of such law);
+c) alter or remove any copyright, trademark or patent notice(s) in the
+Licensed Materials;
+d) use the Licensed Materials to: (i) develop inventions directly derived
+from Confidential Information to seek patent protection; (ii) assist in the
+analysis of Your patents and patent applications; or (iii) modify Your
+existing patents or patent applications; or
+e) use the Licensed Materials in way that requires that the Licensed
+Materials or any portion thereof be licensed under a Free Software License.
+
+5. THIRD PARTY MATERIALS. Together with the Licensed Materials, AMD may
+include third party technologies (e.g. third party libraries) for which You
+must obtain licenses from parties other than AMD. You agree that AMD has not
+obtained or conveyed to You, and that You shall be responsible for obtaining,
+Intellectual Property Rights to use and/or distribute the applicable,
+underlying Intellectual Property Rights related to the third party
+technologies. These third party technologies are not licensed as part of the
+Licensed Materials and are not licensed under this Agreement.
+
+6. NOTICE REGARDING STANDARDS. AMD does not provide a license or sublicense
+to any Intellectual Property Rights relating to any standards, such as,
+including but not limited to any audio and/or video codec technologies such as
+MPEG-2, MPEG-3, MPEG-4; AVC/H.264; VC-1; and MP3 (collectively, the “Media
+Technologies”). For clarity, You will pay any royalties due for such third
+party technologies, which may include the Media Technologies that are owed as
+a result of AMD providing the Licensed Materials to You.
+
+7. OTHER AMD SOFTWARE COMPONENTS. The Licensed Materials may be accompanied
+by AMD software components (e.g. libraries, sample code) which are licensed to
+You under the terms and conditions of their respective licenses located in the
+directory with the software component.
+
+8. OWNERSHIP. The Licensed Materials including all Intellectual Property
+Rights therein are and remain the sole and exclusive property of AMD or its
+licensors, and You shall have no right, title or interest therein except as
+expressly set forth in this Agreement.
+
+9. FEEDBACK. You have no obligation to give AMD any suggestions, comments or
+other feedback (“Feedback”) relating to the Licensed Materials. However, AMD
+may use and include any Feedback that it receives from You to improve the
+Licensed Materials or other AMD products, software and technologies.
+Accordingly, for any Feedback You provide to AMD, You grant AMD and its
+affiliates and subsidiaries a worldwide, non-exclusive, irrevocable,
+royalty-free, fully paid up, perpetual license to, directly or indirectly,
+use, reproduce, license, sublicense, distribute, make, have made, sell and
+otherwise commercialize the Feedback in the Licensed Materials or other AMD
+products, software and technologies. You further agree not to provide any
+Feedback that (a) You know is subject to any Intellectual Property Rights of
+any third party or (b) is subject to license terms which seek to require any
+products incorporating or derived from such Feedback, or other AMD
+Intellectual Property, to be licensed to or otherwise shared with any third
+party.
+
+10. SUPPORT AND UPDATES. AMD is under no obligation to provide any kind of
+support under this Agreement. AMD may, in its sole discretion, provide to You
+updates to the Licensed Materials, and such updates will be covered as
+Licensed Materials under this Agreement.
+
+11. WARRANTY DISCLAIMER, LIMITATION OF LIABILITY AND INDEMNIFICATION.
+11.1 Disclaimer OF Warranty. THE LICENSED MATERIALS ARE PROVIDED "AS IS"
+WITHOUT WARRANTY OF ANY KIND. AMD DISCLAIMS ALL WARRANTIES, EXPRESS, IMPLIED,
+OR STATUTORY, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT,
+THAT THE LICENSED MATERIALS WILL RUN UNINTERRUPTED OR ERROR-FREE OR THOSE
+ARISING FROM CUSTOM OF TRADE OR COURSE OF USAGE. THE ENTIRE RISK ASSOCIATED
+WITH THE USE OF THE LICENSED MATERIALS IS ASSUMED BY YOU. Some jurisdictions
+do not allow the exclusion of implied warranties, so the above exclusion may
+not apply to You.
+
+11.2 Limitation of Liability. AMD AND ITS LICENSORS WILL NOT, UNDER ANY
+CIRCUMSTANCES BE LIABLE TO YOU FOR ANY PUNITIVE, DIRECT, INCIDENTAL, INDIRECT,
+SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM USE OF THE LICENSED MATERIALS OR
+THIS AGREEMENT EVEN IF AMD AND ITS LICENSORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES. In no event shall AMD's total liability to You
+for all damages, losses, and causes of action (whether in contract, tort
+(including negligence) or otherwise) exceed the amount of $100 USD.
+
+11.3 Indemnification. You agree to defend, indemnify and hold harmless AMD
+and its licensors, and any of their directors, officers, employees, affiliates
+or agents from and against any and all loss, damage, liability and other
+expenses (including reasonable attorneys' fees), resulting from a) Your use,
+distribution or sublicense of the Licensed Materials, b) violation of the
+terms and conditions of this Agreement by You or any sublicensee, or c) for
+failure by You to obtain and comply with third party licenses that may be
+required pursuant to Sections 5, 6 and 7 herein.
+
+12. CONFIDENTIALITY. You shall protect the Licensed Materials and any
+information related thereto (collectively, “Confidential Information”) by
+using the same degree of care, but no less than a reasonable degree of care,
+to prevent the unauthorized use, dissemination or publication of the
+Confidential Information as You use to protect your own confidential
+information of a like nature. You shall not disclose any Confidential
+Information disclosed hereunder to any third party and shall limit disclosure
+of Confidential Information to only those of its employees and contractors
+with a need to know and who are bound by confidentiality obligations with You
+at least as restrictive as those contained in this Agreement. You shall be
+responsible for your employees and contractors adherence to the terms of this
+Agreement. You may disclose Confidential Information in accordance with a
+judicial or other governmental order, provided that You either (a) give AMD
+reasonable notice prior to such disclosure to allow AMD a reasonable
+opportunity to seek a protective order or equivalent or (b) obtain written
+assurance from the applicable judicial or governmental entity that it will
+afford the Confidential Information the highest level of protection afforded
+under applicable law or regulation.
+
+13. TERMINATION AND SURVIVAL. AMD may terminate the Agreement immediately upon
+the breach by You or any sublicensee of any of the terms of the Agreement. You
+may terminate the Agreement upon written notice to AMD and destruction of the
+Licensed Materials You accessed hereunder. The termination of this Agreement
+shall: (i) immediately result in the termination of all rights granted by You
+to distribute the Licensed Materials and Derivative Works through multiple
+tiers of distribution under Section 2; and (ii) have no effect on any
+sublicenses previously granted by You to end users under Section 2(c) and
+which are compliant with all terms and conditions of this Agreement, which
+sublicenses shall survive in accordance with their terms. Upon termination or
+expiration of this Agreement, You will cease using and destroy or return to
+AMD all copies of the Confidential Information, including but not limited to
+the Licensed Materials. Upon termination or expiration of this Agreement, all
+provisions survive except for Section 2.
+
+14. EXPORT RESTRICTIONS. You shall adhere to all applicable U.S., European,
+and other export laws, including but not limited to the U.S. Export
+Administration Regulations (“EAR”) (15 C.F.R Sections 730-774), and E.U.
+Council Regulation (EC) No 428/2009 of 5 May 2009. Further, pursuant to
+Section 740.6 of the EAR, You hereby certify that, except pursuant to a
+license granted by the United States Department of Commerce Bureau of Industry
+and Security or as otherwise permitted pursuant to a License Exception under
+the EAR, You will not (1) export, re-export or release to a national of a
+country in Country Groups D:1, E:1 or E:2 any restricted technology, software,
+or source code it receives from AMD, or (2) export to Country Groups D:1, E:1
+or E:2 the direct product of such technology or software, if such foreign
+produced direct product is subject to national security controls as identified
+on the Commerce Control List (currently found in Supplement 1 to Part 774 of
+EAR). For the most current Country Group listings, or for additional
+information about the EAR or Your obligations under those regulations, please
+refer to the U.S. Bureau of Industry and Security’s website at
+http://www.bis.doc.gov/.
+
+15. GOVERNMENT END USERS. The Licensed Materials are provided with “RESTRICTED
+RIGHTS.” Use, duplication or disclosure by the Government is subject to
+restrictions as set forth in FAR 52.227-14 and DFAR 252.227-7013, et seq., or
+its successor. Use of the Licensed Materials by the Government constitutes
+acknowledgment of AMD’s proprietary rights in it.
+
+16. GOVERNING LAW. This Agreement is made under and shall be construed
+according to the laws of the State of Texas, excluding conflicts of law
+rules. Each party submits to the jurisdiction of the state and federal courts
+of Travis County and the Western District of Texas for the purposes of this
+Agreement. You acknowledge that Your breach of this Agreement may cause
+irreparable damage and You agree that AMD shall be entitled to seek injunctive
+relief under this Agreement, as well as such further relief as may be granted
+by a court of competent jurisdiction.
+
+17. GENERAL PROVISIONS. You may not assign this Agreement without the
+prior written consent of AMD and any assignment without such consent will be
+null and void. This Agreement may be executed in multiple counterparts, each
+of which shall constitute a signed original. Any facsimile or electronic
+image of this Agreement or writing referenced herein shall be valid and
+acceptable for all purposes as if it were an original. The Parties do not
+intend that any agency or partnership relationship be created between them by
+this Agreement. Each provision of this Agreement shall be interpreted in such
+a manner as to be effective and valid under applicable law. However, in the
+event that any provision of this Agreement becomes or is declared
+unenforceable by any court of competent jurisdiction, such provision shall be
+deemed deleted and the remainder of this Agreement shall remain in full force
+and effect.
+
+18. ENTIRE AGREEMENT. This Agreement sets forth the entire agreement and
+understanding between the Parties with respect to the Licensed Materials and
+supersedes and merges all prior oral and written agreements, discussions and
+understandings between them regarding the subject matter of this Agreement.
+No waiver or modification of any provision of this Agreement shall be binding
+unless made in writing and signed by an authorized representative of each Party.
+
+If You agree to abide by the terms and conditions of this Agreement, please
+press “Accept.” If You do not agree to abide by the terms and conditions of
+this Agreement, press “Decline” and You may not use or access the Materials.
+
+
+
+
+
+
+
+
+
+
diff --git a/gpudebugsdk/bin/x86_64/amd-debug-lock b/gpudebugsdk/bin/x86_64/amd-debug-lock
new file mode 100755
index 0000000..dc1186a
Binary files /dev/null and b/gpudebugsdk/bin/x86_64/amd-debug-lock differ
diff --git a/gpudebugsdk/bin/x86_64/rocm-gdb-debug-flags.sh b/gpudebugsdk/bin/x86_64/rocm-gdb-debug-flags.sh
new file mode 100755
index 0000000..ab272ff
--- /dev/null
+++ b/gpudebugsdk/bin/x86_64/rocm-gdb-debug-flags.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
+#
+# This script sets up the environment variables required for compiling HCC-HSAIL
+# applications in debug mode.
+# This script does not support the HCC-LC (HCC-Lightning Compiler)
+#
+# This script should be called as "source rocm-gdb-debug-flags.sh"
+# before calling any compile scripts or Makefiles. Alternatively these
+# variables can be added to the debug options in any HCC application's
+# build
+export HCC_NOISA=1
+export LIBHSAIL_OPTIONS_APPEND=' -g -include-source'
+export PROGRAM_FINALIZE_OPTIONS_APPEND=' -g -O0 -amd-reserved-num-vgprs=4'
+export PROGRAM_CREATE_OPTIONS_APPEND=' -g'
diff --git a/gpudebugsdk/include/AMDGPUDebug.h b/gpudebugsdk/include/AMDGPUDebug.h
new file mode 100644
index 0000000..e115213
--- /dev/null
+++ b/gpudebugsdk/include/AMDGPUDebug.h
@@ -0,0 +1,973 @@
+/************************************************************************************//**
+** Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.
+**
+** \author AMD Developer Tools
+** \file
+** \brief The AMD GPU Kernel Debugging API to implement device kernel debugging on
+** AMD Graphics Core Next (GCN) GPUs.
+**
+** \mainpage Introduction
+** \section Overview
+** This document describes a set of interfaces which can be used
+** by debugger or application developers to incorporate GPU kernel debugging
+** functionality into their debugger or application running on AMD Graphics Core Next
+** GPUs (or APUs).
+**
+** The AMD GPU Kernel Debugging API has been designed to hide the multiple
+** driver API specific implementations and the internal architecture of a
+** particular GPU device. It has evolved starting from a minimal set of GPU debugging
+** APIs that can be currently supported by AMD GPUs and software stacks. As more
+** GPU debug features are implemented and validated, the API will evolve further.
+** It is still a work-in-progress.
+**
+** For HSA, this API together with the AMD HSA binary interface, AMD HSA debug info and
+** AMD HSA API and dispatch interception mechanism form the AMD HSA GPU Debugging
+** Architecture.
+** Refer to the "AMD HSA GPU Debugging Architecture" document for more information.
+**
+** \section Assumptions
+** The AMD GPU Kernel Debugging API is an "in-process" debug API. That is, the API
+** must be called from the same process address space as the program being debugged
+** and will have direct access to all process resources. No OS provided inter-process
+** debug mechanisms are required, but it should be reasonably straightforward for
+** tool developers to create a client/server remote debugging model through the
+** introduction of a simple communication protocol.
+**
+** To inject these kernel debugging API calls into the debugged application process
+** address space, the API and kernel dispatch interception mechanism provided through
+** amd_hsa_tools_interfaces.h can be used.
+**
+** \section Requirements
+** For HSA:
+** 1. AMD Kaveri and Carrizo APUs
+** 2. HSA Runtime and HSAIL 1.0 Final
+**
+****************************************************************************************/
+#ifndef AMDGPUDEBUG_H_
+#define AMDGPUDEBUG_H_
+
+#include /* for size_t type */
+#include /* for uintXX_t type */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ #if defined(HWDBG_EXPORTS)
+ /** Export symbols when building the library on windows. */
+ #define HWDBG_API_ENTRY __declspec(dllexport)
+ #else
+ /** No symbol export when used by the library user on windows. */
+ #define HWDBG_API_ENTRY __declspec(dllimport)
+ #endif
+ /** The API calling convention on windows. */
+ #define HWDBG_API_CALL __cdecl
+#else
+ #if __GNUC__ >= 4
+ /** Use symbol visibility control supported by GCC 4.x and newer. */
+ #define HWDBG_API_ENTRY __attribute__ ((visibility("default")))
+ #else
+ /** No symbol visibility control for GCC older than 4.0. */
+ #define HWDBG_API_ENTRY
+ #endif
+ /** The API calling convention on linux. **/
+ #define HWDBG_API_CALL
+#endif
+
+/** The AMD GPU Debug API major version. */
+#define AMDGPUDEBUG_VERSION_MAJOR 1
+/** The AMD GPU Debug API minor version. */
+#define AMDGPUDEBUG_VERSION_MINOR 3
+/** The AMD GPU Debug API build number. */
+#define AMDGPUDEBUG_VERSION_BUILD 5
+
+/** The maximum number of lanes in a wavefront for the GPU device. */
+#define HWDBG_WAVEFRONT_SIZE 64
+
+
+/********************************* ENUMERATIONS *********************************/
+
+/** The enumeration values of the possible return status from the provided API. */
+/** \warning Not all the enum values are supported currently */
+typedef enum
+{
+ /** the API was executed successfully */
+ HWDBG_STATUS_SUCCESS = 0x0,
+
+ /** a debugger internal error occurred */
+ HWDBG_STATUS_ERROR = 0x01,
+
+ /** the GPU device does not support debugging */
+ HWDBG_STATUS_DEVICE_ERROR = 0x02,
+
+ /** the driver is not compatible with the API */
+ HWDBG_STATUS_DRIVER_ERROR = 0x03,
+
+ /** a duplicate breakpoint is detected */
+ HWDBG_STATUS_DUPLICATE_BREAKPOINT = 0x04,
+
+ /** invalid address alignment was provided */
+ HWDBG_STATUS_INVALID_ADDRESS_ALIGNMENT = 0x05,
+
+ /** an invalid debug context handle was provided */
+ HWDBG_STATUS_INVALID_HANDLE = 0x06,
+
+ /** invalid input arguments were provided */
+ HWDBG_STATUS_INVALID_PARAMETER = 0x07,
+
+ /** expected a non NULL input argument */
+ HWDBG_STATUS_NULL_POINTER = 0x08,
+
+ /** out of range address was provided */
+ HWDBG_STATUS_OUT_OF_RANGE_ADDRESS = 0x09,
+
+ /** failed to allocate memory */
+ HWDBG_STATUS_OUT_OF_MEMORY = 0x0A,
+
+ /** ran out of hardware resources (for data breakpoints) */
+ HWDBG_STATUS_OUT_OF_RESOURCES = 0x0B,
+
+ /** started debugging on more than one application process */
+ HWDBG_STATUS_REGISTRATION_ERROR = 0x0C,
+
+ /** an undefined operation was detected (i.e. an incorrect call order) */
+ HWDBG_STATUS_UNDEFINED = 0x0D,
+
+ /** the API has not been implemented */
+ HWDBG_STATUS_UNSUPPORTED = 0x0E,
+
+ /** HwDbgInit has not been called */
+ HWDBG_STATUS_NOT_INITIALIZED = 0x0F,
+
+ /** The debug context was created with unsupported behavior flags for the API*/
+ HWDBG_STATUS_INVALID_BEHAVIOR_STATE = 0x10
+
+} HwDbgStatus;
+
+/** The list of debugger commands for the HwDbgContinueEvent API to advance to the
+ next state in the GPU debug engine. **/
+typedef enum
+{
+ HWDBG_COMMAND_CONTINUE = 0x0, /**< resume the device execution */
+} HwDbgCommand;
+
+/** The enumeration values of possible driver software stacks supported by the library */
+typedef enum
+{
+ HWDBG_API_HSA = 0x0, /**< the library is built for HSA software stack */
+} HwDbgAPIType;
+
+/** The enumeration values of possible breakpoint types supported by the library. */
+/** \warning This is not yet supported */
+typedef enum
+{
+ HWDBG_BREAKPOINT_TYPE_NONE = 0x0, /**< no breakpoint type */
+ HWDBG_BREAKPOINT_TYPE_CODE = 0x1, /**< instruction-based breakpoint type */
+ HWDBG_BREAKPOINT_TYPE_DATA = 0x2, /**< memory-based or data breakpoint type */
+} HwDbgBreakpointType;
+
+/** The enumeration values of possible event types returned by the HwDbgWaitForEvent
+ API. */
+typedef enum
+{
+ HWDBG_EVENT_INVALID = 0x0, /**< an invalid event */
+ HWDBG_EVENT_TIMEOUT = 0x1, /**< has reached the user timeout value */
+ HWDBG_EVENT_POST_BREAKPOINT = 0x2, /**< has reached a breakpoint */
+ HWDBG_EVENT_END_DEBUGGING = 0x3, /**< has completed kernel execution */
+} HwDbgEventType;
+
+/** The list of possible access modes of data breakpoints supported. */
+/** \warning This is not yet supported */
+typedef enum
+{
+ /** read operations only */
+ HWDBG_DATABREAKPOINT_MODE_READ = 0x1,
+
+ /** write or atomic operations only */
+ HWDBG_DATABREAKPOINT_MODE_NONREAD = 0x2,
+
+ /** atomic operations only */
+ HWDBG_DATABREAKPOINT_MODE_ATOMIC = 0x4,
+
+ /** read, write or atomic operations */
+ HWDBG_DATABREAKPOINT_MODE_ALL = 0x7,
+} HwDbgDataBreakpointMode;
+
+
+/************************************ TYPEDEFS **********************************/
+
+/** The code location type (in bytes). */
+typedef uint64_t HwDbgCodeAddress;
+
+/** The hardware wavefront location type. */
+typedef uint32_t HwDbgWavefrontAddress;
+
+/** A unique handle for the kernel debug context (returned by HwDbgBeginDebugContext). */
+typedef void* HwDbgContextHandle;
+
+/** A unique handle for a code breakpoint (returned by HwDbgCreateCodeBreakpoint). */
+typedef void* HwDbgCodeBreakpointHandle;
+
+/** A unique handle for a data breakpoint (returned by HwDbgCreateDataBreakpoint). */
+/** \warning This is not yet supported */
+typedef void* HwDbgDataBreakpointHandle;
+
+
+/*********************************** STRUCTURES *********************************/
+
+/** A three dimensional type, used by work-group and work-item ids. */
+typedef struct
+{
+ uint32_t x; /**< x dimension */
+ uint32_t y; /**< y dimension */
+ uint32_t z; /**< z dimension */
+} HwDbgDim3;
+
+/** A structure to hold all the info required to create a single data breakpoint. */
+/** \warning This is not yet supported */
+typedef struct
+{
+ /** the relevant mode for the data breakpoint */
+ HwDbgDataBreakpointMode dataBreakpointMode;
+
+ /** the size of data in bytes being watched */
+ uint64_t dataSize;
+
+ /** the memory address to be watched */
+ void* pAddress;
+} HwDbgDataBreakpointInfo;
+
+/** A structure to hold the active wave info returned by HwDbgGetActiveWavefronts API */
+typedef struct
+{
+ /** the work-group id */
+ HwDbgDim3 workGroupId;
+
+ /** the work-item id (local id within a work-group) */
+ HwDbgDim3 workItemId[HWDBG_WAVEFRONT_SIZE];
+
+ /** the execution mask of the work-items */
+ uint64_t executionMask;
+
+ /** the hardware wavefront slot address (not unique for a dispatch) */
+ HwDbgWavefrontAddress wavefrontAddress;
+
+ /** the byte offset in the ISA binary for the wavefront */
+ HwDbgCodeAddress codeAddress;
+
+ /** the data breakpoint handle */
+ /** \warning This is not yet supported */
+ HwDbgDataBreakpointHandle dataBreakpointHandle;
+
+ /** the type of breakpoint that was signaled */
+ /** \warning This is not yet supported */
+ HwDbgBreakpointType breakpointType;
+
+ /** additional data that can be returned */
+ void* pOtherData;
+} HwDbgWavefrontInfo;
+
+/** The enumerated bitfield values of supported behavior, the flags can be used internally to optimize behavior */
+typedef enum
+{
+ /** Default flag, used to debug GPU dispatches */
+ HWDBG_BEHAVIOR_NONE = 0x00,
+
+ /** Disable GPU dispatch debugging.
+ ** However this behavior mode allows extraction of kernel binaries and breakpoint management.
+ ** Allowed API calls are HwDbg[Begin or End]DebugContext, HwDbgGetKernelBinary,
+ ** HwDbg[*CodeBreakpoint*] and HwDbg[*DataBreakpoint*] */
+ HWDBG_BEHAVIOR_DISABLE_DISPATCH_DEBUGGING = 0x01
+
+}HwDbgBehaviorType;
+
+/** A structure to hold the device state as an input to the HwDbgBeginDebugContext */
+typedef struct
+{
+ /** set to hsa_agent_t.handle from the pre-dispatch callback function */
+ void* pDevice;
+
+ /** set to hsa_kernel_dispatch_packet_t* from the pre-dispatch callback function */
+ void* pPacket;
+
+ /** set to packet_id from the pre-dispatch callback function */
+ /** \warning This is not yet supported */
+ uint64_t packetId;
+
+ /** flags that the control the behavior of the debug context */
+ uint32_t behaviorFlags;
+} HwDbgState;
+
+
+/********************************** DIAGNOSTIC LOGGING *********************************/
+
+/** The enumerated bitfield values of supported logging message types */
+typedef enum
+{
+ HWDBG_LOG_TYPE_NONE = 0x00, /**< do not register for any message */
+ HWDBG_LOG_TYPE_ASSERT = 0x01, /**< register for assert messages */
+ HWDBG_LOG_TYPE_ERROR = 0x02, /**< register for error messages */
+ HWDBG_LOG_TYPE_TRACE = 0x04, /**< register for trace messages */
+ HWDBG_LOG_TYPE_MESSAGE = 0x08, /**< register for generic messages */
+ HWDBG_LOG_TYPE_ALL = 0x0f /**< register for all messages */
+} HwDbgLogType;
+
+/************************************************************************************//**
+** The user provided logging callback function to be registered.
+**
+** This function will be called when the message with the type registered by the user
+** is generated by the library.
+**
+** \param[in] pUserData The pointer specified by the user during registration
+** \param[in] type The type of log message being passed back
+** \param[in] pMessage The log message being passed back
+****************************************************************************************/
+typedef void (*HwDbgLoggingCallback)( void* pUserData,
+ const HwDbgLogType type,
+ const char* const pMessage);
+
+/************************************************************************************//**
+** Register a logging callback function.
+**
+** Extra diagnostics output about the operation of the AMD GPU Debug API may
+** be enabled by registering a client callback function through this API.
+**
+** This function can be called prior to a HwDbgInit call.
+**
+** \param[in] types specifies the logging message types to be registered
+** (a combination of HwDbgLogType enum value)
+** \param[in] pCallback specifies the logging callback function
+** Set to a callback function function to enable logging
+** Set to NULL to disable logging
+** \param[in] pUserData specifies a pointer to data that can be accessed by the
+** user specified logging callback function
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS If the callback can be set successfully
+** \retval HWDBG_STATUS_ERROR If an error is encountered
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgSetLoggingCallback(uint32_t types,
+ HwDbgLoggingCallback pCallback,
+ void* pUserData);
+
+
+/***************************** LIBRARY VERSION AND TYPE ********************************/
+
+/************************************************************************************//**
+** Retrieve the library version (major, minor and build) number.
+**
+** This function can be called prior to a HwDbgInit call.
+**
+** \param[out] pVersionMajorOut returns the API version major number
+** \param[out] pVersionMinorOut returns API version minor number
+** \param[out] pVersionBuildOut returns API build number
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_NULL_POINTER If an input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API is not yet implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetAPIVersion(uint32_t* pVersionMajorOut,
+ uint32_t* pVersionMinorOut,
+ uint32_t* pVersionBuildOut);
+
+/************************************************************************************//**
+** Retrieve the driver API type of the loaded library.
+**
+** This function can be called prior to a HwDbgInit call.
+**
+** \param[out] pAPITypeOut returns the API type of the library
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API is not yet implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetAPIType(HwDbgAPIType* pAPITypeOut);
+
+
+/*********************** GPU DEBUG INITIALIZATION AND SHUTDOWN *************************/
+
+/************************************************************************************//**
+** Initialize the GPU debug engine.
+**
+** This function should be called right after the debugged process starts.
+** For hsa, this is in the HSA Runtime's OnLoad callback.
+**
+** \param[in] pApiTable Used by HSA: Pass in the pointer to the hsa api table
+** provided by the HSA Runtime's OnLoad callback.
+** Can be NULL (won't support full DBE functionality).
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If called multiple times without a
+** corresponding HwDbgShutDown
+** \retval HWDBG_STATUS_OUT_OF_MEMORY If fail to allocate necessary memory
+**
+** \see HwDbgShutDown
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgInit(void* pApiTable);
+
+/************************************************************************************//**
+** Shut down the GPU debug engine.
+**
+** This function should be called before the debugged process ends.
+** For hsa, this should be called right before calling the hsa_shut_down API.
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called without a corresponding HwDbgInit
+**
+** \see HwDbgInit
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgShutDown();
+
+/************************************************************************************//**
+** Mark the start debugging of a kernel dispatch.
+**
+** This function should be called right before the execution of the kernel
+** to be debugged (such as within the pre-dispatch callback function).
+** Only one kernel dispatch should be between HwDbgBeginDebugContext and
+** HwDbgEndDebugContext.
+** Only one process can be debugged at a time in the system.
+**
+** \param[in] state specifies the input debug state
+** \param[out] pDebugContextOut returns the handle that identifies the particular
+** kernel debug context
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_OUT_OF_MEMORY If fail to allocate necessary memory
+** \retval HWDBG_STATUS_REGISTRATION_ERROR If more than 1 debug process is detected
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgEndDebugContext
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgBeginDebugContext(const HwDbgState state,
+ HwDbgContextHandle* pDebugContextOut);
+
+/************************************************************************************//**
+** Mark the end debugging of a kernel dispatch.
+**
+** This function must be called after the kernel has complete execution.
+** Only one kernel dispatch should be between HwDbgBeginDebugContext and
+** HwDbgEndDebugContext.
+** Only one process can be debugged at a time in the system.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API.
+** If it is NULL, then all sessions in flight
+** will be terminated and deleted
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_INVALID_HANDLE If hDebugContext is an invalid handle
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNDEFINED If kernel execution has not yet completed
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgBeginDebugContext
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgEndDebugContext(HwDbgContextHandle hDebugContext);
+
+
+/******************************* GPU EVENT LOOP PROCESSING *****************************/
+
+/************************************************************************************//**
+** Wait on a debug event from the GPU device.
+**
+** This is a synchronous function that will not return until it receives an
+** event or reaches the specified timeout value.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] timeout specifies how long to wait in milliseconds
+** before timing out
+** \param[out] pEventTypeOut The resulting event type
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If an input argument is NULL
+** \retval HWDBG_STATUS_UNDEFINED If the kernel has completed execution
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgContinueEvent
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgWaitForEvent( HwDbgContextHandle hDebugContext,
+ const uint32_t timeout,
+ HwDbgEventType* pEventTypeOut);
+
+/************************************************************************************//**
+** Continue to the next operation (resume device execution, run to the next
+** breakpoint).
+**
+** This is performed after receiving an event from HwDbgWaitForEvent.
+** This is an asynchronous call, subsequent calls are undefined until
+** the next HwDbgWaitEvent call.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] command specifies the debugger command to execute next
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_INVALID_PARAMETER If the command argument is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNDEFINED If the kernel has completed execution
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgWaitForEvent
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgContinueEvent( HwDbgContextHandle hDebugContext,
+ const HwDbgCommand command);
+
+
+/************************ GPU INSTRUCTION-BASED BREAKPOINT CONTROL *********************/
+
+/************************************************************************************//**
+** Create a breakpoint at a specified program counter.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] codeAddress specifies the byte offset into the ISA binary
+** indicating where to set the breakpoint.
+** This has to be 4-byte aligned for AMD GPUs.
+** \param[out] pBreakpointOut returns the handle of the newly created instruction-based
+** breakpoint. It is valid for use anywhere after creation.
+** However, it is undefined to change the breakpoint
+** state outside the HwDbgWaitForEvent/
+** HwDbgContinueEvent pair associated with the
+** kernel dispatch that the breakpoint was created for
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If the codeAddress is invalid (not 4-byte
+** aligned or out of range) or has been
+** inserted before
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgDeleteCodeBreakpoint, HwDbgDeleteAllCodeBreakpoints,
+** HwDbgGetCodeBreakpointAddress
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgCreateCodeBreakpoint( HwDbgContextHandle hDebugContext,
+ const HwDbgCodeAddress codeAddress,
+ HwDbgCodeBreakpointHandle* pBreakpointOut);
+
+/************************************************************************************//**
+** Delete a instruction-based breakpoint.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] hBreakpoint specifies the breakpoint handle. The handle is
+** invalid after this call and may be
+** returned in future calls to HwDbgCreateCodeBreakpoint
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If breakpoint handle is invalid or
+** contains an invalid code address
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateCodeBreakpoint, HwDbgDeleteAllCodeBreakpoints,
+** HwDbgGetCodeBreakpointAddress
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgDeleteCodeBreakpoint(HwDbgContextHandle hDebugContext,
+ HwDbgCodeBreakpointHandle hBreakpoint);
+
+/************************************************************************************//**
+** Delete all instruction-based breakpoints.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateCodeBreakpoint, HwDbgDeleteCodeBreakpoint,
+** HwDbgGetCodeBreakpointAddress
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgDeleteAllCodeBreakpoints(HwDbgContextHandle hDebugContext);
+
+/************************************************************************************//**
+** Retrieve the code location from an instruction-based breakpoint handle.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] hBreakpoint specifies the breakpoint handle
+** \param[out] pCodeAddressOut returns the code address (program counter)
+**
+** \return HwDbgStatus
+** \return HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateCodeBreakpoint, HwDbgDeleteCodeBreakpoint,
+** HwDbgDeleteAllCodeBreakpoints
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetCodeBreakpointAddress(const HwDbgContextHandle hDebugContext,
+ const HwDbgCodeBreakpointHandle hBreakpoint,
+ HwDbgCodeAddress* pCodeAddressOut);
+
+
+/******************************* KERNEL BINARY INFORMATION *****************************/
+
+/************************************************************************************//**
+** Retrieve the kernel binary (in ELF) of the kernel dispatch.
+**
+** For HSA, the binary is the loaded and relocated code object.
+** The binary contains the debugging information (in DWARF) from high level source
+** to ISA (can be multiple level of DWARFs such as one DWARF to represent the mapping
+** from a high level kernel source to BRIG and another DWARF to represent the mapping
+** from BRIG to ISA).
+** \note Refer to the following two documentation for more information:
+** 1. HSA Application Binary Interface - AMD GPU Architecture document for the
+** complete ABI.
+** 2. HSA Debug Information document for the HSA DWARF extension
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[out] ppBinaryOut returns a pointer to a buffer containing the
+** binary kernel code object
+** The lifetime of the buffer is within the
+** debug context (i.e. after HwDbgBeginDebugContext call
+** until the HwDbgEndDebugContext call)
+** \param[out] pBinarySizeOut returns the binary size in bytes
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_DRIVER_ERROR If the retrieved kernel binary is NULL
+** or the binary size is 0
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetKernelBinary(const HwDbgContextHandle hDebugContext,
+ const void** ppBinaryOut,
+ size_t* pBinarySizeOut);
+
+/************************************************************************************//**
+** Retrieve the dispatched kernel name.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[out] ppKernelNameOut returns a pointer to a null-terminated character array
+** The lifetime of the character array is within the
+** debug context (i.e. after HwDbgBeginDebugContext call
+** until the HwDbgEndDebugContext call)
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_DRIVER_ERROR If the retrieved kernel name is NULL
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetDispatchedKernelName(const HwDbgContextHandle hDebugContext,
+ const char** ppKernelNameOut);
+
+
+/****************************** GPU DEVICE STATE INSPECTION ****************************/
+
+/************************************************************************************//**
+** Retrieve the list of active wavefronts for the kernel dispatch in the GPU device.
+**
+** Must only be called after receiving a HWDBG_EVENT_POST_BREAKPOINT event from
+** HwDbgWaitForEvent API.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[out] ppWavefrontInfoOut returns a pointer to HwDbgWavefrontInfo structures.
+** It contains the work-group ids, work-
+** item ids, code adress, etc for each wavefront
+** \param[out] pNumWavefrontsOut returns the number of active wavefronts
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the ppWaveInfoOut is NULL
+** \retval HWDBG_STATUS_UNDEFINED If it is called after not receiving
+** a HWDBG_EVENT_POST_BREAKPOINT event
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetActiveWavefronts(const HwDbgContextHandle hDebugContext,
+ const HwDbgWavefrontInfo** ppWavefrontInfoOut,
+ uint32_t* pNumWavefrontsOut);
+
+/************************************************************************************//**
+** Read data from a memory region.
+**
+** \warning Only private memory region (IMR_Scratch = 1) is currently supported.
+**
+** Must only be called after receiving a HWDBG_EVENT_POST_BREAKPOINT event from
+** HwDbgWaitForEvent API.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] memoryRegion specifies the target memory region to read from.
+** This should be set to an enum value stored in
+** DW_AT_HSA_isa_memory_region attribute of
+** DW_TAG_variable tag in ISA DWARF.
+** \param[in] workGroupId specifies the work-group id of interest (from
+** HwDbgGetActiveWavefronts)
+** \param[in] workItemId specifies the work-item id of interest (from
+** HwDbgGetActiveWavefronts)
+** \param[in] offset specifies a byte offset for the logical
+** location that should be retrieved. On GPU,
+** this must be a multiple of 4 bytes
+** (align on a DWORD boundary)
+** \param[in] numBytesToRead specifies the number of bytes to retrieve
+** On GPU, this must be a multiple of 4 bytes
+** \param[out] pMemOut returns a pointer to a memory chunk of at least
+** "numBytesToRead" bytes long
+** \param[out] pNumBytesOut returns the number of bytes written into pMemOut
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If an input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgReadMemory(const HwDbgContextHandle hDebugContext,
+ const uint32_t memoryRegion,
+ const HwDbgDim3 workGroupId,
+ const HwDbgDim3 workItemId,
+ const size_t offset,
+ const size_t numBytesToRead,
+ void* pMemOut,
+ size_t* pNumBytesOut);
+
+
+/***************************** GPU DEVICE EXECUTION CONTROL ****************************/
+
+/************************************************************************************//**
+** Break kernel execution of all active wavefronts for a kernel dispatch.
+**
+** Can be called at any time after a HwDbgBeginDebugContext call.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgBreakAll(const HwDbgContextHandle hDebugContext);
+
+/************************************************************************************//**
+** Terminate the kernel dispatch execution.
+**
+** Can be called at any time after a HwDbgBeginDebugContext call.
+** Can be called multiple times to terminate a large kernel dispatch.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgKillAll(const HwDbgContextHandle hDebugContext);
+
+
+/***************************** GPU DATA BREAKPOINT CONTROL *****************************/
+
+/************************************************************************************//**
+** Create a data breakpoint.
+**
+** \warning This is not yet supported
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] breakpointInfo specifies the structure containing information
+** where to set the data breakpoint
+** \param[out] pDataBreakpointOut returns the handle of the newly created data
+** breakpoint. It is valid for use anywhere after
+** creation. However, it is undefined to change the
+** breakpoint state outside the HwDbgWaitForEvent/
+** HwDbgContinueEvent pair associated with the
+** shader dispatch that the breakpoint was created
+** for
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument or address is NULL
+** \retval HWDBG_STATUS_OUT_OF_RESOURCES If cannot be created due to hw limits
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgDeleteDataBreakpoint, HwDbgDeleteAllDataBreakpoints,
+** HwDbgGetDataBreakpointInfo
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgCreateDataBreakpoint( HwDbgContextHandle hDebugContext,
+ const HwDbgDataBreakpointInfo breakpointInfo,
+ HwDbgDataBreakpointHandle* pDataBreakpointOut);
+
+/************************************************************************************//**
+** Delete a data breakpoint.
+**
+** \warning This is not yet supported
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] hDataBreakpoint specifies the data breakpoint handle. The handle is
+** invalid after this call and may be returned in
+** future calls to HwDbgCreateCodeBreakpoint
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateDataBreakpoint, HwDbgDeleteAllDataBreakpoints,
+** HwDbgGetDataBreakpointInfo
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgDeleteDataBreakpoint(HwDbgContextHandle hDebugContext,
+ HwDbgDataBreakpointHandle hDataBreakpoint);
+
+/************************************************************************************//**
+** Delete all data breakpoints.
+**
+** \warning This is not yet supported
+**
+** After this call, all data breakpoint handles created prior for the debug
+** context will be invalid.
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+**
+** \return HwDbgStatus
+** \retval HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateDataBreakpoint, HwDbgDeleteDataBreakpoint,
+** HwDbgGetDataBreakpointInfo
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgDeleteAllDataBreakpoints(HwDbgContextHandle hDebugContext);
+
+/************************************************************************************//**
+** Retrieve the data breakpoint information from a data breakpoint handle.
+**
+** \warning This is not yet supported
+**
+** \param[in] hDebugContext specifies the context handle received
+** from HwDbgBeginDebugContext API
+** \param[in] hDataBreakpoint specifies the data breakpoint handle
+** \param[out] pDataBreakpointInfoOut returns a structure containing
+** information of the data breakpoint
+** \retval HWDBG_STATUS_NOT_INITIALIZED If called prior to a HwDbgInit call
+**
+** \return HwDbgStatus
+** \return HWDBG_STATUS_SUCCESS On success
+** \retval HWDBG_STATUS_ERROR If an internal error occurs
+** (check the log output for details)
+** \retval HWDBG_STATUS_INVALID_BEHAVIOR If the context behavior flags are invalid
+** \retval HWDBG_STATUS_INVALID_HANDLE If the input hDebugContext is invalid
+** \retval HWDBG_STATUS_NULL_POINTER If the input argument is NULL
+** \retval HWDBG_STATUS_UNSUPPORTED If the API has not been implemented
+**
+** \see HwDbgCreateDataBreakpoint, HwDbgDeleteDataBreakpoint,
+** HwDbgDeleteAllDataBreakpoints
+****************************************************************************************/
+extern HWDBG_API_ENTRY HwDbgStatus HWDBG_API_CALL
+HwDbgGetDataBreakpointInfo(const HwDbgContextHandle hDebugContext,
+ const HwDbgDataBreakpointHandle hDataBreakpoint,
+ HwDbgDataBreakpointInfo* pDataBreakpointInfoOut);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gpudebugsdk/include/FacilitiesInterface.h b/gpudebugsdk/include/FacilitiesInterface.h
new file mode 100644
index 0000000..2090c0c
--- /dev/null
+++ b/gpudebugsdk/include/FacilitiesInterface.h
@@ -0,0 +1,217 @@
+/************************************************************************************//**
+** Copyright (c) 2014-2015 Advanced Micro Devices, Inc. All rights reserved.
+**
+** \author AMD Developer Tools
+** \file
+** \brief A C interface for HSA debug info (dwarf)
+****************************************************************************************/
+#ifndef FACILITIES_INTERFACE_H_
+#define FACILITIES_INTERFACE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************************************/
+/* HwDbgInfo types: */
+/************************************************************/
+/* A debug info handle */
+typedef const void* HwDbgInfo_debug;
+/* A (HLC) code location - file and line number */
+typedef const void* HwDbgInfo_code_location;
+/* A single frame in a call stack */
+typedef const void* HwDbgInfo_frame_context;
+/* A line number */
+typedef unsigned long long HwDbgInfo_linenum;
+/* Debug information for a variable, parameter, or member */
+typedef const void* HwDbgInfo_variable;
+/* A memory or instruction address */
+typedef unsigned long long HwDbgInfo_addr;
+/* Error / success code (HWDBGINGO_E_*) */
+typedef unsigned int HwDbgInfo_err;
+/* Variable encoding (HWDBGINFO_VENC_*) */
+typedef unsigned int HwDbgInfo_encoding;
+/* Variable indirection (HWDBGINFO_VIND_*) */
+typedef unsigned int HwDbgInfo_indirection;
+/* Variable indirection detail (HWDBGINFO_VINDD_*) */
+typedef unsigned int HwDbgInfo_indirectiondetail;
+/* Variable location register (HWDBGINFO_VLOC_REG_* */
+typedef unsigned int HwDbgInfo_locreg;
+
+/***************/
+/* Error codes */
+/***************/
+/* Success */
+#define HWDBGINFO_E_SUCCESS 0
+/* Unexpected failure */
+#define HWDBGINFO_E_UNEXPECTED 1
+/* Invalid parameter */
+#define HWDBGINFO_E_PARAMETER 2
+/* Supplied output buffer is too small */
+#define HWDBGINFO_E_BUFFERTOOSMALL 3
+/* Cannot allocate enough memory */
+#define HWDBGINFO_E_OUTOFMEMORY 4
+/* Binary not found or is invalid */
+#define HWDBGINFO_E_NOBINARY 5
+/* Kernel cannot be identified */
+#define HWDBGINFO_E_NOKERNEL 6
+/* HL binary (BRIG DWARF) cannot be found */
+#define HWDBGINFO_E_NOHLBINARY 7
+/* LL binary (ISA DWARF) cannot be found */
+#define HWDBGINFO_E_NOLLBINARY 8
+/* Unexpected binary format */
+#define HWDBGINFO_E_BINARY 9
+/* Invalid HL (BRIG DWARF) debug information */
+#define HWDBGINFO_E_HLINFO 10
+/* Invalid LL (ISA DWARF) debug information */
+#define HWDBGINFO_E_LLINFO 11
+/* Requested information cannot be found */
+#define HWDBGINFO_E_NOTFOUND 12
+/* Requested constant information from a variable or vice-versa */
+#define HWDBGINFO_E_VARIABLEVALUETYPE 13
+/* Source code not available */
+#define HWDBGINFO_E_NOSOURCE 14
+
+/*********************/
+/* Variable encoding */
+/*********************/
+/* Pointer encoding (%p) */
+#define HWDBGINFO_VENC_POINTER 0
+/* Boolean encoding (T/F) */
+#define HWDBGINFO_VENC_BOOLEAN 1
+/* Floating-point encoding (%f/%e/%g) */
+#define HWDBGINFO_VENC_FLOAT 2
+/* Signed integer encoding (%d/%l/%ll) */
+#define HWDBGINFO_VENC_INTEGER 3
+/* Unsigned integer encoding (%u/%lu/%llu) */
+#define HWDBGINFO_VENC_UINTEGER 4
+/* Signed character encoding (%c) */
+#define HWDBGINFO_VENC_CHARACTER 5
+/* Unsigned character encoding (%uc) */
+#define HWDBGINFO_VENC_UCHARACTER 6
+/* No valid encoding (e.g. struct type) */
+#define HWDBGINFO_VENC_NONE 7
+
+/*************************/
+/* Variable indirection: */
+/*************************/
+/* Direct value (int) */
+#define HWDBGINFO_VIND_DIRECT 0
+/* Pointer value (int*) */
+#define HWDBGINFO_VIND_POINTER 1
+/* Reference value (int&) */
+#define HWDBGINFO_VIND_REFERENCE 2
+/* Array value (int[]) */
+#define HWDBGINFO_VIND_ARRAY 3
+
+/*********************************************************************/
+/* Variable indirection detail for AMD GPUs = pointer address space: */
+/*********************************************************************/
+/* Not a pointer */
+#define HWDBGINFO_VINDD_AMD_GPU_NOT_A_POINTER 0
+/* Pointer to global memory */
+#define HWDBGINFO_VINDD_AMD_GPU_GLOBAL_POINTER 1
+/* Pointer to region (GDS) memory */
+#define HWDBGINFO_VINDD_AMD_GPU_GDS_POINTER 2
+/* Pointer to local (LDS) memory */
+#define HWDBGINFO_VINDD_AMD_GPU_LDS_POINTER 3
+/* Pointer to private memory */
+#define HWDBGINFO_VINDD_AMD_GPU_PRIVATE_POINTER 4
+/* Pointer to const global memory */
+#define HWDBGINFO_VINDD_AMD_GPU_CONSTANT_POINTER 5
+/* Undefined / uninitialized */
+#define HWDBGINFO_VINDD_AMD_GPU_UNKNOWN_POINTER 6
+
+/************************************/
+/* Variable location register type: */
+/************************************/
+/* Value is located in a register */
+#define HWDBGINFO_VLOC_REG_REGISTER 0
+/* Value is located at a stack offset */
+#define HWDBGINFO_VLOC_REG_STACK 1
+/* Variable located at pure address */
+#define HWDBGINFO_VLOC_REG_NONE 2
+/* Undefined / uninitialized */
+#define HWDBGINFO_VLOC_REG_UNINIT 3
+
+/*******************/
+/* Initialization: */
+/*******************/
+/* Create a HwDbgInfo_debug from a single- or two- level binary */
+HwDbgInfo_debug hwdbginfo_init_and_identify_binary(const void* bin, size_t bin_size, HwDbgInfo_err* err);
+/* Create a HwDbgInfo_debug from a single level ELF/DWARF binary */
+HwDbgInfo_debug hwdbginfo_init_with_single_level_binary(const void* bin, size_t bin_size, HwDbgInfo_err* err);
+/* Create a HwDbgInfo_debug from an HSA 1.0 (May) binary */
+HwDbgInfo_debug hwdbginfo_init_with_hsa_1_0_binary(const void* bin, size_t bin_size, HwDbgInfo_err* err);
+/* Create a HwDbgInfo_debug directly from the BRIG DWARF container and ISA DWARF container */
+HwDbgInfo_debug hwdbginfo_init_with_two_binaries(const void* hl_bin, size_t hl_bin_size, const void* const ll_bin, size_t ll_bin_size, HwDbgInfo_err* err);
+
+/***********************/
+/* Binary data access: */
+/***********************/
+/* Get the HSAIL text source, if it was available */
+HwDbgInfo_err hwdbginfo_get_hsail_text(HwDbgInfo_debug dbg, const char** hsail_source, size_t* hsail_source_len);
+
+/*******************/
+/* Debug lines API */
+/*******************/
+/* Create a code location for queries */
+HwDbgInfo_code_location hwdbginfo_make_code_location(const char* file_name, HwDbgInfo_linenum line_num);
+/* Query a code location for its details */
+HwDbgInfo_err hwdbginfo_code_location_details(HwDbgInfo_code_location loc, HwDbgInfo_linenum* line_num, size_t buf_len, char* file_name, size_t* file_name_len);
+/* Query a frame context for its details */
+HwDbgInfo_err hwdbginfo_frame_context_details(HwDbgInfo_frame_context frm, HwDbgInfo_addr* pc, HwDbgInfo_addr* fp, HwDbgInfo_addr* mp, HwDbgInfo_code_location* loc, size_t buf_len, char* func_name, size_t* func_name_len);
+
+/* Translate a LL address to a HL line */
+HwDbgInfo_err hwdbginfo_addr_to_line(HwDbgInfo_debug dbg, HwDbgInfo_addr addr, HwDbgInfo_code_location* loc);
+/* Translate a HL line to LL address(es) */
+HwDbgInfo_err hwdbginfo_line_to_addrs(HwDbgInfo_debug dbg, HwDbgInfo_code_location loc, size_t buf_len, HwDbgInfo_addr* addrs, size_t* addr_count);
+/* Get the nearest legal (mapped) HL line */
+HwDbgInfo_err hwdbginfo_nearest_mapped_line(HwDbgInfo_debug dbg, HwDbgInfo_code_location base_line, HwDbgInfo_code_location* line);
+/* Get the nearest legal (mapped) LL address */
+HwDbgInfo_err hwdbginfo_nearest_mapped_addr(HwDbgInfo_debug dbg, HwDbgInfo_addr base_addr, HwDbgInfo_addr* addr);
+/* Get first legal (mapped) HL filepath */
+HwDbgInfo_err hwdbginfo_first_file_name(HwDbgInfo_debug dbg, size_t buf_len, char* file_name, size_t* file_name_len);
+/* Get all legal (mapped) LL addresses */
+HwDbgInfo_err hwdbginfo_all_mapped_addrs(HwDbgInfo_debug dbg, size_t buf_len, HwDbgInfo_addr* addrs, size_t* addr_count);
+/* Get a LL address's virtual (inlined) call stack */
+HwDbgInfo_err hwdbginfo_addr_call_stack(HwDbgInfo_debug dbg, HwDbgInfo_addr start_addr, size_t buf_len, HwDbgInfo_frame_context* stack_frames, size_t* frame_count);
+/* Get all the addresses that can be the target of a step operation from a LL address */
+HwDbgInfo_err hwdbginfo_step_addresses(HwDbgInfo_debug dbg, HwDbgInfo_addr start_addr, bool step_out, size_t buf_len, HwDbgInfo_addr* addrs, size_t* addr_count);
+
+/******************/
+/* Debug info API */
+/******************/
+/* Query a variable / constant for its data */
+HwDbgInfo_err hwdbginfo_variable_data(HwDbgInfo_variable var, size_t name_buf_len, char* var_name, size_t* var_name_len, size_t type_name_buf_len, char* type_name, size_t* type_name_len, size_t* var_size, HwDbgInfo_encoding* encoding, bool* is_constant, bool* is_output);
+/* Query a variable for its data */
+HwDbgInfo_err hwdbginfo_variable_location(HwDbgInfo_variable var, HwDbgInfo_locreg* reg_type, unsigned int* reg_num, bool* deref_value, unsigned int* offset, unsigned int* resource, unsigned int* isa_memory_region, unsigned int* piece_offset, unsigned int* piece_size, int* const_add);
+/* Query a constant for its data */
+HwDbgInfo_err hwdbginfo_variable_const_value(HwDbgInfo_variable var, size_t buf_size, void* var_value);
+/* Query a variable for its indirection data */
+HwDbgInfo_err hwdbginfo_variable_indirection(HwDbgInfo_variable var, HwDbgInfo_indirection* var_indir, HwDbgInfo_indirectiondetail* var_indir_detail);
+/* Query a variable /constant for its members */
+HwDbgInfo_err hwdbginfo_variable_members(HwDbgInfo_variable var, size_t buf_len, HwDbgInfo_variable* members, size_t* member_count);
+/* Query a variable for its definition scope */
+HwDbgInfo_err hwdbginfo_variable_range(HwDbgInfo_variable var, HwDbgInfo_addr* loPC, HwDbgInfo_addr* hiPC);
+
+/* Get a (HL to LL) variable information by name */
+HwDbgInfo_variable hwdbginfo_variable(HwDbgInfo_debug dbg, HwDbgInfo_addr start_addr, bool current_scope_only, const char* var_name, HwDbgInfo_err* err);
+/* Get a LL variable information by name */
+HwDbgInfo_variable hwdbginfo_low_level_variable(HwDbgInfo_debug dbg, HwDbgInfo_addr start_addr, bool current_scope_only, const char* var_name, HwDbgInfo_err* err);
+/* Get all variables defined in the scope of a LL address */
+HwDbgInfo_err hwdbginfo_frame_variables(HwDbgInfo_debug dbg, HwDbgInfo_addr start_addr, int stack_depth, bool leaf_members, size_t buf_len, HwDbgInfo_variable* vars, size_t* var_count);
+
+/***************************/
+/* Release allocated data: */
+/***************************/
+void hwdbginfo_release_debug_info(HwDbgInfo_debug* dbg);
+void hwdbginfo_release_code_locations(HwDbgInfo_code_location* locs, size_t loc_count);
+void hwdbginfo_release_frame_contexts(HwDbgInfo_frame_context* frames, size_t frame_count);
+void hwdbginfo_release_variables(HwDbgInfo_debug dbg, HwDbgInfo_variable* vars, size_t var_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FACILITIES_INTERFACE_H_ */
diff --git a/gpudebugsdk/lib/x86_64/libAMDGPUDebugHSA-x64.so b/gpudebugsdk/lib/x86_64/libAMDGPUDebugHSA-x64.so
new file mode 100644
index 0000000..d4ec5c3
Binary files /dev/null and b/gpudebugsdk/lib/x86_64/libAMDGPUDebugHSA-x64.so differ
diff --git a/gpudebugsdk/lib/x86_64/libAMDHSADebugAgent-x64.so b/gpudebugsdk/lib/x86_64/libAMDHSADebugAgent-x64.so
new file mode 100755
index 0000000..0782e4c
Binary files /dev/null and b/gpudebugsdk/lib/x86_64/libAMDHSADebugAgent-x64.so differ
diff --git a/gpudebugsdk/lib/x86_64/libAMDHwDbgFacilities-x64.so b/gpudebugsdk/lib/x86_64/libAMDHwDbgFacilities-x64.so
new file mode 100755
index 0000000..a1c7e2b
Binary files /dev/null and b/gpudebugsdk/lib/x86_64/libAMDHwDbgFacilities-x64.so differ
diff --git a/gpudebugsdk/samples/Common/HSAExtensionFinalizer.cpp b/gpudebugsdk/samples/Common/HSAExtensionFinalizer.cpp
new file mode 100644
index 0000000..c371417
--- /dev/null
+++ b/gpudebugsdk/samples/Common/HSAExtensionFinalizer.cpp
@@ -0,0 +1,84 @@
+//==============================================================================
+// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+/// \brief Data structure to keep HSA extension function pointer table, and call hsa_ext_* through it.
+//==============================================================================
+
+#include // memset
+#include
+
+#include "HSAExtensionFinalizer.h"
+
+namespace AMDT
+{
+ static bool GetExtensionTable(const uint16_t& extension, const uint16_t& major, const uint16_t minor, void* pTable)
+ {
+ bool isSupported = false;
+ hsa_status_t status = hsa_system_extension_supported(extension, major, minor, &isSupported);
+ if (HSA_STATUS_SUCCESS != status || true != isSupported)
+ {
+ if (HSA_STATUS_ERROR_NOT_INITIALIZED == status)
+ {
+ std::cerr << "HSA haven't initialized yet.\n";
+ return false;
+ }
+
+ if (HSA_STATUS_ERROR_INVALID_ARGUMENT == status)
+ {
+ std::cerr << "Extension 0x" << std::hex << extension << " is not a valid extension.\n";
+ std::cerr << std::dec;
+ return false;
+ }
+
+ std::cerr << "HSA Runtime " << major << "." << minor << " doesn't support this extension: " << extension << ".\n";
+ return false;
+ }
+
+ status = hsa_system_get_extension_table(extension, major, minor, pTable);
+ if (HSA_STATUS_SUCCESS != status)
+ {
+ std::cerr << "Get extension functions table failed. Extension: " << extension << "\n";
+ return false;
+ }
+
+ return true;
+ }
+
+ HSAFinalizer::HSAFinalizer() : m_pTable(nullptr)
+ {
+ }
+
+ HSAFinalizer::~HSAFinalizer()
+ {
+ if (nullptr != m_pTable)
+ {
+ delete m_pTable;
+ m_pTable = nullptr;
+ }
+ }
+
+ bool HSAFinalizer::GetExtensionTable(const uint16_t& major, const uint16_t& minor)
+ {
+ if (nullptr == m_pTable)
+ {
+ m_pTable = new HSAFinalizerTable;
+ if (nullptr == m_pTable)
+ {
+ std::cerr << "Cannot allocate Finalizer functions table.\n";
+ return false;
+ }
+ memset(m_pTable, 0, sizeof(m_pTable));
+ }
+
+ bool ret = AMDT::GetExtensionTable(HSA_EXTENSION_FINALIZER, major, minor, m_pTable);
+ if (!ret)
+ {
+ std::cerr << "Fail to get finalizer extension table.\n";
+ return false;
+ }
+
+ return true;
+ }
+}// namespace AMDT
diff --git a/gpudebugsdk/samples/Common/HSAExtensionFinalizer.h b/gpudebugsdk/samples/Common/HSAExtensionFinalizer.h
new file mode 100644
index 0000000..394cf83
--- /dev/null
+++ b/gpudebugsdk/samples/Common/HSAExtensionFinalizer.h
@@ -0,0 +1,75 @@
+//==============================================================================
+// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+/// \brief Data structure to keep HSA extension function pointer table, and call hsa_ext_* through it.
+//==============================================================================
+
+#ifndef HSA_EXTENSION_FINALIZER_H_
+#define HSA_EXTENSION_FINALIZER_H_
+
+#include
+
+#ifdef USE_EXISTING_FINALIZER_EXTENSION
+#include
+#else
+// \todo: Add these struct definitions here.
+struct hsa_ext_program_t;
+
+struct hsa_ext_program_info_t;
+
+struct hsa_ext_control_directives_t;
+
+struct BrigModuleHeader;
+typedef struct BrigModuleHeader* BrigModule_t;
+
+typedef BrigModule_t hsa_ext_module_t;
+#endif
+
+namespace AMDT
+{
+ class HSAFinalizer
+ {
+ private:
+ typedef struct HSAFinalizerTable
+ {
+ hsa_status_t(*hsa_ext_program_create)(
+ hsa_machine_model_t machine_model,
+ hsa_profile_t profile,
+ hsa_default_float_rounding_mode_t default_float_rounding_mode,
+ const char *options,
+ hsa_ext_program_t *program);
+
+ hsa_status_t(*hsa_ext_program_destroy)(hsa_ext_program_t program);
+
+ hsa_status_t(*hsa_ext_program_add_module)(hsa_ext_program_t program,
+ hsa_ext_module_t module);
+
+ hsa_status_t(*hsa_ext_program_iterate_modules)(
+ hsa_ext_program_t program,
+ hsa_status_t(*callback)(hsa_ext_program_t program,
+ hsa_ext_module_t module, void *data),
+ void *data);
+
+ hsa_status_t(*hsa_ext_program_get_info)(
+ hsa_ext_program_t program, hsa_ext_program_info_t attribute,
+ void *value);
+
+ hsa_status_t(*hsa_ext_program_finalize)(
+ hsa_ext_program_t program, hsa_isa_t isa, int32_t call_convention,
+ hsa_ext_control_directives_t control_directives, const char *options,
+ hsa_code_object_type_t code_object_type, hsa_code_object_t *code_object);
+ }HSAFinalizerTable;
+
+ public:
+ HSAFinalizer();
+ ~HSAFinalizer();
+
+ bool GetExtensionTable(const uint16_t& major, const uint16_t& minor);
+
+ HSAFinalizerTable* m_pTable;
+ };
+
+}// namespace AMDT
+#endif // HSA_EXTENSION_FINALIZER_H_
diff --git a/gpudebugsdk/samples/Common/HSAResourceManager.cpp b/gpudebugsdk/samples/Common/HSAResourceManager.cpp
new file mode 100644
index 0000000..136f09f
--- /dev/null
+++ b/gpudebugsdk/samples/Common/HSAResourceManager.cpp
@@ -0,0 +1,1472 @@
+//==============================================================================
+// Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+/// \brief HSA Runtime resource management class
+//==============================================================================
+/// \todo: Considering having an HSA application counter to keep track of how many applications are using HSA runtime.
+
+
+#include // _putenv_s, _dupenv_s on Windows, setenv, unsetenv on Linux.
+#include // memset, memcpy
+#include
+#include
+#include
+
+#define USE_EXISTING_FINALIZER_EXTENSION
+#include "HSAExtensionFinalizer.h"
+
+#include "HSAResourceManager.h"
+
+namespace AMDT
+{
+
+// Local struct to query gpu and cpu agent.
+typedef struct AgentList
+{
+ std::vector m_vecGPU;
+ std::vector m_vecCPU;
+} AgentList;
+
+static bool gs_bVerbosePrint = false;
+
+// Static local function declaration
+static bool InitAQL(hsa_kernel_dispatch_packet_t& aqlPacket);
+static hsa_status_t FindMemRegions_Callback(hsa_region_t region, void* data);
+static hsa_status_t QueryDevice_Callback(hsa_agent_t agent, void* pData);
+
+HSAFinalizer HSAResourceManager::ms_finalizer;
+uint16_t HSAResourceManager::ms_hsaCount = 0;
+AgentInfo HSAResourceManager::ms_gpu;
+AgentInfo HSAResourceManager::ms_cpu;
+bool HSAResourceManager::ms_hasRuntime = false;
+bool HSAResourceManager::ms_profilingEnabled = false;
+hsa_queue_t* HSAResourceManager::ms_pQueue = nullptr;
+
+// ------------------------------------- Public Functions -------------------------------------
+HSAResourceManager::HSAResourceManager()
+{
+ ms_hsaCount++;
+}
+
+HSAResourceManager::~HSAResourceManager()
+{
+ if (!CleanUp())
+ {
+ std::cerr << "Error in HSAResourceManager::~HSAResourceManager(): CleanUp() failed\n";
+ }
+
+ ms_hsaCount--;
+
+ if (0 == ms_hsaCount)
+ {
+ if (!HSAResourceManager::ShutDown())
+ {
+ std::cerr << "Error in HSAResourceManager::~HSAResourceManager(): ShutDown() failed\n";
+ }
+ }
+
+ //std::cout << "HSA resource management object remain: " << ms_hsaCount << "\n";
+
+}
+
+bool HSAResourceManager::InitRuntime(bool verbosePrint)
+{
+ bool ret = true;
+
+ if (!ms_hasRuntime)
+ {
+ hsa_status_t status = hsa_init();
+ ret = HSA_CHECK_STATUS(status);
+
+ if (true != ret)
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime(): Initialing HSA Runtime failed, exiting...\n";
+ status = hsa_shut_down();
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime(): Shutting down HSA Runtime failed.\n";
+ }
+ }
+
+ if (true != ms_finalizer.GetExtensionTable(1, 0))
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime(): Fail to get fianlizer extension table.\n";
+ ret &= false;
+ }
+
+ gs_bVerbosePrint = verbosePrint;
+ AgentList agentList; // Local agentList to get agents information
+ status = hsa_iterate_agents(QueryDevice_Callback, &agentList);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime() when querying all HSA devices.\n";
+ ret &= false;
+ }
+
+ // At least one GPU and one CPU should present
+ if (0 == agentList.m_vecGPU.size())
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime(): Can't find any GPU device.\n";
+ return false;
+ }
+
+ if (0 == agentList.m_vecCPU.size())
+ {
+ std::cerr << "Error in HSAResourceManager::InitRuntime(): Can't find any CPU device.\n";
+ return false;
+ }
+
+ // Choose the first agent from the agent vector.
+ ms_gpu = agentList.m_vecGPU[0];
+ ms_cpu = agentList.m_vecCPU[0];
+
+ // Find all memory region
+ status = hsa_agent_iterate_regions(ms_gpu.m_device, FindMemRegions_Callback, &ms_gpu);
+ ret &= HSA_CHECK_STATUS(status);
+
+ status = hsa_agent_iterate_regions(ms_cpu.m_device, FindMemRegions_Callback, &ms_cpu);
+ ret &= HSA_CHECK_STATUS(status);
+
+ ms_hasRuntime = true;
+ }
+
+ // Cache hsa version number
+ {
+ uint16_t major = 0;
+ uint16_t minor = 0;
+
+ if (true != GetHsaVersion(major, minor) || (0 == major && 0 == minor))
+ {
+ std::cerr << "Error in caching hsa version numbers.\n";
+ ret &= false;
+ }
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::PrintHsaVersion()
+{
+ uint16_t maj = 0;
+ uint16_t min = 0;
+
+ bool ret = GetHsaVersion(maj, min);
+
+ if (ret)
+ {
+ std::cout << "HSA version: " << maj << "." << min << "\n";
+ }
+ else
+ {
+ std::cerr << "Error in HSAResourceManager::PrintHsaVersion(): GetHsaVersion() failed.\n";
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::GetHsaVersion(uint16_t& major, uint16_t& minor)
+{
+ static uint16_t s_major = 0;
+ static uint16_t s_minor = 0;
+
+ if (0 != s_major || 0 != s_minor)
+ {
+ major = s_major;
+ minor = s_minor;
+ return true;
+ }
+
+ bool ret = true;
+ hsa_status_t status;
+
+ if (false == ms_hasRuntime)
+ {
+ status = hsa_init();
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Cannot init HSA runtime when querying HSA version.\n";
+ return false;
+ }
+ }
+
+ status = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MAJOR, &s_major);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ ret = false;
+ std::cerr << "Error in HSAResourceManager::GetHsaVersion(): Get HSA Major version number failed\n";
+ }
+
+ status = hsa_system_get_info(HSA_SYSTEM_INFO_VERSION_MINOR, &s_minor);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ ret = false;
+ std::cerr << "Error in HSAResourceManager::GetHsaVersion(): Get HSA Minor version number failed\n";
+ }
+
+ major = s_major;
+ minor = s_minor;
+
+ if (false == ms_hasRuntime)
+ {
+ status = hsa_shut_down();
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Cannot shutdown HSA runtime after querying HSA version.\n";
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::CreateDefaultQueue(bool enableKernelTimestamps)
+{
+ bool ret = true;
+
+ if (!DestroyQueue())
+ {
+ ret = false;
+ std::cerr << "Error in CreateDefaultQueue(): Destroying previous existing queue failed\n";
+ return ret;
+ }
+
+ uint32_t queueSize = 0;
+ hsa_status_t status = hsa_agent_get_info(ms_gpu.m_device, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &queueSize);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::CreateDefaultQueue(): Get queue max size failed.\n";
+ ret = false;
+ }
+
+ ms_gpu.m_maxQueueSize = queueSize;
+
+ status = hsa_queue_create(ms_gpu.m_device, // HSA agent
+ queueSize, // Number of packets the queue is expected to hold
+ HSA_QUEUE_TYPE_SINGLE, // Type of the queue
+ nullptr, // callback related to the queue. No specific requirement so it should be nullptr.
+ nullptr, // Data that is passed to callback. nullptr because no callback here.
+ UINT32_MAX, // Private segment size. Hint indicating the maximum expected usage per work item. No particular value required, so it should be UINT32_MAX
+ UINT32_MAX, // Group segment size. Also no particular value required.
+ &ms_pQueue); // The queue we want to create.
+
+ if (!HSA_CHECK_STATUS(status) || nullptr == ms_pQueue)
+ {
+ std::cerr << "Error in HSAResourceManager::CreateDefaultQueue(): Create queue failed.\n";
+ ret = false;
+ }
+
+ ms_profilingEnabled = enableKernelTimestamps;
+
+ if (enableKernelTimestamps)
+ {
+ status = hsa_amd_profiling_set_profiler_enabled(ms_pQueue, 1);
+
+ if (!HSA_CHECK_STATUS(status) || nullptr == ms_pQueue)
+ {
+ std::cerr << "Error in HSAResourceManager::CreateDefaultQueue(): hsa_amd_profiling_set_profiler_enabled() failed.\n";
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::SetQueue(hsa_queue_t* pQueue)
+{
+ bool ret = true;
+
+ if (!DestroyQueue())
+ {
+ ret = false;
+ std::cerr << "Error in SetQueue(): Destroying previous existing queue failed\n";
+ return ret;
+ }
+
+ ms_pQueue = pQueue;
+
+ return ret;
+};
+
+// Simple function to trim head and tail space of a string.
+static void TrimHeadAndTailSpace(std::string& s)
+{
+ if (s.size() == 0)
+ {
+ return;
+ }
+
+ std::size_t nsi = s.find_first_not_of(' ');
+ s.erase(0, nsi);
+
+ // if there are all spaces in the string
+ if (s.size() == 0)
+ {
+ return;
+ }
+
+ nsi = s.find_last_not_of(' ');
+ s.erase(nsi + 1);
+
+ return;
+}
+
+bool HSAResourceManager::CreateAQLPacketFromBrig(
+ const void* pBRIG,
+ const std::string& kernelSymbol,
+ const bool bCreateSignal,
+ hsa_kernel_dispatch_packet_t& aqlPacketOut,
+ const std::string& finalizerFlags,
+ const hsa_profile_t hsaProfile,
+ const std::size_t& kernargOffset)
+{
+
+ if (nullptr == pBRIG)
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): pBrig cannot be nullptr.\n";
+ return false;
+ }
+
+ hsa_executable_t hsaExecutable = { 0 };
+ hsa_code_object_t codeObj = {0};
+ {
+ // Simple string processing, current finalizer v3 is weak for option parameter parsing.
+ std::string fFlags = finalizerFlags;
+ TrimHeadAndTailSpace(fFlags);
+
+ if (!Finalize(pBRIG, fFlags, hsaProfile, hsaExecutable, codeObj))
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLPacketFromBrig(): Finalize() failed\n";
+ return false;
+ }
+
+ if (0 == hsaExecutable.handle)
+ {
+ std::cerr << "executable fail to create.\n";
+ }
+
+ m_aqlInfos[&aqlPacketOut].m_executable = hsaExecutable;
+
+ if (0 == codeObj.handle)
+ {
+ std::cerr << "codeObj fail to create.\n";
+ }
+
+ m_aqlInfos[&aqlPacketOut].m_codeObj = codeObj;
+
+ }
+
+ if (!CreateAQLFromExecutable(hsaExecutable, kernelSymbol, bCreateSignal, aqlPacketOut, kernargOffset)
+ || (0 == aqlPacketOut.kernel_object))
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLPacketFromBrig(): Failed to create aql from executable.\n";
+ return false;
+ }
+
+ if (bCreateSignal && 0 == m_aqlInfos[&aqlPacketOut].m_completionSignal.handle)
+ {
+ std::cerr << "completion_signal fail in aqlInfo.\n";
+ }
+
+ if (nullptr == m_aqlInfos[&aqlPacketOut].m_kernArgBuffer.GetArgBufferPointer())
+ {
+ std::cerr << "kernarg buffer fail in aqlInfo.\n";
+ }
+
+ return true;
+}
+
+bool HSAResourceManager::CreateAQLFromExecutable(
+ const hsa_executable_t& hsaExecutable,
+ const std::string& kernelSymbol,
+ const bool bCreateSignal,
+ hsa_kernel_dispatch_packet_t& aql,
+ const std::size_t& kernargOffset)
+{
+ if (0 == hsaExecutable.handle)
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLFromExecutable(): Input hsa_executable_t is invalid.\n";
+ return false;
+ }
+
+ bool ret = InitAQL(aql);
+
+ if (!ret)
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLFromExecutable(): InitAQL() failed.\n";
+ return false;
+ }
+
+ m_aqlInfos[&aql].m_executable = hsaExecutable;
+
+ // Get symbol handle
+ hsa_executable_symbol_t symbolOffset;
+ hsa_status_t status = hsa_executable_get_symbol(hsaExecutable, nullptr, kernelSymbol.c_str(), ms_gpu.m_device, 0, &symbolOffset);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLFromExecutable(): hsa_executable_get_symbol failed.\n";
+ return false;
+ }
+
+ // Get code object handle
+ status = hsa_executable_symbol_get_info(
+ symbolOffset, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &aql.kernel_object);
+
+ if (!HSA_CHECK_STATUS(status) || aql.kernel_object == 0)
+ {
+ std::cerr << "Error in HSAResourceManager::CreateAQLFromExecutable(): hsa_executable_symbol_get_info failed.\n";
+ return false;
+ }
+
+ // Get private segment size
+ status = hsa_executable_symbol_get_info(
+ symbolOffset, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, &aql.private_segment_size);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "hsa_executable_symbol_get_info: query private_segment_size failed.\n";
+ return false;
+ }
+
+ // Get kernel args size
+ std::size_t kernArgSize = 0;
+ status = hsa_executable_symbol_get_info(
+ symbolOffset, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE, &kernArgSize);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "hsa_executable_symbol_get_info: query kernelarg_segment_size failed.\n";
+ return false;
+ }
+
+ ret = m_aqlInfos[&aql].m_kernArgBuffer.AllocateBuffer(kernArgSize, kernargOffset);
+
+ if (!ret)
+ {
+ std::cerr << "Cannot allocate kernel arg buffer for aql.\n";
+ return false;
+ }
+
+ aql.kernarg_address = m_aqlInfos[&aql].m_kernArgBuffer.GetArgBufferPointer();
+
+ if (bCreateSignal)
+ {
+ ret = CreateSignal(aql.completion_signal);
+
+ if (!ret)
+ {
+ std:: cerr << "Error in HSAResourceManager::CreateAQLFromExecutable(): Create signal failed.\n";
+ return false;
+ }
+ }
+
+ m_aqlInfos[&aql].m_completionSignal = aql.completion_signal;
+
+ return true;
+}
+
+bool HSAResourceManager::Finalize(const void* pBRIG,
+ const std::string& compileFlags,
+ const hsa_profile_t hsaProfile,
+ hsa_executable_t& executableOut,
+ hsa_code_object_t& codeObjOut)
+{
+ if (nullptr == pBRIG)
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): pBrig cannot be nullptr.\n";
+ return false;
+ }
+
+ hsa_status_t status;
+
+ // Create HSA program ----------------------------
+ hsa_ext_program_t program = {0};
+#if defined(_WIN64) || defined(_LP64)
+ status = ms_finalizer.m_pTable->hsa_ext_program_create(
+ HSA_MACHINE_MODEL_LARGE,
+ hsaProfile,
+ HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO,
+ "-g",
+ &program
+ );
+#else
+ status = ms_finalizer.m_pTable->hsa_ext_program_create(
+ HSA_MACHINE_MODEL_SMALL,
+ hsaProfile,
+ HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO,
+ "-g",
+ &program
+ );
+#endif
+
+ if (!HSA_CHECK_STATUS(status) || 0 == program.handle)
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): Create HSA program failed.\n";
+ return false;
+ }
+
+ // Add BRIG module to HSA program ----------------------------
+ hsa_ext_module_t programModule = reinterpret_cast(const_cast(pBRIG));
+ status = ms_finalizer.m_pTable->hsa_ext_program_add_module(program, programModule);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): Adding BRIG module failed.\n";
+ return false;
+ }
+
+ // Finalize hsail program --------------------------------------------------------
+ hsa_isa_t isa;
+ status = hsa_agent_get_info(ms_gpu.m_device, HSA_AGENT_INFO_ISA, &isa);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): Fail to get ISA.\n";
+ return false;
+ }
+
+ hsa_ext_control_directives_t control_directives;
+ memset(&control_directives, 0, sizeof(hsa_ext_control_directives_t));
+
+ status = ms_finalizer.m_pTable->hsa_ext_program_finalize(
+ program,
+ isa,
+ 0,
+ control_directives,
+ compileFlags.c_str(),
+ HSA_CODE_OBJECT_TYPE_PROGRAM,
+ &codeObjOut
+ );
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Failed to finalize program.\n";
+ return false;
+ }
+
+ m_codeObjSet.insert(codeObjOut.handle);
+
+ status = ms_finalizer.m_pTable->hsa_ext_program_destroy(program);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::Finalize(): Failed to destroy program.\n";
+ }
+
+ program.handle = 0;
+
+ // Create executable
+ status = hsa_executable_create(
+ hsaProfile, HSA_EXECUTABLE_STATE_UNFROZEN, "", &executableOut);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Failed to create hsa executable.\n";
+ return false;
+ }
+
+ m_executableSet.insert(executableOut.handle);
+
+ // Load code object.
+ status = hsa_executable_load_code_object(executableOut, ms_gpu.m_device, codeObjOut, nullptr);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Failed to load code object.\n";
+ return false;
+ }
+
+ // Freeze executable
+ status = hsa_executable_freeze(executableOut, nullptr);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Failed to freeze executable.\n";
+ return false;
+ }
+
+ return true;
+}
+
+bool HSAResourceManager::CopyKernelDispatchPacket(
+ const hsa_kernel_dispatch_packet_t& aqlPacket,
+ const bool bCopySignal,
+ hsa_kernel_dispatch_packet_t& aqlPacketOut) const
+{
+ if (nullptr == memcpy(&aqlPacketOut, &aqlPacket, sizeof(hsa_kernel_dispatch_packet_t)))
+ {
+ std::cerr << "Error in HSAResourceManager::CopyKernelDispatchPacket(): memcpy() fail.\n";
+ return false;
+ }
+
+ if (!bCopySignal)
+ {
+ aqlPacketOut.completion_signal.handle = 0;
+ }
+
+ return true;
+}
+
+bool HSAResourceManager::AppendKernelArgs(const void* pAddr, const std::size_t size, hsa_kernel_dispatch_packet_t& aql)
+{
+ return m_aqlInfos[&aql].m_kernArgBuffer.AppendKernelArgs(pAddr, size);
+}
+
+bool HSAResourceManager::RegisterKernelArgsBuffer(hsa_kernel_dispatch_packet_t& aql)
+{
+ aql.kernarg_address = m_aqlInfos[&aql].m_kernArgBuffer.GetArgBufferPointer();
+
+ if (nullptr == aql.kernarg_address)
+ {
+ std::cerr << "Error in RegisterKernelArgsBuffer(): argument buffer hasn't been allocated yet.\n";
+ return false;
+ }
+
+ return true;
+}
+
+bool HSAResourceManager::DeregisterKernelArgsBuffer(hsa_kernel_dispatch_packet_t& aql)
+{
+ bool ret = m_aqlInfos[&aql].m_kernArgBuffer.DestroyBuffer();
+
+ aql.kernarg_address = nullptr;
+
+ return ret;
+}
+
+bool HSAResourceManager::Dispatch(hsa_kernel_dispatch_packet_t& aql)
+{
+ if (nullptr == ms_pQueue)
+ {
+ std::cerr << "No queue!\n";
+ return false;
+ }
+
+ // Verify if we have register the kernel args buffer.
+ // Assumming we have only one kernel in the application.
+ if (nullptr != m_aqlInfos[&aql].m_kernArgBuffer.GetArgBufferPointer()
+ && nullptr == aql.kernarg_address)
+ {
+ this->RegisterKernelArgsBuffer(aql);
+ }
+
+ const uint32_t& queueSize = ms_pQueue->size;
+ const uint32_t queueMask = queueSize - 1;
+
+ // Write to queue
+ uint64_t index = hsa_queue_load_write_index_relaxed(ms_pQueue);
+ ((hsa_kernel_dispatch_packet_t*)(ms_pQueue->base_address))[index & queueMask] = aql;
+ hsa_queue_store_write_index_relaxed(ms_pQueue, index + 1);
+
+ // Ring doorbell.
+ hsa_signal_store_release(ms_pQueue->doorbell_signal, static_cast(index));
+
+ return true;
+}
+
+bool HSAResourceManager::WaitForCompletion(hsa_signal_t& completionSignal, uint64_t timeout, bool outputTimingData)
+{
+ bool ret = true;
+
+ if (0 != hsa_signal_wait_acquire(completionSignal, // signal
+ HSA_SIGNAL_CONDITION_EQ, // condition
+ 0, // compare_value
+ timeout, // time_out_hint
+ HSA_WAIT_STATE_ACTIVE) // wait_state_hint
+ )
+ {
+ std::cerr << "Error in HSAResourceManager::WaitForCompletion(): Signal wait return unexpected value\n";
+ ret = false;
+ }
+
+ if (outputTimingData && ms_profilingEnabled)
+ {
+ hsa_amd_profiling_dispatch_time_t dispatch_times;
+ dispatch_times.start = 0;
+ dispatch_times.end = 0;
+ hsa_status_t status = hsa_amd_profiling_get_dispatch_time(ms_gpu.m_device, completionSignal, &dispatch_times);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::WaitForCompletion(): hsa_amd_profiling_get_dispatch_time() failed.\n";
+ }
+
+ std::cout << "Kernel dispatch executed in " << double((dispatch_times.end - dispatch_times.start) / 1e6) << " milliseconds.\n";
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::CreateSignal(hsa_signal_t& signalOut)
+{
+ bool ret = true;
+ hsa_signal_t signal;
+ // The initial value of the signal is 1.
+ hsa_status_t status = hsa_signal_create(1, 0, nullptr, &signal);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::CreateSignal(): hsa_signal_create failed\n";
+ signal.handle = 0;
+ ret = false;
+ }
+ else
+ {
+ m_signals.push_back(signal);
+ signalOut = signal;
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::DestroySignal(hsa_signal_t& signal)
+{
+ bool ret = true;
+ hsa_status_t status;
+
+ for (unsigned int i = 0; i < m_signals.size(); ++i)
+ {
+ if (signal.handle == m_signals[i].handle)
+ {
+ m_signals[i] = m_signals[m_signals.size() - 1];
+ m_signals.pop_back();
+ break;
+ }
+ }
+
+ status = hsa_signal_destroy(signal);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Error in HSAResourceManager::DestoySignal(): hsa_signal_destroy() failed\n";
+ ret &= false;
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::HasRuntime()
+{
+ return ms_hasRuntime;
+}
+
+bool HSAResourceManager::ShutDown()
+{
+ bool ret = true;
+
+ if (ms_hasRuntime)
+ {
+ if (!DestroyQueue())
+ {
+ ret = false;
+ std::cerr << "Error in HSAResourceManager::ShutDown(): Destroying queue failed\n";
+ }
+
+ hsa_status_t status = hsa_shut_down();
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ ret = false;
+ std::cerr << "Error in HSAResourceManager::ShutDown(): Shutting down HSA runtime failed.\n";
+ }
+
+ ms_hasRuntime = false;
+ }
+
+ return ret;
+}
+
+bool HSAResourceManager::CleanUp()
+{
+ bool ret = true;
+ hsa_status_t status;
+
+ // Clean up signals
+ for (std::size_t i = 0; i < m_signals.size(); ++i)
+ {
+ if (0 != m_signals[i].handle)
+ {
+ // TODO: Check the correct way to terminate a kernel.
+ // If there is still kernel running, it should be terminated at this time.
+ /**
+ hsa_signal_value_t sv = hsa_signal_wait_acquire(
+ m_signals[i],
+ HSA_EQ, // condition
+ 0, // compare_value
+ 0, // time_out_hint
+ HSA_WAIT_ACTIVE); // wait_state_hint
+ if (static_cast(0) != sv)
+ {
+ std::cout << "HSAResourceManager::CleanUp(): A kernel may not exit normally.\n";
+ }
+ **/
+ status = hsa_signal_destroy(m_signals[i]);
+ bool lret = HSA_CHECK_STATUS(status);
+ ret &= lret;
+
+ if (true != lret)
+ {
+ std::cerr << "Error in HSAResourceManager::CleanUp(): Destroying signal " << i << " failed.\n";
+ }
+
+ m_signals[i].handle = 0;
+ }
+ }
+
+ m_signals.clear();
+
+ for (std::unordered_map::iterator iter = m_aqlInfos.begin();
+ iter != m_aqlInfos.end(); ++iter)
+ {
+ iter->second.m_kernArgBuffer.DestroyBuffer();
+ }
+
+ m_aqlInfos.clear();
+
+ // Destroy executable
+ for (std::unordered_set::iterator iter = m_executableSet.begin();
+ iter != m_executableSet.end(); ++iter)
+ {
+ hsa_executable_t tmp = {*iter};
+ status = hsa_executable_destroy(tmp);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Fail to destroy hsa executable.\n";
+ ret = false;
+ }
+ }
+
+ m_executableSet.clear();
+
+ // Destroy code object
+ for (std::unordered_set::iterator iter = m_codeObjSet.begin();
+ iter != m_codeObjSet.end(); ++iter)
+ {
+ hsa_code_object_t tmp = {*iter};
+ status = hsa_code_object_destroy(tmp);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ std::cerr << "Fail to destroy code object.\n";
+ ret = false;
+ }
+ }
+
+ m_codeObjSet.clear();
+
+ m_aqlInfos.clear();
+
+ return ret;
+}
+
+bool HSAResourceManager::DestroyQueue()
+{
+ bool ret = true;
+
+ if (nullptr != ms_pQueue)
+ {
+ hsa_status_t status = hsa_queue_destroy(ms_pQueue);
+ ret = HSA_CHECK_STATUS(status);
+
+ if (true != ret)
+ {
+ std::cerr << "Error in HSAResourceManager::DestroyQueue(): hsa_queue_destroy() falied.\n";
+ }
+ else
+ {
+ ms_pQueue = nullptr;
+ }
+ }
+
+ return ret;
+}
+
+void* HSAResourceManager::AllocateCoarseLocalMemory(size_t size)
+{
+ if (0 == ms_gpu.coarseRegion.handle)
+ {
+ std::cerr << "AllocateCoarseLocalMemory(): No coarse memory region present, exit" << std::endl;
+ return nullptr;
+ }
+
+ void* pBuffer = nullptr;
+ hsa_status_t status = hsa_memory_allocate(ms_gpu.coarseRegion, size, &pBuffer);
+ return HSA_CHECK_STATUS(status) ? pBuffer : nullptr;
+}
+
+void* HSAResourceManager::AllocateSysMemory(size_t size)
+{
+ if (0 == ms_gpu.kernargRegion.handle)
+ {
+ std::cerr << "AllocateSysMemory(): No kernel arg region present, exit." << std::endl;
+ return nullptr;
+ }
+
+ void* pBuffer = nullptr;
+ hsa_status_t status = hsa_memory_allocate(ms_gpu.kernargRegion, size, &pBuffer);
+ return HSA_CHECK_STATUS(status) ? pBuffer : nullptr;
+}
+
+bool HSAResourceManager::FreeHSAMemory(void* pBuffer)
+{
+ if (nullptr == pBuffer)
+ {
+ return true;
+ }
+
+ return HSA_CHECK_STATUS(hsa_memory_free(pBuffer));
+}
+
+bool HSAResourceManager::CopyHSAMemory(void* pDest, const void* pSrc,
+ std::size_t size, bool hostToDev)
+{
+ if (nullptr == pDest || nullptr == pSrc)
+ {
+ std::cerr << "HSAResourceManager::CopyHSAMemory(): Input source or destination buffer cannot be nullptr.\n";
+ return false;
+ }
+
+ if (0 == size)
+ {
+ std::cout << "Copy size is 0, nothing need to be done.\n";
+ return 0;
+ }
+
+ void* pBuffer = (hostToDev) ? pDest : const_cast(pSrc);
+ hsa_status_t status = hsa_memory_assign_agent(pBuffer, ms_gpu.m_device, HSA_ACCESS_PERMISSION_RW);
+
+ if (!HSA_CHECK_STATUS(status))
+ {
+ return false;
+ }
+
+ status = hsa_memory_copy(pDest, pSrc, size);
+ return (HSA_CHECK_STATUS(status));
+}
+
+// Accessors
+const AgentInfo& HSAResourceManager::GPUInfo()
+{
+ return ms_gpu;
+}
+
+const AgentInfo& HSAResourceManager::CPUInfo()
+{
+ return ms_cpu;
+}
+
+const hsa_agent_t& HSAResourceManager::GPU()
+{
+ return ms_gpu.m_device;
+}
+
+const hsa_agent_t& HSAResourceManager::CPU()
+{
+ return ms_cpu.m_device;
+}
+
+const uint32_t& HSAResourceManager::GPUChipID()
+{
+ return ms_gpu.m_chipID;
+}
+
+const uint32_t& HSAResourceManager::CPUChipID()
+{
+ return ms_cpu.m_chipID;
+}
+
+hsa_queue_t* const& HSAResourceManager::Queue()
+{
+ return ms_pQueue;
+}
+
+AQLInfo& HSAResourceManager::GetAqlInfo(hsa_kernel_dispatch_packet_t& aql)
+{
+ return m_aqlInfos[&aql];
+}
+
+bool InitAQL(hsa_kernel_dispatch_packet_t& aqlPacketOut)
+{
+ bool ret = true;
+ memset(&aqlPacketOut, 0, sizeof(hsa_kernel_dispatch_packet_t));
+
+ aqlPacketOut.header |= HSA_PACKET_TYPE_KERNEL_DISPATCH << HSA_PACKET_HEADER_TYPE;
+
+ // using FENCE_SCOPE_SYSTEM base on example on HSA runtime document, version 1_00_20150130.
+ aqlPacketOut.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE;
+ aqlPacketOut.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE;
+ aqlPacketOut.setup |= 1 << HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
+
+ aqlPacketOut.workgroup_size_x = 1;
+ aqlPacketOut.workgroup_size_y = 1;
+ aqlPacketOut.workgroup_size_z = 1;
+ aqlPacketOut.grid_size_x = 1;
+ aqlPacketOut.grid_size_y = 1;
+ aqlPacketOut.grid_size_z = 1;
+
+ return ret;
+}
+
+// ------------------ Definitions of HSAKernelArgBuffer ------------------------
+
+HSAKernelArgBuffer::HSAKernelArgBuffer() :
+ m_pArgBuffer(nullptr),
+ m_argBufferSize(0),
+ m_location(0)
+{
+}
+
+HSAKernelArgBuffer::~HSAKernelArgBuffer()
+{
+ this->DestroyBuffer();
+}
+
+bool HSAKernelArgBuffer::AllocateBuffer(
+ const std::size_t bufSize,
+ const std::size_t offsetSize,
+ const std::size_t clearedValue)
+{
+ if (nullptr == m_pArgBuffer)
+ {
+ m_argBufferSize = bufSize;
+ m_pArgBuffer = HSAResourceManager::AllocateSysMemory(m_argBufferSize);
+
+ if (nullptr == m_pArgBuffer)
+ {
+ std::cerr << "Error in AllocateBuffer(): Fail to AllocateSysMemory for argument buffer.\n";
+ return false;
+ }
+
+ // Need to add arguments offsets.
+ // They are the OpenCL compiler generated offsets, can be zero.
+ m_location += offsetSize;
+ memset(m_pArgBuffer, static_cast(clearedValue), m_argBufferSize);
+ }
+ else
+ {
+ std::cerr << "Error in AllocateBuffer(): Please call DestroyBuffer() first before re-using it.\n";
+ return false;
+ }
+
+ return true;
+}
+
+bool HSAKernelArgBuffer::DestroyBuffer()
+{
+ bool ret = HSAResourceManager::FreeHSAMemory(m_pArgBuffer);
+ m_pArgBuffer = nullptr;
+ m_argBufferSize = 0;
+ m_location = 0;
+ return ret;
+}
+
+bool HSAKernelArgBuffer::AppendKernelArgs(const void* pAddr, const std::size_t size)
+{
+ if (nullptr == m_pArgBuffer)
+ {
+ std::cerr << "Error in AppendKernelArgs(): Please call AllocateBuffer() first.\n";
+ return false;
+ }
+
+ if (nullptr == pAddr)
+ {
+ std::cerr << "Error in AppendKernelArgs(): Address of input arguments is nullptr.\n";
+ return false;
+ }
+
+ if (m_location + size > m_argBufferSize)
+ {
+ std::cerr << "Error in AppendKernelArgs(): Exceed argument buffer size.\n";
+ return false;
+ }
+
+ memcpy(reinterpret_cast(m_pArgBuffer) + m_location, pAddr, size);
+ m_location += size;
+
+ return true;
+}
+
+void* HSAKernelArgBuffer::GetArgBufferPointer() const
+{
+ return m_pArgBuffer;
+}
+// ----------------- End of Definitions of HSAKernelArgBuffer ------------------
+
+/// \brief Output device type as string
+///
+/// \param[in] dt Device type
+/// \return Device type as string
+static std::string ConvertDeviceTypeToString(hsa_device_type_t dt)
+{
+ std::string ret;
+
+ switch (dt)
+ {
+ case HSA_DEVICE_TYPE_CPU:
+ ret = "CPU";
+ break;
+
+ case HSA_DEVICE_TYPE_GPU:
+ ret = "GPU";
+ break;
+
+ case HSA_DEVICE_TYPE_DSP:
+ ret = "DSP";
+ break;
+
+ default:
+ ret = "Unknown";
+ break;
+ }
+
+ return ret;
+}
+
+hsa_status_t QueryDevice_Callback(hsa_agent_t agent, void* pData)
+{
+ if (pData == nullptr)
+ {
+ std::cerr << "QueryDevice_Callback: pData cannot be nullptr.\n";
+ return HSA_STATUS_ERROR_INVALID_ARGUMENT;
+ }
+
+ hsa_device_type_t deviceType;
+ hsa_status_t err;
+ AgentList* pAgentList = reinterpret_cast(pData);
+ AgentInfo agentInfo;
+
+ agentInfo.m_device = agent;
+ // Query type of device
+ err = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &deviceType);
+
+ if (!HSA_CHECK_STATUS(err))
+ {
+ std::cerr << "Error in QueryDevice_Callback(): Obtaining device type failed.\n";
+ }
+
+ // Query chip id
+ err = hsa_agent_get_info(agent, static_cast(HSA_AMD_AGENT_INFO_CHIP_ID), &agentInfo.m_chipID);
+
+ if (!HSA_CHECK_STATUS(err))
+ {
+ std::cerr << "Error in InitRuntime(): Obtaining chip id failed.\n";
+ agentInfo.m_chipID = 0;
+ }
+
+ // Query HSA profile of the agent.
+ err = hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, &agentInfo.m_profile);
+
+ if (!HSA_CHECK_STATUS(err))
+ {
+ std::cerr << "Error in InitRuntime(): Obtaining hsa profile failed.\n";
+ }
+
+ switch (deviceType)
+ {
+ case HSA_DEVICE_TYPE_CPU:
+ pAgentList->m_vecCPU.push_back(agentInfo);
+ break;
+
+ case HSA_DEVICE_TYPE_GPU:
+ pAgentList->m_vecGPU.push_back(agentInfo);
+ break;
+
+ default:
+ break;
+ }
+
+ if (gs_bVerbosePrint)
+ {
+ char deviceName[64];
+ memset(deviceName, '\0', sizeof(deviceName));
+ // Query the name of device
+ err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, deviceName);
+
+ if (!HSA_CHECK_STATUS(err))
+ {
+ std::cerr << "Error in QueryDevice_Callback(): Obtaining device name failed.\n";
+ }
+
+ std::cout << "HSA device attributes:\n";
+ std::cout << "\tname: " << deviceName << "\n";
+ std::cout << "\ttype: " << ConvertDeviceTypeToString(deviceType) << "\n";
+ std::cout << std::hex << "\tchip ID: 0x" << agentInfo.m_chipID << "\n";
+ std::cout << std::dec; // reset digit output format.
+ std::cout << "\tHSA profile: " << ((agentInfo.m_profile == 0) ? ("Base") : ("Full")) << "\n";
+ }
+
+ return err;
+}
+
+hsa_status_t FindMemRegions_Callback(hsa_region_t region, void* data)
+{
+ if (nullptr == data)
+ {
+ std::cerr << "FindMemRegions(): data cannot be nullptr.\n";
+ return HSA_STATUS_ERROR;
+ }
+
+ hsa_region_global_flag_t flags;
+ hsa_region_segment_t segment_id;
+
+ hsa_status_t status = hsa_region_get_info(region, HSA_REGION_INFO_SEGMENT, &segment_id);
+ bool ret = HSA_CHECK_STATUS(status);
+
+ if (!ret)
+ {
+ return status;
+ }
+
+ if (HSA_REGION_SEGMENT_GLOBAL != segment_id)
+ {
+ return HSA_STATUS_SUCCESS;
+ }
+
+ AgentInfo* pRegion = reinterpret_cast(data);
+ status = hsa_region_get_info(region, HSA_REGION_INFO_GLOBAL_FLAGS, &flags);
+ ret = HSA_CHECK_STATUS(status);
+
+ if (!ret)
+ {
+ return status;
+ }
+
+ if (flags & HSA_REGION_GLOBAL_FLAG_COARSE_GRAINED)
+ {
+ pRegion->coarseRegion = region;
+ }
+
+ if (flags & HSA_REGION_GLOBAL_FLAG_KERNARG)
+ {
+ pRegion->kernargRegion = region;
+ }
+
+ if (flags & HSA_REGION_GLOBAL_FLAG_FINE_GRAINED)
+ {
+ pRegion->fineRegion = region;
+ }
+
+ return HSA_STATUS_SUCCESS;
+}
+
+bool HsaCheckStatus(hsa_status_t s)
+{
+ bool ret = true;
+
+ if (HSA_STATUS_SUCCESS == s)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ std::cerr << "\nHSA status is not HSA_STATUS_SUCCESS.\n";
+ std::cerr << HsaStatusStrings(s) << "\n";
+ }
+
+ return ret;
+}
+
+bool HsaCheckStatus(hsa_status_t s, const std::string& fileName, int lineNum)
+{
+ bool ret = true;
+
+ if (HSA_STATUS_SUCCESS == s)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ std::cout << "In " << fileName << ", line " << lineNum << "\n";
+ std::cerr << "HSA status is not HSA_STATUS_SUCCESS.\n";
+ std::cerr << "Error code: " << s << ".\n";
+ std::cerr << HsaStatusStrings(s) << ".\n";
+ }
+
+ return ret;
+}
+
+std::string HsaStatusStrings(hsa_status_t s)
+{
+ const char* pszbuff = nullptr;
+ hsa_status_string(s, &pszbuff);
+
+ std::string str;
+
+ if (pszbuff != nullptr)
+ {
+ str = pszbuff;
+ }
+ else
+ {
+ str = "hsa_status_string return nullptr string. Input HSA status code: " + std::to_string(static_cast(s));
+ }
+
+ return str;
+}
+
+#if defined(_WIN32) || defined(_WIN64)
+// setenv() and unsetenv() wrapper
+static int setenv(const char* name, const char* value, int overwrite)
+{
+ int ret = 0;
+ char* pBuffer = nullptr;
+ size_t len = 0;
+ errno_t err = _dupenv_s(&pBuffer, &len, name);
+
+ if (err)
+ {
+ return 1;
+ }
+
+ if (nullptr == pBuffer || 1 == overwrite)
+ {
+ ret = _putenv_s(name, value);
+ }
+
+ return ret;
+}
+
+static int unsetenv(const char* name)
+{
+ int ret = 0;
+ char* pBuffer = nullptr;
+ size_t len = 0;
+ errno_t err = _dupenv_s(&pBuffer, &len, name);
+
+ if (err)
+ {
+ return 1;
+ }
+
+ if (nullptr != pBuffer)
+ {
+ ret = _putenv_s(name, "");
+ }
+
+ return ret;
+}
+
+// GetEnv() wrapper
+static const std::string GetEnv(const std::string& name)
+{
+ std::string value = "";
+ char* pBuffer = nullptr;
+ size_t len = 0;
+ errno_t err = _dupenv_s(&pBuffer, &len, name.c_str());
+
+ if (err)
+ {
+ return value;
+ }
+
+ if (nullptr != pBuffer)
+ {
+ value = pBuffer;
+ }
+ return value;
+}
+
+#else // Linux platform
+// GetEnv() wrapper
+static const std::string GetEnv(const std::string& name)
+{
+ std::string value = "";
+ char* pBuffer = getenv(name.c_str());
+
+ if (nullptr != pBuffer)
+ {
+ value = pBuffer;
+ }
+
+ return value;
+}
+#endif
+
+bool SetSoftCPMode(bool bEnable, bool verbosePrint)
+{
+ using namespace std;
+ bool ret = true;
+ const string emulateStr = "HSA_EMULATE_AQL";
+ const string toolsLibStr = "HSA_TOOLS_LIB";
+
+ if (bEnable)
+ {
+ string emulateVar = "1";
+
+#ifdef _WIN64
+ string toolsLibVar = "hsa-runtime-tools64.dll";
+#elif defined(_WIN32)
+ string toolsLibVar = "hsa-runtime-tools.dll";
+#else // Only Linux x64 platform is supported for now. 03/18/2015
+ string toolsLibVar = "libhsa-runtime-tools64.so.1";
+#endif
+
+ if (0 != setenv(emulateStr.c_str(), emulateVar.c_str(), 1))
+ {
+ cerr << "Error in setting " << emulateStr << "\n";
+ ret &= false;
+ }
+
+ if (0 != setenv(toolsLibStr.c_str(), toolsLibVar.c_str(), 1))
+ {
+ cerr << "Error in setting " << toolsLibStr << "\n";
+ ret &= false;
+ }
+ }
+ else
+ {
+ if (0 != unsetenv(emulateStr.c_str()))
+ {
+ cerr << "Error in unsetting " << emulateStr << "\n";
+ ret &= false;
+ }
+
+ if (0 != unsetenv(toolsLibStr.c_str()))
+ {
+ cerr << "Error in unsetting " << toolsLibStr << "\n";
+ ret &= false;
+ }
+ }
+
+ // Print out the environment variable just set/unset.
+ if (verbosePrint)
+ {
+ std::string value = GetEnv(emulateStr);
+
+ if (value != "")
+ {
+ cout << "Set " << emulateStr << " = " << value << "\n";
+ }
+ else
+ {
+ cout << emulateStr << " is unset.\n";
+ }
+
+ value = GetEnv(toolsLibStr);
+
+ if (value != "")
+ {
+ cout << "Set " << toolsLibStr << " = " << value << "\n";
+ }
+ else
+ {
+ cout << toolsLibStr << " is unset.\n";
+ }
+ }
+
+ return ret;
+}
+
+} // namespace AMDT
diff --git a/gpudebugsdk/samples/Common/HSAResourceManager.h b/gpudebugsdk/samples/Common/HSAResourceManager.h
new file mode 100644
index 0000000..cd211f7
--- /dev/null
+++ b/gpudebugsdk/samples/Common/HSAResourceManager.h
@@ -0,0 +1,431 @@
+//==============================================================================
+// Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+/// \brief HSA Runtime resource management class
+//==============================================================================
+#ifndef HSA_RESOURCE_MANAGER_H_
+#define HSA_RESOURCE_MANAGER_H_
+
+#include
+#include // UINT64_MAX
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+/// \brief Check status macro that also report file name and line number in application debug build.
+///
+/// \param[in] x The status need to be check
+/// \return true if x == HSA_STATUS_SUCCESS
+#if defined (_DEBUG) || defined (DEBUG)
+ #define HSA_CHECK_STATUS( x ) AMDT::HsaCheckStatus(x, __FILE__, __LINE__)
+#else
+ #define HSA_CHECK_STATUS( x ) AMDT::HsaCheckStatus(x)
+#endif
+
+namespace AMDT
+{
+class HSAFinalizer;
+
+static const std::size_t gs_MAX_ARGS_BUFF_SIZE = 256;
+
+/// \brief A struct holding HSA agent (Device) information
+typedef struct AgentInfo
+{
+ // Agent device handle
+ hsa_agent_t m_device;
+
+ // Device chip ID
+ uint32_t m_chipID;
+
+ // Agent profile (FULL or BASE)
+ hsa_profile_t m_profile;
+
+ // Max size of Queue buffer
+ uint32_t m_maxQueueSize;
+
+ // Device local coarse grain memory region
+ hsa_region_t coarseRegion;
+
+ // Device local fine grain memory region
+ hsa_region_t fineRegion;
+
+ // Memory region supporting kernel arguments
+ hsa_region_t kernargRegion;
+
+ AgentInfo() : m_device({0}), m_chipID(0), m_maxQueueSize(0),
+ coarseRegion({0}), fineRegion({0}), kernargRegion({0})
+ {}
+} AgentInfo;
+
+// -----------------------------------------------------------------------------
+
+/// Wrap the kernel argument buffer processing
+class HSAKernelArgBuffer
+{
+public:
+ /// Constructor
+ HSAKernelArgBuffer();
+
+ /// Destructor
+ ~HSAKernelArgBuffer();
+
+ /// \brief Allocate kernel argument buffers.
+ bool AllocateBuffer(const std::size_t bufSize,
+ const std::size_t offsetSize = sizeof(uint64_t) * 6,
+ const std::size_t clearedValue = 0x0);
+
+ /// \brief Release kernel argument buffers.
+ bool DestroyBuffer();
+
+ /// \brief Append a kernel argument into argument buffer, m_argsBuff
+ ///
+ /// \param[in] pAddrToCopyIn The address of input kernel argument
+ /// \param[in] argsSizeInBytes Size of the input kernel argument
+ /// \param[in] offsetSize Depends on the source, we have additional global offset argument.
+ /// For now the default value is for OpenCL 2.0 kernel.
+ /// \return true if there is no error
+ bool AppendKernelArgs(
+ const void* pAddrToCopyIn,
+ const std::size_t argsSizeInBytes);
+
+ /// Return the kernel arg buffer pointer
+ /// \returns the internal kernel arg buffer pointer
+ void* GetArgBufferPointer() const;
+
+private:
+ /// disable copy constructor
+ HSAKernelArgBuffer(const HSAKernelArgBuffer&);
+
+ /// disable assignment operator
+ HSAKernelArgBuffer& operator=(const HSAKernelArgBuffer&);
+
+ void* m_pArgBuffer; ///< pointer to the kernel argument buffer
+ size_t m_argBufferSize; ///< the allocated size of kernel argument buffer in bytes
+ size_t m_location; ///< the next available location in the arg buffer
+}; // class HSAKernelArgBuffer
+
+// -----------------------------------------------------------------------------
+
+// Info that related to specific aql
+typedef struct AQLInfo
+{
+ hsa_signal_t m_completionSignal;
+ hsa_executable_t m_executable;
+ hsa_code_object_t m_codeObj;
+ HSAKernelArgBuffer m_kernArgBuffer;
+
+ AQLInfo() : m_completionSignal({0}), m_executable({0}), m_codeObj({0}), m_kernArgBuffer(){}
+ AQLInfo(const AQLInfo& aqlInfo) :
+ m_completionSignal({0}),
+ m_executable(aqlInfo.m_executable),
+ m_codeObj(aqlInfo.m_codeObj)
+ {}
+} AQLInfo;
+
+class HSAResourceManager
+{
+public:
+ /// \brief Default constructor, initialize member variable
+ HSAResourceManager();
+
+ /// \brief Destructor, will call Destroy() to release resources.
+ ~HSAResourceManager();
+
+ /// \brief Call hsa_init() and setup a default GPU device
+ /// \param[in] verbosePrint set to true to print extra message outputs to console
+ ///
+ /// \return true if there is no error
+ static bool InitRuntime(bool verbosePrint = true);
+
+ /// \brief DetroyQueue() and then shut down HSA runtime
+ ///
+ /// \return true if there is no error
+ static bool ShutDown();
+
+ /// \brief Print hsa version numbers
+ ///
+ /// \return true if no error
+ static bool PrintHsaVersion();
+
+ /// \brief Get HSA version numbers
+ ///
+ /// \param[out] major Major version number
+ /// \param[out] minor Minor version number
+ /// \return true if no error
+ static bool GetHsaVersion(uint16_t& major, uint16_t& minor);
+
+ /// \brief Create a default HSA GPU queue. Note: assuming there is a
+ /// single queue with a single program
+ /// \param[in] enableKernelTimestamps flag indicating whether or not profiling is enabled on this queue
+ /// \return true if there is no error
+ static bool CreateDefaultQueue(bool enableKernelTimestamps = false);
+
+ /// \brief overide the default queue with the specified queue (deleting the default queue if necessary)
+ ///
+ /// \param[in] pQueue the queue to replace the default queue with
+ /// \return true if there is no error
+ static bool SetQueue(hsa_queue_t* pQueue);
+
+ /// \brief Finalize BRIG and create a default aql packet with 1 workitem
+ ///
+ /// \param[in] pBRIG BRIG module to be finalize to ISA.
+ /// \param[in] kernelSymbol Kernel entry point.
+ /// \param[in] bCreateSignal Tell the function to whether to create
+ /// a default signal value for AQL packet or not.
+ /// \param[out] aqlPacketOut The AQL packet which the finalized HSA program
+ /// information will be put into.
+ /// \param[in] finalizerFlags Additional compilation flags for finalizer.
+ /// \param[in] hsaProfile The hsa profile that the code object will be. It has to be matched with
+ /// the hsa profile of the input pBRIG.
+ /// \param[in] kernargOffset Depends on the source, we have additional global offset argument.
+ /// For now the default value is for OpenCL 2.0 kernel.
+ /// \return true if there is no error
+ bool CreateAQLPacketFromBrig(
+ const void* pBRIG,
+ const std::string& kernelSymbol,
+ const bool bCreateSignal,
+ hsa_kernel_dispatch_packet_t& aqlPacketOut,
+ const std::string& finalizerFlags = "",
+ const hsa_profile_t hsaProfile = HSA_PROFILE_FULL,
+ const std::size_t& kernargOffset = sizeof(uint64_t) * 6);
+
+ /// \brief Create a default aql packet from the existing executable with relative kernel symbol
+ ///
+ /// \param[in] kernelSymbol Kernel entry point
+ /// \param[in] bCreateSignal Tell the function to whether to create
+ /// a default signal value for AQL packet or not.
+ /// \param[out] aqlPacketOut The AQL packet which the finalized HSA program
+ /// information will be put into.
+ /// \return true if there is no error
+ bool CreateAQLFromExecutable(
+ const hsa_executable_t& hsaExecutable,
+ const std::string& kernelSymbol,
+ const bool bCreateSignal,
+ hsa_kernel_dispatch_packet_t& aqlPacketOut,
+ const std::size_t& kernargOffset = sizeof(uint64_t) * 6);
+
+ /// \brief Copy one aql packet setting to another
+ ///
+ /// \param[in] aqlPacket The AQL packet to be copied from
+ /// \param[in] bCopySignal Tell the function whether to copy the signal value from iAql.
+ /// \param[out] aqlPacketOut The AQL packet to be copied to.
+ /// \return true if there is no error
+ bool CopyKernelDispatchPacket(
+ const hsa_kernel_dispatch_packet_t& aqlPacket,
+ const bool bCopySignal,
+ hsa_kernel_dispatch_packet_t& aqlPacketOut) const;
+
+ /// \brief Append a kernel argument into argument buffer of specified aql,
+ ///
+ /// \param[in] pAddrToCopyIn The address of input kernel argument
+ /// \param[in] argsSizeInBytes Size of the input kernel argument
+ /// \param[in] aql The aql which the kernel arguments would be append to its
+ /// kernel arg buffer.
+ /// \return true if there is no error
+ bool AppendKernelArgs(
+ const void* pAddrToCopyIn,
+ const std::size_t argsSizeInBytes,
+ hsa_kernel_dispatch_packet_t& aql);
+
+ /// \brief Register kernel arguments buffer to the runtime
+ ///
+ /// \param[in] aqlPacket The aql packet which will take the kernel argument buffer
+ /// \return true if there is no error
+ bool RegisterKernelArgsBuffer(hsa_kernel_dispatch_packet_t& aqlPacket);
+
+ /// \brief Deregister kernel arguments buffer.
+ ///
+ /// \return true if there is no error
+ bool DeregisterKernelArgsBuffer(hsa_kernel_dispatch_packet_t& aql);
+
+ /// \brief Dispatch AQL kernel dispatch packet
+ ///
+ /// \param[in] aqlPacket The AQL packet going to be dispatch.
+ /// \return true if there is no error
+ bool Dispatch(hsa_kernel_dispatch_packet_t& aqlPacket);
+
+ /// \brief Wait for the AQL packet completion signal value be set to 0 as completion.
+ /// Once the AQL dispatch complete, the signal value will be set back to 1 by
+ /// this function.
+ ///
+ /// \param[in] completionSignal The completion signal to be waited on
+ /// \param[in] timeout Maximum duration of the wait. Specified in the same unit as the system timestamp.
+ /// \param[in] outputTimingData flag indicating whether or not kernel timing info
+ /// is output to the console (only available if CreateDefaultQueue was
+ /// called with kernel timestamps enabled)
+ /// \return true if there is no error
+ bool WaitForCompletion(hsa_signal_t& completionSignal, uint64_t timeout = UINT64_MAX, bool outputTimingData = false);
+
+ /// \brief Create a signal with default value 1.
+ ///
+ /// \param[out] signalOut The signal handle to be put into the created signal variable.
+ /// \return true if there is no error
+ bool CreateSignal(hsa_signal_t& signalOut);
+
+ /// \brief Destroy a signal
+ ///
+ /// \param[in,out] signal The signal going to be destroy.
+ /// \return true if there is no error
+ bool DestroySignal(hsa_signal_t& signal);
+
+ /// \brief Clean up function, release all signal variables which are created by CreateSignal(),
+ /// and m_prog, the HSA program handle member variable.
+ ///
+ /// \return true if there is no error
+ bool CleanUp();
+
+ /// \brief Destroy the queue created by CreateDefaultQueue().
+ ///
+ /// \return true if there is no error
+ static bool DestroyQueue();
+
+ /// \brief Allocate HSA device local memory in coarse grain region, if there is.
+ ///
+ /// \param[in] size Size of memory to be allocated, in bytes
+ /// \return Pointer to the allocated memory location, nullptr if fail.
+ static void* AllocateCoarseLocalMemory(size_t size);
+
+ /// \brief Allocate HSA kerenarg memory region
+ ///
+ /// \param[in] size Size of memory to be allocated, in bytes
+ /// \return Pointer to the allocated memory location, nullptr if fail.
+ static void* AllocateSysMemory(size_t size);
+
+ /// \brief Free HSA memory
+ ///
+ /// \param[in] Pointer to the memory location to be freed.
+ /// \return true if there is no error.
+ static bool FreeHSAMemory(void* pBuffer);
+
+ /// \brief Copy HSA memory
+ ///
+ /// \param[in] pDest Pointer to destination memory location.
+ /// \param[in] pSrc Pointer to source memory location.
+ /// \param[in] size Size of memory to be copy, in bytes.
+ /// \param[in] hostToDev Marker to tell whether it is going to be copied from host (CPU) to device (GPU).
+ /// \return true if there is no error.
+ static bool CopyHSAMemory(void* pDest, const void* pSrc, std::size_t size, bool hostToDev);
+
+
+ /// \brief return whether it has an HSA runtime initialized in it.
+ ///
+ /// \return true if there is already an HSA runtime.
+ static bool HasRuntime();
+
+ // Accessors
+ /// \brief return GPU agent info
+ ///
+ /// \return GPU agent info
+ static const AgentInfo& GPUInfo();
+
+ /// \brief return CPU agent info
+ ///
+ /// \return CPU agent info
+ static const AgentInfo& CPUInfo();
+
+ /// \brief return the GPU agent device
+ ///
+ /// \return GPU agent device
+ static const hsa_agent_t& GPU();
+
+ // Accessors
+ /// \brief return the CPU agent device
+ ///
+ /// \return GPU agent device
+ static const hsa_agent_t& CPU();
+
+ /// \brief Query GPU chip ID
+ ///
+ /// \return GPU chip ID
+ static const uint32_t& GPUChipID();
+
+ /// \brief Query CPU chip ID
+ ///
+ /// \return CPU chip ID
+ static const uint32_t& CPUChipID();
+
+ /// \brief return the default queue
+ ///
+ /// \return the default queue
+ static hsa_queue_t* const& Queue();
+
+ /// \brief Get specific AQLInfo
+ ///
+ /// \param[in] aql The aql which to be getting its AQLInfo
+ /// \param[in] return the AQLInfo
+ AQLInfo& GetAqlInfo(hsa_kernel_dispatch_packet_t& aql);
+
+private:
+ /// \brief Copy constructor, temporary banned
+ HSAResourceManager(const HSAResourceManager&);
+
+ /// \brief assignment operator, temporary banned
+ void operator=(const HSAResourceManager&);
+
+ /// \brief Finalize pBRIG to m_executable
+ bool Finalize(
+ const void* pBRIG,
+ const std::string& compileFlags,
+ const hsa_profile_t hsaProfile,
+ hsa_executable_t& executableOut,
+ hsa_code_object_t& codeObjOut);
+
+ // Member variables
+ static AMDT::HSAFinalizer ms_finalizer;
+
+ static uint16_t ms_hsaCount;
+ static bool ms_hasRuntime;
+ static bool ms_profilingEnabled;
+
+ /// \todo: Inorder to support multi-GPU system we should use vector<>
+ // (or something similar) here.
+ static AgentInfo ms_gpu;
+ static AgentInfo ms_cpu;
+
+ static hsa_queue_t* ms_pQueue;
+
+ std::vector m_signals;
+ std::unordered_map m_aqlInfos;
+ std::unordered_set m_executableSet;
+ std::unordered_set m_codeObjSet;
+
+}; // class HSAResourceManager
+
+// -----------------------------------------------------------------------------
+
+/// \brief Check status.
+///
+/// \param[in] s The status need to be check
+/// \return true if s == HSA_STATUS_SUCCESS
+bool HsaCheckStatus(hsa_status_t s);
+
+/// \brief Check status.
+///
+/// \param[in] s The status need to be check
+/// \param[in] fileName Current file name
+/// \param[in] lineNum Current line number in file
+/// \return true if s == HSA_STATUS_SUCCESS
+bool HsaCheckStatus(hsa_status_t s, const std::string& fileName, int lineNum);
+
+/// \brief Convert hsa status enum to string
+///
+/// \param[in] s the hsa status enum
+/// \return return the string
+std::string HsaStatusStrings(hsa_status_t s);
+
+/// \brief Enable or disable soft CP mode (set HSA_EMULATE_AQL and HSA_TOOLS_LIB environment variables)
+///
+/// \param[in] bEnable true to enable soft CP mode, false to disable soft CP mode
+/// \param[in] verbosePrint set to true to print the extra message outputs to console
+/// \return true if successful
+bool SetSoftCPMode(bool bEnable, bool verbosePrint = true);
+
+} // namespace AMDT
+
+#endif // HSA_RESOURCE_MANAGER_H_
diff --git a/gpudebugsdk/samples/MatrixMultiplication/Makefile b/gpudebugsdk/samples/MatrixMultiplication/Makefile
new file mode 100644
index 0000000..29870ec
--- /dev/null
+++ b/gpudebugsdk/samples/MatrixMultiplication/Makefile
@@ -0,0 +1,42 @@
+# Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+
+makefile: all
+all: MatrixMul
+
+SDKINC=../../include/
+
+HSADIR=/opt/rocm/hsa/
+HSAINC=$(HSADIR)include/
+HSALIB=$(HSADIR)lib/
+
+LIBLINE=-L$(HSALIB) -l:libhsa-runtime64.so.1
+
+CC=g++
+
+TESTCOMMON=../Common
+CFLAGS= -g -D_DEBUG -std=c++11 -m64 -Werror -I$(HSAINC) -I$(TESTCOMMON) -I$(SDKINC)
+LDFLAGS= -g -m64 -Werror -Wl,--unresolved-symbols=ignore-in-shared-libs
+
+OBJFLAGS = -c $(CFLAGS)
+
+SOURCES=\
+ $(TESTCOMMON)/HSAResourceManager.cpp\
+ $(TESTCOMMON)/HSAExtensionFinalizer.cpp\
+ MatrixMul.cpp
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+DEPS := $(OBJECTS:.o=.d)
+
+MatrixMul : $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LIBLINE) -o MatrixMul
+
+.cpp.o:
+ $(CC) -c -MMD $(CFLAGS) $< -o $@
+
+clean:
+ rm -f $(TESTCOMMON)/*.o $(TESTCOMMON)/*.d
+ rm -f *.o *.d
+ rm -f MatrixMul
+
+-include $(DEPS)
diff --git a/gpudebugsdk/samples/MatrixMultiplication/MatrixMul.cpp b/gpudebugsdk/samples/MatrixMultiplication/MatrixMul.cpp
new file mode 100644
index 0000000..fc34ad1
--- /dev/null
+++ b/gpudebugsdk/samples/MatrixMultiplication/MatrixMul.cpp
@@ -0,0 +1,388 @@
+//==============================================================================
+// Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+/// \brief A matrix multiplication sample implemented using the HSA runtime and
+/// HSAIL kernel 1.0F. This sample is provided to demonstrate
+/// rocm-gdb functionality. It loads brig file directly (that was
+/// generated with debugging support).
+//==============================================================================
+#include
+#include
+#include
+#if !defined(_WIN32) && !defined(_WIN64)
+#include
+#include
+#endif
+#include
+#include
+#include
+#include
+
+#include
+
+#include "HSAResourceManager.h"
+
+static const std::string gs_MATRIX_MUL_KERNEL_SYMBOL = "&__OpenCL_matrixMul_kernel";
+static const std::string gs_MATRIX_MUL_KERNEL_BRIG_FILE = "matrixMul_kernel.brig";
+
+static const std::string gs_OUTPUT_MATRIX_DIR = "./outputMatrix/";
+
+// ================================= Functions declaration ============================================
+
+void RunTest(bool doVerify);
+
+// Helper function to load binary file into data.
+bool LoadFile(const std::string& fileName, std::vector& data);
+
+// Helper function to output matrix result to file.
+void OutputMatrix(const std::string& fileName, const float* pMatrix, const size_t numElements, const size_t width);
+
+// =====================================================================================================
+
+int main(int argc, char** argv)
+{
+ bool doVerify = false;
+
+ if (argc > 1)
+ {
+ std::string ipOption(argv[1]);
+
+ if (ipOption == "--verify")
+ {
+ doVerify = true;
+ }
+ else
+ {
+ std::cout << "Matrixmul dispatches an HSAIL matrix multiplication kernel\n";
+ std::cout << "Possible options";
+ std::cout << " \t--verify\t verify correctness by comparing against a serial implementation\n";
+ }
+
+ }
+
+ RunTest(doVerify);
+ return 0;
+}
+
+void RunTest(bool doVerify)
+{
+ using namespace AMDT;
+
+ // Initialize HSA runtime
+ std::cout << "Initializing HSA runtime...\n";
+
+ if (true != HSAResourceManager::InitRuntime())
+ {
+ std::cerr << "RunTest(): HSA runtime initialization fail, exiting...\n";
+ return;
+ }
+
+ HSAResourceManager myHsa;
+
+ // Create default queue
+ if (!myHsa.CreateDefaultQueue(true))
+ {
+ std::cerr << "RunTest(): Error on creating default queue.\n";
+ return;
+ }
+
+ // Load the kernel brig
+ std::vector brigData;
+ if (!LoadFile(gs_MATRIX_MUL_KERNEL_BRIG_FILE, brigData))
+ {
+ std::cerr << "Error in RunTest(): LoadFile() failed.\n";
+ return;
+ }
+
+ if (0 == brigData.size())
+ {
+ std::cerr << "RuntTest(): Error in loading brig.\n";
+ return;
+ }
+
+ // Create AQL packet
+ hsa_kernel_dispatch_packet_t aql;
+
+ if (!myHsa.CreateAQLPacketFromBrig(
+ &brigData[0],
+ gs_MATRIX_MUL_KERNEL_SYMBOL,
+ true,
+ aql))
+ {
+ std::cerr << "RuntTest(): Error in finalizing and creating AQL packet.\n";
+ return;
+ }
+
+ // Setup matrices dimensions
+ const size_t WORK_GROUP_SIZE = 16;
+ const size_t HA = 5 * WORK_GROUP_SIZE;
+ const size_t WA = 3 * WORK_GROUP_SIZE;
+ const size_t HB = WA;
+ const size_t WB = 8 * WORK_GROUP_SIZE;
+ const size_t HC = HA;
+ const size_t WC = WB;
+
+ // Setup AQL packet
+ aql.setup |= 2 << HSA_KERNEL_DISPATCH_PACKET_SETUP_DIMENSIONS;
+ aql.workgroup_size_x = WORK_GROUP_SIZE;
+ aql.workgroup_size_y = WORK_GROUP_SIZE;
+ aql.grid_size_x = WC;
+ aql.grid_size_y = HC;
+
+ // Allocate memory for computation
+ size_t sizeA = HA * WA;
+ size_t sizeB = HB * WB;
+ size_t sizeC = HC * WC;
+ float* pBufferA = (float*) HSAResourceManager::AllocateSysMemory(sizeA * sizeof(float));
+ float* pBufferB = (float*) HSAResourceManager::AllocateSysMemory(sizeB * sizeof(float));
+ float* pBufferC = (float*) HSAResourceManager::AllocateSysMemory(sizeC * sizeof(float));
+ // Initialize buffers, generate random matrices data.
+ srand(static_cast(time(nullptr)));
+
+ for (size_t i = 0; i < sizeA; ++i)
+ {
+ pBufferA[i] = static_cast(rand()) / static_cast(RAND_MAX);
+ }
+
+ for (size_t i = 0; i < sizeB; ++i)
+ {
+ pBufferB[i] = static_cast(rand()) / static_cast(RAND_MAX);
+ }
+
+ for (size_t i = 0; i < sizeC; ++i)
+ {
+ pBufferC[i] = 0.0f;
+ }
+
+#ifdef _DEBUG
+ // Output matrices data to files
+ OutputMatrix("matrixA.mat", pBufferA, sizeA, WA);
+ OutputMatrix("matrixB.mat", pBufferB, sizeB, WB);
+#endif
+
+ // Setup aql kernel arguments.
+ // Pass kernel arguments
+
+ // We have extra 6 64-bits kernel arguments before matrix C, A and B in kernel
+ // arguments, so we need to set them up in offset size.
+ if (!myHsa.AppendKernelArgs(&pBufferC, sizeof(float*), aql))
+ {
+ std::cerr << "RunTest(): Error on pBufferC AppendKernelArgs()\n";
+ }
+
+ if (!myHsa.AppendKernelArgs(&pBufferA, sizeof(float*), aql))
+ {
+ std::cerr << "RunTest(): Error on pBufferA AppendKernelArgs()\n";
+ }
+
+ if (!myHsa.AppendKernelArgs(&pBufferB, sizeof(float*), aql))
+ {
+ std::cerr << "RunTest(): Error on pBufferB AppendKernelArgs()\n";;
+ }
+
+ if (!myHsa.AppendKernelArgs(&WA, sizeof(uint32_t), aql))
+ {
+ std::cerr << "RunTest(): Error on WA AppendKernelArgs()\n";
+ }
+
+ if (!myHsa.AppendKernelArgs(&WB, sizeof(uint32_t), aql))
+ {
+ std::cerr << "RunTest(): Error on WB AppendKernelArgs()\n";
+ }
+
+ myHsa.RegisterKernelArgsBuffer(aql);
+
+ if (!myHsa.Dispatch(aql))
+ {
+ std::cerr << "RunTest(): Error on Dispatch()\n";
+ return;
+ }
+
+ // Wait for completion
+ std::cout << "Waiting for completion...\n";
+
+ if (!myHsa.WaitForCompletion(aql.completion_signal, UINT64_MAX, true))
+ {
+ std::cerr << "Error in RunTest(): Signal return error.\n";
+ return;
+ }
+
+ std::cout << "Complete.\n";
+
+#ifdef _DEBUG
+ // Output matrices data to files
+ OutputMatrix("matrixC.mat", pBufferC, sizeC, WC);
+#endif
+
+ if (doVerify)
+ {
+ std::cout << "Calculating reference data...\n";
+ std::vector referenceData(sizeC, 0.0f);
+
+ for (uint32_t i = 0; i < HA; ++i)
+ {
+ for (uint32_t j = 0; j < WB; ++j)
+ {
+ float sum = 0;
+
+ for (uint32_t k = 0; k < HB; ++k)
+ {
+ // c_ij = sum_k^HB(a_ik * b_kj);
+ sum += pBufferA[i * WA + k] * pBufferB[k * WB + j];
+ }
+
+ referenceData[i * WC + j] = sum;
+ }
+ }
+
+ // Validate
+ std::cout << "Validating...\n";
+ bool valid = true;
+ int failIndex = 0;
+
+ for (size_t i = 0; i < referenceData.size(); ++i)
+ {
+ if (fabs(pBufferC[i] - referenceData[i]) > 1e-3f)
+ {
+ failIndex = i;
+ valid = false;
+ break;
+ }
+ }
+
+ if (!valid)
+ {
+ uint32_t fi = failIndex / WC;
+ uint32_t fj = failIndex % WC;
+ std::cerr << "Result not correct!\n";
+ std::cerr << "Fail index: " << failIndex << "(" << fi << ", " << fj << ")\n";
+ std::cerr << "pBufferC[" << failIndex << "] = " << pBufferC[failIndex] << "\n";
+ std::cerr << "Expected: " << referenceData[failIndex] << "\n";
+ }
+ else
+ {
+ std::cout << "Pass.\n";
+ }
+
+#ifdef _DEBUG
+ // Output matrices data to files
+ OutputMatrix("referenceResult.mat", &referenceData[0], referenceData.size(), WC);
+#endif
+ }
+
+ // Cleanup.
+ if (nullptr != pBufferA)
+ {
+ HSAResourceManager::FreeHSAMemory(pBufferA);
+ pBufferA = nullptr;
+ }
+ if (nullptr != pBufferB)
+ {
+ HSAResourceManager::FreeHSAMemory(pBufferB);
+ pBufferB = nullptr;
+ }
+ if (nullptr != pBufferC)
+ {
+ HSAResourceManager::FreeHSAMemory(pBufferC);
+ pBufferC = nullptr;
+ }
+
+ myHsa.CleanUp();
+ myHsa.DestroyQueue();
+
+ // Explicit call ShutDown() function, though it will
+ // be called automatically when the program exit.
+ HSAResourceManager::ShutDown();
+}
+
+bool LoadFile(const std::string& fileName, std::vector& data)
+{
+ bool ret = false;
+ std::ifstream inFile(fileName, std::ios::binary);
+
+ if (inFile.good())
+ {
+ // get the size of the file;
+ inFile.seekg(0, std::ios::end);
+ std::size_t length = inFile.tellg();
+ inFile.seekg(0, std::ios::beg);
+
+ data.clear();
+ data.resize(length, 0);
+ inFile.read(&data[0], length);
+ ret = true;
+ }
+ else
+ {
+ std::cerr << "Error in LoadFile(): Error when open file \"" << fileName << "\"\n";
+ ret = false;
+ }
+
+ inFile.close();
+ return ret;
+}
+
+void OutputMatrix(const std::string& fileName, const float* pMatrix, const size_t numElements, const size_t width)
+{
+ static std::string realMatrixOutDir = gs_OUTPUT_MATRIX_DIR;
+ static bool isFirst = true;
+
+ // First time run to check the output matrix directory
+ if (isFirst)
+ {
+#if defined(_WIN32) || defined(_WIN64)
+ /// \todo: windows version directory creation
+#else
+ // Check if gs_OUTPUT_MATRIX_DIR is exist.
+ DIR* pDir = opendir(gs_OUTPUT_MATRIX_DIR.c_str());
+
+ if (nullptr == pDir)
+ {
+ // Create it.
+ int err = mkdir(gs_OUTPUT_MATRIX_DIR.c_str(), S_IRWXU | S_IRWXG);
+
+ if (0 != err)
+ {
+ std::cout << "Warning in RunTest(): Cannot create output matrix directory \"" << gs_OUTPUT_MATRIX_DIR << "\"\n";
+ realMatrixOutDir = "";
+ }
+ }
+ else
+ {
+ // Nothing need to be done if gs_OUTPUT_MATRIX_DIR already exist.
+ closedir(pDir);
+ }
+
+#endif
+ isFirst = false;
+ }
+
+ std::string realPath = realMatrixOutDir + fileName;
+ std::ofstream outFile(realPath);
+
+ if (outFile.is_open())
+ {
+ size_t height = numElements / width;
+
+ for (size_t i = 0; i < height; ++i)
+ {
+ size_t rowOffset = i * width;
+ outFile << pMatrix[rowOffset];
+
+ for (size_t j = 1; j < width; ++j)
+ {
+ outFile << "\t" << pMatrix[rowOffset + j];
+ }
+
+ outFile << "\n";
+ }
+ }
+ else
+ {
+ std::cerr << "Cannot open file " << realPath << "\n";
+ }
+
+ outFile.close();
+}
diff --git a/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.brig b/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.brig
new file mode 100644
index 0000000..35195d6
Binary files /dev/null and b/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.brig differ
diff --git a/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.hsail b/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.hsail
new file mode 100644
index 0000000..b0d806d
--- /dev/null
+++ b/gpudebugsdk/samples/MatrixMultiplication/matrixMul_kernel.hsail
@@ -0,0 +1,119 @@
+//==============================================================================
+// Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+//
+/// \author AMD Developer Tools
+/// \file
+//==============================================================================
+module &m:1:0:$full:$large:$default;
+extension "amd:gcn";
+extension "IMAGE";
+
+decl prog function &abort()();
+
+prog kernel &__OpenCL_matrixMul_kernel(
+ kernarg_u64 %__global_offset_0,
+ kernarg_u64 %__global_offset_1,
+ kernarg_u64 %__global_offset_2,
+ kernarg_u64 %__printf_buffer,
+ kernarg_u64 %__vqueue_pointer,
+ kernarg_u64 %__aqlwrap_pointer,
+ kernarg_u64 %C,
+ kernarg_u64 %A,
+ kernarg_u64 %B,
+ kernarg_u32 %wA,
+ kernarg_u32 %wB)
+{
+ pragma "AMD RTI", "ARGSTART:__OpenCL_matrixMul_kernel";
+ pragma "AMD RTI", "version:3:1:104";
+ pragma "AMD RTI", "device:generic";
+ pragma "AMD RTI", "uniqueid:1024";
+ pragma "AMD RTI", "memory:private:0";
+ pragma "AMD RTI", "memory:region:0";
+ pragma "AMD RTI", "memory:local:0";
+ pragma "AMD RTI", "value:__global_offset_0:u64:1:1:0";
+ pragma "AMD RTI", "value:__global_offset_1:u64:1:1:16";
+ pragma "AMD RTI", "value:__global_offset_2:u64:1:1:32";
+ pragma "AMD RTI", "pointer:__printf_buffer:u8:1:1:48:uav:7:1:RW:0:0:0";
+ pragma "AMD RTI", "value:__vqueue_pointer:u64:1:1:64";
+ pragma "AMD RTI", "value:__aqlwrap_pointer:u64:1:1:80";
+ pragma "AMD RTI", "pointer:C:float:1:1:96:uav:7:4:RW:0:0:0";
+ pragma "AMD RTI", "pointer:A:float:1:1:112:uav:7:4:RW:0:0:0";
+ pragma "AMD RTI", "pointer:B:float:1:1:128:uav:7:4:RW:0:0:0";
+ pragma "AMD RTI", "value:wA:u32:1:1:144";
+ pragma "AMD RTI", "value:wB:u32:1:1:160";
+ pragma "AMD RTI", "function:1:0";
+ pragma "AMD RTI", "memory:64bitABI";
+ pragma "AMD RTI", "privateid:8";
+ pragma "AMD RTI", "enqueue_kernel:0";
+ pragma "AMD RTI", "kernel_index:0";
+ pragma "AMD RTI", "reflection:0:size_t";
+ pragma "AMD RTI", "reflection:1:size_t";
+ pragma "AMD RTI", "reflection:2:size_t";
+ pragma "AMD RTI", "reflection:3:size_t";
+ pragma "AMD RTI", "reflection:4:size_t";
+ pragma "AMD RTI", "reflection:5:size_t";
+ pragma "AMD RTI", "reflection:6:float*";
+ pragma "AMD RTI", "reflection:7:float*";
+ pragma "AMD RTI", "reflection:8:float*";
+ pragma "AMD RTI", "reflection:9:int";
+ pragma "AMD RTI", "reflection:10:int";
+ pragma "AMD RTI", "ARGEND:__OpenCL_matrixMul_kernel";
+
+@__OpenCL_matrixMul_kernel_entry:
+ // BB#0: // %entry
+ workitemabsid_u32 $s0, 0;
+ cvt_u64_u32 $d5, $s0; // $d5 = work_item_id_x (tx)
+ workitemabsid_u32 $s0, 1;
+ ld_kernarg_align(8)_width(all)_u64 $d6, [%__global_offset_0]; // $d6 = 0
+ add_u64 $d0, $d5, $d6; // $d0 = tx
+ cvt_u64_u32 $d7, $s0; // $d7 = work_item_id_y (ty)
+ ld_kernarg_align(8)_width(all)_u64 $d8, [%__global_offset_1]; // $d8 = 0
+ add_u64 $d2, $d7, $d8; // $d2 = ty
+ ld_kernarg_align(4)_width(all)_u32 $s0, [%wB]; // $s0 = wB
+ ld_kernarg_align(4)_width(all)_u32 $s1, [%wA]; // $s1 = wA
+ ld_kernarg_align(8)_width(all)_u64 $d1, [%C]; // $d1 = C
+ cmp_lt_b1_s32 $c0, $s1, 1; // if (wA < 1)
+ cbr_b1 $c0, @BB0_1;
+ // BB#2: // %for.body.lr.ph
+ ld_kernarg_align(8)_width(all)_u64 $d3, [%B]; // $d3 = B
+ ld_kernarg_align(8)_width(all)_u64 $d4, [%A]; // $d4 = A
+ add_u64 $d7, $d8, $d7; // $d7 = ty
+ cvt_u32_u64 $s2, $d7;
+ mul_u32 $s3, $s1, $s2; // $s3 = ty * wA
+ add_u64 $d5, $d6, $d5; // $d5 = tx
+ cvt_u32_u64 $s4, $d5; // $s4 = tx
+ mov_b32 $s2, 0; // value = 0
+
+@BB0_3:
+ // %for.body
+ cvt_s64_s32 $d5, $s4; // $d5 = $s4
+ shl_u64 $d5, $d5, 2; // $d5 *= 4
+ add_u64 $d5, $d3, $d5; // $d5 = &B + (k*wB + tx)*4
+ ld_global_align(4)_f32 $s5, [$d5]; // $s5 = B[k*wB + tx]
+ cvt_s64_s32 $d5, $s3; // $d5 = ty * wA + k
+ shl_u64 $d5, $d5, 2;
+ add_u64 $d5, $d4, $d5; // $d5 = &A + (ty*wA+k)*4
+ ld_global_align(4)_f32 $s6, [$d5]; // $s6 = A[ty*wA + k]
+ mul_ftz_f32 $s5, $s6, $s5; // $s5 = A[ty*wA + k] * B[k*wB + tx]
+ add_ftz_f32 $s2, $s2, $s5; // value += $s5
+ add_u32 $s4, $s4, $s0; // $s4 += wB, (++k)*wB
+ add_u32 $s3, $s3, 1; // $s3 += 1, ++k
+ add_u32 $s1, $s1, 4294967295; // $s1 += 0xFFFFFFFF
+ cmp_ne_b1_s32 $c0, $s1, 0; // $c0 = ($s1 != 0) , loop wA times
+ cbr_b1 $c0, @BB0_3;
+ br @BB0_4;
+
+@BB0_1:
+ mov_b32 $s2, 0;
+
+@BB0_4:
+ // %for.end
+ cvt_u32_u64 $s1, $d2;
+ cvt_u32_u64 $s3, $d0;
+ mad_u32 $s0, $s1, $s0, $s3;
+ cvt_s64_s32 $d0, $s0;
+ shl_u64 $d0, $d0, 2;
+ add_u64 $d0, $d1, $d0;
+ st_global_align(4)_f32 $s2, [$d0]; // C[ty*wB + tx] = value
+ ret;
+};