mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-11-14 02:03:27 -08:00
Merge remote-tracking branch 'EpicGamesExt/master'
This commit is contained in:
commit
8066378fd3
266 files changed
+23733
-15926
No files matched your search
@@ -12,7 +12,7 @@ env:
|
||||
TORTURE_FLAGS: "--gen_crash_dump"
|
||||
|
||||
jobs:
|
||||
build-ubuntu-24-04:
|
||||
build-ubuntu-24:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -24,30 +24,58 @@ jobs:
|
||||
- radbin
|
||||
- torture
|
||||
compiler:
|
||||
- clang-17
|
||||
- clang-22
|
||||
# TODO: - gcc
|
||||
mode:
|
||||
- debug
|
||||
- release
|
||||
- gcc
|
||||
|
||||
name: ${{ matrix.target }}-${{ matrix.compiler }}-ubuntu24
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
- name: Install Dependencies
|
||||
|
||||
- name: Install Common Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --no-install-recommends -y pkg-config libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxrandr-dev libgl1-mesa-dev libegl1-mesa-dev
|
||||
|
||||
- name: Install clang-17 Dependencies
|
||||
if: ${{ matrix.compiler == 'clang-17' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends -y clang-17 lld-17 llvm-17
|
||||
sudo ln -sf /usr/bin/llvm-symbolizer-17 /usr/bin/llvm-symbolizer
|
||||
echo CC="${{ matrix.compiler }}" >> "${GITHUB_ENV}"
|
||||
echo AR=llvm-ar-17 >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Install ${{ matrix.compiler }} Dependencies
|
||||
if: ${{ matrix.compiler == 'clang-22' }}
|
||||
shell: bash
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main"
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang-22 lld-22 llvm-22 gcc-14 pkg-config libfreetype6-dev libx11-dev libxext-dev libgl1-mesa-dev libegl1-mesa-dev
|
||||
sudo ln -s /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer
|
||||
- name: build
|
||||
sudo apt-get install -y clang-22 lld-22 llvm-22
|
||||
sudo ln -sf /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer
|
||||
echo CC="${{ matrix.compiler }}" >> "${GITHUB_ENV}"
|
||||
echo AR=llvm-ar-22 >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Build (debug)
|
||||
shell: bash
|
||||
run: |
|
||||
CC="${{ matrix.compiler }}" ./build.sh "${{ matrix.target }}" "${{ matrix.mode }}"
|
||||
export CC_BUILD="${{ matrix.compiler }}"
|
||||
./build.sh "${{ matrix.target }}" debug ${CC_BUILD%%-*}
|
||||
|
||||
build-windows-2022:
|
||||
- name: Build (release)
|
||||
shell: bash
|
||||
run: |
|
||||
export CC_BUILD="${{ matrix.compiler }}"
|
||||
./build.sh "${{ matrix.target }}" release ${CC_BUILD%%-*}
|
||||
|
||||
build-windows-vs2022:
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -60,23 +88,60 @@ jobs:
|
||||
compiler:
|
||||
- msvc
|
||||
- clang
|
||||
mode:
|
||||
- debug
|
||||
- release
|
||||
|
||||
name: ${{ matrix.target }}-${{ matrix.compiler }}-vs2022
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
- name: build (vs 2022)
|
||||
- name: Build (debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VS_INSTALL=%%i"
|
||||
call "%VS_INSTALL%\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" "${{ matrix.mode }}" || exit /b 1
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" debug || exit /b 1
|
||||
- name: Build (debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" release || exit /b 1
|
||||
|
||||
build-windows-vs2026:
|
||||
runs-on: windows-2025
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- raddbg
|
||||
- radlink
|
||||
- radbin
|
||||
- mule_main
|
||||
compiler:
|
||||
- msvc
|
||||
- clang
|
||||
|
||||
name: ${{ matrix.target }}-${{ matrix.compiler }}-vs2026
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
- name: Build (debug)
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" debug || exit /b 1
|
||||
- name: Build (release)
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
|
||||
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" release || exit /b 1
|
||||
|
||||
run-ubuntu-24-04:
|
||||
runs-on: ubuntu-24.04
|
||||
if: false
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -97,12 +162,13 @@ jobs:
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main"
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang-22 lld-22 llvm-22 gcc-14 pkg-config libfreetype6-dev libx11-dev libxext-dev libgl1-mesa-dev libegl1-mesa-dev
|
||||
sudo apt-get install -y clang-22 lld-22 llvm-22 gcc-14 pkg-config libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxrandr-dev libgl1-mesa-dev libegl1-mesa-dev
|
||||
# crash callstack symbolizer depends on LLVM
|
||||
sudo ln -s /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer
|
||||
- name: Run
|
||||
shell: bash
|
||||
run: |
|
||||
[[ "${{ matrix.compiler }}" == "clang-22" ]] && export AR=llvm-ar-22
|
||||
CC="${{ matrix.compiler }}" ./run_tests.sh clang "${{ matrix.mode }}" -- \* $TORTURE_FLAGS
|
||||
- name: Upload Artifacts
|
||||
if: failure()
|
||||
@@ -118,6 +184,7 @@ jobs:
|
||||
|
||||
run-windows-2022:
|
||||
runs-on: windows-2022
|
||||
if: false
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
+99
-2
@@ -1,11 +1,102 @@
|
||||
# v0.9.29-alpha
|
||||
|
||||
## Debugger Changes
|
||||
- **The debugger now has preliminary support for native Linux x64 debugging.**
|
||||
It's still *very early*, and there is surely a lot to fix, so please expect a
|
||||
less stable experience than on Windows! But it is now finally in a state that
|
||||
we feel it'd be helpful for people to try it, so that we can begin
|
||||
battle-testing the debugger on Linux also. Here are a list of known issues
|
||||
and caveats:
|
||||
- We are not releasing any binaries for Linux yet, so we've provided
|
||||
instructions for locally building the debugger in the codebase's
|
||||
`README.md`.
|
||||
- We do not support debugging of code which uses `fork` and `vfork` yet.
|
||||
- When computing locations of thread-local storage, we currently assume that
|
||||
the debuggee uses the same libc version as the debugger.
|
||||
- We do not currently correctly unwind when the `.eh_frame_hdr` section is
|
||||
missing. This is normally there by default, but this may explain some
|
||||
broken callstacks you encounter. It can be enabled by passing the
|
||||
`--eh-frame-hdr` flag to the linker, if it's not enabled by default.
|
||||
- Bitfield type info is not yet supported correctly.
|
||||
- In some cases, our type deduplication (when converting from DWARF to RDI)
|
||||
is not working correctly. (#959)
|
||||
- Sometimes, a keyboard combination will incorrectly send text events. (#954)
|
||||
- The debugger now has preliminary support for loading Minidump (`.dmp`) files.
|
||||
They can be opened with the `Open Crash Dump` command.
|
||||
- Added a breakpoint setting which causes breakpoints to only break if they're
|
||||
hit by the currently selected thread, if there is a selected thread. If there
|
||||
isn't a selected thread yet, all threads will still cause a break.
|
||||
- Added a setting, `Lock New Breakpoints To Selected Thread`, which turns on
|
||||
the aforementioned breakpoint setting by default on all newly placed
|
||||
breakpoints.
|
||||
- Reintroduced `Browse` buttons for cells that edit file paths, which spawn a
|
||||
file picker, to more conveniently choose paths.
|
||||
- The debugger now tags watch expressions with the selected project, which
|
||||
means they'll be loaded and unloaded along with projects, similar to targets
|
||||
and breakpoints.
|
||||
- Empty spaces in the leftmost margin (where the selected thread position is
|
||||
visualized) in source and disassembly views is now clickable, as a fastpath
|
||||
for `Run To Line`.
|
||||
- The position of the destination of a `Run To Line` command is now visualized.
|
||||
- The debugger now better visualizes the status of loading debug info in the
|
||||
`Modules` tab.
|
||||
- The debugger's IPC system is now built on sockets rather than shared memory
|
||||
ring buffers. This is mostly an implementation detail, but it has introduced
|
||||
some noteworthy changes. First, communication with instances of the graphical
|
||||
debugger is now done through network ports, rather than through process IDs.
|
||||
By default, this port is `7423`, but it can be changed per-instance by
|
||||
passing the `--ipc_port` command line option, e.g. `raddbg --ipc_port=1234`.
|
||||
Furthermore, this also means that IPC commands can be sent over the network.
|
||||
This is unlikely to be especially helpful right now. But to do this, you can
|
||||
pass an IP address and port when sending a command, e.g.:
|
||||
`raddbg --ipc --ipc_addr=123.45.67.89:1234`.
|
||||
- The debugger now allows using a single font for the entire interface, if you
|
||||
want the UI elements and code to be drawn in a more uniform style. This is
|
||||
available through the `Use Alternative Font For UI` setting.
|
||||
- Fixed a performance issue when computing very large call stacks with many
|
||||
very small frames (fixes missing call stacks in some stack overflow cases).
|
||||
(#963)
|
||||
- Fixed `raddbg.com` adding the debugger as a command line target to itself
|
||||
incorrectly. (#946)
|
||||
- Fixed many other minor bugs and instabilities.
|
||||
|
||||
## Linker Changes
|
||||
- Improved memory usage and performance.
|
||||
- Fixes.
|
||||
|
||||
# v0.9.28-alpha
|
||||
|
||||
## Debugger Changes
|
||||
- First pass (will only work for simple cases currently) of watch expressions
|
||||
locks, allowing the same address (with the same type) to be evaluated after
|
||||
the expression goes out of scope.
|
||||
- Improved disassembly snapping behavior when not viewing disassembly. Now, if
|
||||
you do not have disassembly open, the debugger will prefer snapping to a call
|
||||
stack frame which has line info.
|
||||
- Added some visual and discoverability improvements to the UI.
|
||||
- Fixed a crash in the new (as of 0.9.27) unwinder. (#893, #882, #877, #869,
|
||||
#867, #865, #857, #848, #855, #824, #823)
|
||||
- Fixed a number of memory leaks, causing out-of-control memory usage in some
|
||||
cases. (#850)
|
||||
- Fixed certain cases of location information being incorrectly generated
|
||||
(notably in optimized builds, and functions with large stack usage). (#864)
|
||||
- Fixed incorrect session start logic (debug string clearing, breakpoint hit
|
||||
count resets) in multi-process debugging scenarios.
|
||||
- Fixed rare issues with call stack computation reliability.
|
||||
- Fixed cursor trails not being toggled by the `Animations` setting.
|
||||
- Fixed cursor trails being incorrectly rendered when a cursor is first
|
||||
scrolled into view.
|
||||
- Fixed line edits embedded in cells (e.g. in the Palette) not correctly
|
||||
clipping and scrolling longer strings. (#873)
|
||||
- Fixed behavior of setting the project path when that would overwrite a file
|
||||
which is not a debugger project file. (#875)
|
||||
|
||||
## Linker Changes
|
||||
- Implemented `/OPT:ICF` identical COMDAT folding.
|
||||
- Added DEF, and SECTION configuration support.
|
||||
- Improved COMDAT handling for weak symbols, ICF, and zero-sized COMDAT
|
||||
anchors, and stopped emitting empty marker sections that could produce invalid
|
||||
PE images.
|
||||
anchors, and stopped emitting empty marker sections that could produce
|
||||
invalid PE images.
|
||||
- Fixed import/export edge cases, including import data-directory bounds and
|
||||
archive member handling for `__imp_*` symbols.
|
||||
- Accepted duplicate identical weak search aliases without reporting multiply
|
||||
@@ -14,6 +105,12 @@
|
||||
- Fixed DBI section-contribution image-section range mapping.
|
||||
- Improved debug logging for `/OPT:REF` liveness stats and unresolved symbols
|
||||
referenced by `.llvm_addrsig`.
|
||||
- Improved diagnostics for unresolved symbols: radlink now identifies functions
|
||||
that reference undefined symbols, even if the function was inlined (provided
|
||||
the object file was compiled with debug info)
|
||||
- Reduced memory usage for large links.
|
||||
- Fixed forwarder export detection when the symbol name contains dots and has
|
||||
no alias.
|
||||
|
||||
# v0.9.27-alpha
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ local copy has been built. You can find pre-built release binaries
|
||||
[here](https://github.com/EpicGames/raddebugger/releases)._
|
||||
|
||||
The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It
|
||||
currently only supports local-machine Windows x64 debugging with PDBs, with
|
||||
plans to expand and port in the future. In the future we'll expand to also
|
||||
support native Linux debugging and DWARF debug info.
|
||||
currently only supports local-machine x64 debugging on both Windows and Linux
|
||||
(although Linux support is still very early). We plan to expand support to
|
||||
other architectures, and to implement remote and multi-machine debugging.
|
||||
|
||||
The debugger is currently in *ALPHA*. In order to get the debugger
|
||||
bullet-proof, it'd greatly help out if you submitted the issues you find
|
||||
@@ -27,8 +27,7 @@ additional related technologies: **(1)** the RAD Debug Info (RDI) format, and
|
||||
The RAD Debug Info (RDI) format is our custom debug information format, which
|
||||
the debugger parses and uses, rather than the debug information natively
|
||||
produced by toolchains, like PDB or DWARF. To work with these existing
|
||||
toolchains, we convert PDB (and eventually PE/ELF files with embedded DWARF)
|
||||
into the RDI format on-demand.
|
||||
toolchains, we convert PDB and DWARF to the RDI format on-demand.
|
||||
|
||||
The RDI format is currently specified in code, in the files within the
|
||||
`src/lib_rdi` folder. In [`rdi.h`](src/lib_rdi/rdi.h) and
|
||||
@@ -83,20 +82,23 @@ A benchmark of the linker's performance is below:
|
||||
|
||||
---
|
||||
|
||||
# Project Development Setup Instructions
|
||||
# Project Development Setup / Local Build Instructions
|
||||
|
||||
**NOTE: Currently, only x64 Windows development is supported for the project.**
|
||||
The project is actively developed both on [Windows x64](#windows-x64) and
|
||||
[Linux x64](#linux-x64) development machines. Click on whichever you'd like to
|
||||
use.
|
||||
|
||||
## 1. Installing the Required Tools (MSVC & Windows SDK)
|
||||
## Windows x64
|
||||
|
||||
In order to work with the codebase, you'll need the [Microsoft C/C++ Build Tools
|
||||
v15 (2017) or later](https://aka.ms/vs/17/release/vs_BuildTools.exe), for both
|
||||
the Windows SDK and the MSVC compiler and linker.
|
||||
### 1. Installing the Required Tools (MSVC & Windows SDK)
|
||||
|
||||
First, you'll need the [Microsoft C/C++ Build Tools v15 (2017) or later](https://aka.ms/vs/17/release/vs_BuildTools.exe),
|
||||
for the Windows SDK, and the MSVC compiler and linker.
|
||||
|
||||
If the Windows SDK is installed (e.g. via installation of the Microsoft C/C++
|
||||
Build Tools), you may also build with [Clang](https://releases.llvm.org/).
|
||||
|
||||
## 2. Build Environment Setup
|
||||
### 2. Build Environment Setup
|
||||
|
||||
Building the codebase can be done in a terminal which is equipped with the
|
||||
ability to call either MSVC or Clang from command line.
|
||||
@@ -169,73 +171,142 @@ build radlink release
|
||||
build radbin release
|
||||
```
|
||||
|
||||
---
|
||||
## Linux x64
|
||||
|
||||
# Project Roadmap
|
||||
### 1. Installing the Required Tools (GCC or Clang, Libraries)
|
||||
|
||||
### The Initial Alpha Battle-Testing Phase
|
||||
First, you'll need either GCC or Clang, if you don't already have them. They
|
||||
can be obtained by running one of the following commands, depending on your
|
||||
toolchain of choice and distribution:
|
||||
|
||||
The first priority for the project is to ensure that the most crucial components
|
||||
are functioning extremely reliably for local, x64, Windows development.
|
||||
For the debugger, this would include parts like debug info conversion, debug
|
||||
info loading, process control, stepping, evaluation (correct usage of both
|
||||
location info and type info), and a robust frontend which ensures the lower
|
||||
level parts are usable. For the linker, this is a matter of reliability and
|
||||
convergence with existing linker behavior.
|
||||
#### GCC on Ubuntu / Debian / Mint
|
||||
```
|
||||
sudo apt update && sudo apt install build-essential
|
||||
```
|
||||
|
||||
We feel that we've already come a long way in all of these respects, but given
|
||||
the massive set of possible combinations of languages, build settings,
|
||||
toolchains, used language features, and patterns of generated code, we still
|
||||
expect some issues, and are prioritizing these issues being resolved first.
|
||||
#### Clang on Ubuntu / Debian / Mint
|
||||
```
|
||||
sudo apt update && sudo apt install clang llvm
|
||||
```
|
||||
|
||||
We also hope to continue to improve performance in this phase. For the debugger,
|
||||
this primarily includes frontend performance, introducing caches when economical
|
||||
to do so, and tightening existing systems up. For the linker, it has been mostly
|
||||
tuned thus far for giant projects, and so we'd like to improve linking speed for
|
||||
small-to-mid sized projects as well.
|
||||
#### GCC on Arch / Manjaro
|
||||
```
|
||||
sudo pacman -S base-devel
|
||||
```
|
||||
|
||||
For the linker, there are also a number of features to come, like
|
||||
dead-code-elimination (`/opt:ref`), and link-time-optimizations with the help
|
||||
of `clang` (we won't support LTCG from MSVC, since it is undocumented).
|
||||
#### Clang on Arch / Manjaro
|
||||
```
|
||||
sudo pacman -S clang llvm
|
||||
```
|
||||
|
||||
### Local x64 Linux Debugging Phase
|
||||
If you've installed the Clang and LLVM tooling required, you can run:
|
||||
|
||||
The next priority for the project is to take the rock solid x64 Windows
|
||||
debugging experience, and port all of the relevant pieces to support local x64
|
||||
Linux debugging also.
|
||||
```
|
||||
clang --version && llvm-ar --version
|
||||
```
|
||||
|
||||
The debugger has been written to abstract over the parts that need to differ on
|
||||
either Linux or Windows, and this is mainly going to be a task in building out
|
||||
different backends for those abstraction layers.
|
||||
You should see output similar to the following:
|
||||
|
||||
The major parts of this phase are:
|
||||
```
|
||||
Ubuntu clang version 18.1.3 (1ubuntu1)
|
||||
Target: x86_64-pc-linux-gnu
|
||||
Thread model: posix
|
||||
InstalledDir: /usr/bin
|
||||
Ubuntu LLVM version 18.1.3
|
||||
Optimized build.
|
||||
```
|
||||
|
||||
- Porting the `src/demon` layer to implement the Demon local process control
|
||||
abstraction API.
|
||||
- Implementing an x64 ELF Linux unwinder in the `src/ctrl` layer.
|
||||
- Creating a DWARF-to-RDI converter (in the same way that we've built a
|
||||
PDB-to-RDI converter). A partial implementation of this is in
|
||||
`src/rdi_from_dwarf`.
|
||||
- Porting the `src/render` layer to implement all of the rendering features the
|
||||
frontend needs on a Linux-compatible API (the backend used on Windows is D3D11).
|
||||
- Porting the `src/font_provider` layer to a Linux-compatible font
|
||||
rasterization backend, like FreeType (the backend used on Windows is
|
||||
DirectWrite).
|
||||
- Porting the `src/os` layers to Linux. This includes core operating system
|
||||
abstraction (virtual memory allocation, threading and synchronization
|
||||
primitives, and so on), and graphical operating system abstraction (windows,
|
||||
input events, and so on).
|
||||
If you've installed the GCC tooling required, you can run:
|
||||
|
||||
Once the above list is complete, and once every part is rock solid, the Windows
|
||||
debugging experience we'll have worked diligently to create will also be
|
||||
available natively on Linux machines.
|
||||
```
|
||||
gcc --version && gcc-ar --version
|
||||
```
|
||||
|
||||
### And Beyond!
|
||||
You should see output similar to the following:
|
||||
|
||||
There are several directions we might take after these two major phases,
|
||||
like remote debugging, porting to different architectures, further improving
|
||||
the debugger's features (like improving the visualization engine), and so on.
|
||||
But for now, we're mostly focused on those first two phases.
|
||||
```
|
||||
gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
GNU ar (GNU Binutils for Ubuntu) 2.42
|
||||
Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
This program is free software; you may redistribute it under the terms of
|
||||
the GNU General Public License version 3 or (at your option) any later version.
|
||||
This program has absolutely no warranty.
|
||||
```
|
||||
|
||||
### 2. Installing Dependencies
|
||||
|
||||
The debugger project relies on a few dynamically linked libraries being present
|
||||
on the system:
|
||||
|
||||
- `libfreetype`
|
||||
- `libx11`
|
||||
- `libxext`
|
||||
- `libxfixes`
|
||||
- `libxrandr`
|
||||
- `libgl`
|
||||
- `libegl`
|
||||
|
||||
You'll need the development packages for them in order to build. These can be
|
||||
installed using one of the following commands, depending on your distribution:
|
||||
|
||||
#### Ubuntu / Debian / Mint
|
||||
|
||||
```
|
||||
sudo apt install -y libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxrandr-dev libgl-dev libegl-dev
|
||||
```
|
||||
|
||||
#### Arch / Manjaro
|
||||
|
||||
```
|
||||
sudo pacman -S --needed freetype2 libx11 libxext libxfixes libxrandr libglvnd
|
||||
```
|
||||
|
||||
### 3. Building
|
||||
|
||||
To build, `cd` to the root directory of the codebase, and run the `build.sh`
|
||||
script:
|
||||
|
||||
```
|
||||
./build.sh
|
||||
```
|
||||
|
||||
You should see something similar to the following output:
|
||||
|
||||
```
|
||||
[clang compile]
|
||||
[debug mode]
|
||||
[building metagen]
|
||||
searching /mnt/c/devel/raddebugger/src... 562 files found
|
||||
parsing metadesk... 23 metadesk files parsed
|
||||
gathering tables... 138 tables found
|
||||
generating layer code...
|
||||
```
|
||||
|
||||
If everything worked correctly, there will be a `build` folder in the root
|
||||
level of the codebase, and it will contain a freshly-built `raddbg` binary.
|
||||
|
||||
This `raddbg` will have been built in **debug mode**, which is not built with
|
||||
optimizations, and may perform worse. To produce a **release mode executable**,
|
||||
run `build.sh` with a `release` argument:
|
||||
|
||||
```
|
||||
./build.sh release
|
||||
```
|
||||
|
||||
This build will take significantly longer.
|
||||
|
||||
By default, `build.sh` only builds the debugger if no arguments (or just
|
||||
`release`) are passed, but additional arguments can be passed to build the RAD
|
||||
Linker, or the `radbin` CLI binary file utility:
|
||||
|
||||
```
|
||||
./build.sh radlink release
|
||||
./build.sh radbin release
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,10 +27,12 @@ cd /D "%~dp0"
|
||||
:: - `ubsan`: enable undefined-behavior sanitizer
|
||||
:: - `telemetry`: enable RAD telemetry profiling support
|
||||
:: - `spall`: enable spall profiling support
|
||||
:: - `oodle`: enable Oodle from local\oodle2*\win or an explicit OODLE_SDK_DIR
|
||||
|
||||
:: --- Unpack Arguments -------------------------------------------------------
|
||||
for %%a in (%*) do set "%%~a=1"
|
||||
if not "%msvc%"=="1" if not "%clang%"=="1" set msvc=1
|
||||
if not "%release%"=="1" if not "%debug%"=="1" set debug_implicit=1
|
||||
if not "%release%"=="1" set debug=1
|
||||
if "%debug%"=="1" set release=0 && echo [debug mode]
|
||||
if "%release%"=="1" set debug=0 && echo [release mode]
|
||||
@@ -67,6 +69,13 @@ if "%pgo%"=="1" (
|
||||
)
|
||||
)
|
||||
|
||||
:: --- Mix Git Commit ID ------------------------------------------------------
|
||||
git rev-parse --is-inside-work-tree >nul 2>&1 && set in_git_tree=1
|
||||
if "%in_git_tree%"=="1" (
|
||||
for /f %%i in ('call git describe --always --dirty') do set auto_compile_flags=!auto_compile_flags! -DBUILD_GIT_HASH=\"%%i\"
|
||||
for /f %%i in ('call git rev-parse HEAD') do set auto_compile_flags=!auto_compile_flags! -DBUILD_GIT_HASH_FULL=\"%%i\"
|
||||
)
|
||||
|
||||
:: --- Compile/Link Line Definitions ------------------------------------------
|
||||
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 /Zc:preprocessor
|
||||
set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags%
|
||||
@@ -97,6 +106,10 @@ if "%msvc%"=="1" set rc=call rc
|
||||
if "%clang%"=="1" set rc=call llvm-rc
|
||||
if "%msvc%"=="1" set link_dll=/link /DLL
|
||||
if "%clang%"=="1" set link_dll=-Xlinker -DLL
|
||||
if "%msvc%"=="1" set asm=call ml64 -nologo -c -Zi -Fo
|
||||
if "%clang%"=="1" set asm=call llvm-ml -m64 -nologo -c -Fo
|
||||
if "%msvc%"=="1" set mklib=call lib -nologo
|
||||
if "%clang%"=="1" set mklib=call llvm-lib
|
||||
|
||||
:: --- Choose Compile/Link Lines ----------------------------------------------
|
||||
if "%msvc%"=="1" set compile_debug=%cl_debug%
|
||||
@@ -121,12 +134,9 @@ pushd build
|
||||
%rc% /nologo /fo logo.res ..\data\logo.rc || exit /b 1
|
||||
popd
|
||||
|
||||
:: --- Get Current Git Commit Id ----------------------------------------------
|
||||
for /f %%i in ('call git describe --always --dirty') do set compile=%compile% -DBUILD_GIT_HASH=\"%%i\"
|
||||
for /f %%i in ('call git rev-parse HEAD') do set compile=%compile% -DBUILD_GIT_HASH_FULL=\"%%i\"
|
||||
|
||||
:: --- Build & Run Metaprogram ------------------------------------------------
|
||||
pushd build
|
||||
if not exist metagen.exe set meta=1
|
||||
if "%meta%"=="1" (
|
||||
echo [building metagen]
|
||||
%compile_debug% ..\src\metagen\metagen_main.c %compile_link% %out%metagen.exe || exit /b 1
|
||||
@@ -137,11 +147,56 @@ if "%no_meta%"=="" if exist metagen.exe (
|
||||
)
|
||||
popd
|
||||
|
||||
:: --- Assemble BLAKE3 --------------------------------------------------------
|
||||
if not exist build\blake3.lib if "%VSCMD_ARG_TGT_ARCH%" equ "x64" (
|
||||
echo [assembling blake3]
|
||||
pushd build
|
||||
%asm% blake3_sse2_x86-64_windows_msvc.obj ..\src\third_party\blake3\blake3_sse2_x86-64_windows_msvc.asm || exit /b 1
|
||||
%asm% blake3_sse41_x86-64_windows_msvc.obj ..\src\third_party\blake3\blake3_sse41_x86-64_windows_msvc.asm || exit /b 1
|
||||
%asm% blake3_avx2_x86-64_windows_msvc.obj ..\src\third_party\blake3\blake3_avx2_x86-64_windows_msvc.asm || exit /b 1
|
||||
%asm% blake3_avx512_x86-64_windows_msvc.obj ..\src\third_party\blake3\blake3_avx512_x86-64_windows_msvc.asm || exit /b 1
|
||||
%mklib% -out:blake3.lib blake3_*_msvc.obj || exit /b 1
|
||||
popd
|
||||
)
|
||||
|
||||
:: --- Set up Oodle SDK -------------------------------------------------------
|
||||
if "%oodle%"=="1" (
|
||||
set "oodle_sdk_path=%OODLE_SDK_DIR%"
|
||||
if not defined oodle_sdk_path (
|
||||
for /d %%d in ("%~dp0local\oodle2*") do (
|
||||
if exist "%%~fd\win\include\oodle2.h" (
|
||||
if defined oodle_sdk_path (
|
||||
echo Multiple Oodle SDKs found: "!oodle_sdk_path!" and "%%~fd\win"
|
||||
echo Set OODLE_SDK_DIR to select the SDK root.
|
||||
exit /b 1
|
||||
)
|
||||
set "oodle_sdk_path=%%~fd\win"
|
||||
)
|
||||
)
|
||||
)
|
||||
if not defined oodle_sdk_path (
|
||||
echo Oodle SDK not found. Put an oodle2* SDK with a win subdirectory in "%~dp0local" or set OODLE_SDK_DIR.
|
||||
exit /b 1
|
||||
)
|
||||
if exist "!oodle_sdk_path!\win\include\oodle2.h" set "oodle_sdk_path=!oodle_sdk_path!\win"
|
||||
for %%d in ("!oodle_sdk_path!") do set "oodle_sdk_path=%%~fd"
|
||||
if not exist "!oodle_sdk_path!\include\oodle2.h" (
|
||||
echo Oodle SDK directory "!oodle_sdk_path!" must contain include\oodle2.h
|
||||
exit /b 1
|
||||
)
|
||||
echo [Oodle SDK: !oodle_sdk_path!]
|
||||
set "compile=!compile! -DOODLE_SDK=1 -I"!oodle_sdk_path!\include""
|
||||
if exist "!oodle_sdk_path!\redist\oo2core_*_win64.dll" (
|
||||
copy /y "!oodle_sdk_path!\redist\oo2core_*_win64.dll" "%~dp0build\" >nul || exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
:: --- Build Everything (@build_targets) --------------------------------------
|
||||
pushd build
|
||||
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
|
||||
if "%raddbg_non_graphical%"=="1" set didbuild=1 && %compile% -DWM_STUB=1 -DR_BACKEND=R_BACKEND_STUB ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg_non_graphical.exe || exit /b 1
|
||||
if "%com_shim%"=="1" set didbuild=1 && %compile% ..\src\com_shim\com_shim_main.c %compile_link% %out%com_shim.exe || exit /b 1
|
||||
if "%raddbg_server%"=="1" set didbuild=1 && %compile% ..\src\raddbg_server\raddbg_server_main.c %compile_link% %out%raddbg_server.exe || exit /b 1
|
||||
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
|
||||
if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1
|
||||
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
|
||||
@@ -187,3 +242,8 @@ if "%pgo_run%"=="1" (
|
||||
)
|
||||
goto restart
|
||||
)
|
||||
|
||||
:: --- Warn On Debug Builds (if debug not explicitly specified) ---------------
|
||||
if "%debug_implicit%"=="1" (
|
||||
echo [INFO] Debug build complete. For a faster build, call this script with the `release` argument; this will take significantly longer than a debug build.
|
||||
)
|
||||
@@ -3,23 +3,24 @@ set -eu
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# --- Unpack Arguments --------------------------------------------------------
|
||||
auto_compile_flags=""
|
||||
for arg in "$@"; do declare $arg='1'; done
|
||||
if [[ "$#" == "0" ]]; then raddbg='1'; fi
|
||||
|
||||
cc_sanitize=""
|
||||
if [[ "$#" == "1" && "${release:-0}" == "1" ]]; then raddbg='1'; fi
|
||||
if [[ "${asan:-0}" == "1" ]]; then
|
||||
echo "[asan enabled]"
|
||||
cc_sanitize="-fsanitize=address"
|
||||
auto_compile_flags="$auto_compile_flags -fsanitize=address"
|
||||
fi
|
||||
|
||||
# --- Get Current Git Commit Id -----------------------------------------------
|
||||
git_hash=$(git describe --always --dirty)
|
||||
git_hash_full=$(git rev-parse HEAD)
|
||||
# --- Mix Git Commit ID -------------------------------------------------------
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
auto_compile_flags="$auto_compile_flags -DBUILD_GIT_HASH=\"$(git describe --always --dirty)\" -DBUILD_GIT_HASH_FULL=$(git rev-parse HEAD)"
|
||||
fi
|
||||
|
||||
# --- Compile/Link Line Definitions -------------------------------------------
|
||||
cc_cflags_gcc=""
|
||||
cc_cflags_clang=${cc_sanitize}" -fdiagnostics-absolute-paths -Wno-for-loop-analysis -Wno-incompatible-pointer-types-discards-qualifiers -Wno-initializer-overrides -Wno-compare-distinct-pointer-types -Wno-single-bit-bitfield-constant-conversion -Wno-deprecated-declarations -Wno-writable-strings -Wno-unknown-warning-option -Wno-deprecated-register -Wno-unused-local-typedef -msse2"
|
||||
cc_common="-mcx16 -I../src/ -I../local/ -D_GNU_SOURCE -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wall -Wno-missing-braces -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-value -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
|
||||
cc_cflags_clang=" -fdiagnostics-absolute-paths -Wno-for-loop-analysis -Wno-incompatible-pointer-types-discards-qualifiers -Wno-initializer-overrides -Wno-compare-distinct-pointer-types -Wno-single-bit-bitfield-constant-conversion -Wno-deprecated-declarations -Wno-writable-strings -Wno-unknown-warning-option -Wno-deprecated-register -Wno-unused-local-typedef -msse2"
|
||||
cc_common=${auto_compile_flags}"-mcx16 -I../src/ -I../local/ -D_GNU_SOURCE -g -Wall -Wno-missing-braces -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-value -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
|
||||
cc_debug="-g -O0 -DBUILD_DEBUG=1 ${cc_common}"
|
||||
cc_release="-g -O2 -DBUILD_DEBUG=0 ${cc_common}"
|
||||
cc_link="-lpthread -lm -lrt -ldl"
|
||||
@@ -28,50 +29,111 @@ cc_link="-lpthread -lm -lrt -ldl"
|
||||
cc_link_dll="-fPIC"
|
||||
|
||||
# --- External Libraries ------------------------------------------------------
|
||||
# sudo apt install -y pkg-config libfreetype6-dev libx11-dev libxext-dev libgl-dev libegl-dev
|
||||
# sudo apt install -y pkg-config libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxrandr-dev libgl-dev libegl-dev
|
||||
if [[ -x "$(command -v pkg-config)" ]]; then
|
||||
cc_font_provider="$(pkg-config --cflags --libs freetype2)"
|
||||
cc_os_gfx="$(pkg-config --cflags --libs x11 xext)"
|
||||
cc_os_gfx="$(pkg-config --cflags --libs x11 xext xfixes xrandr)"
|
||||
cc_render="$(pkg-config --cflags --libs gl egl)"
|
||||
else
|
||||
cc_font_provider="-I/usr/include/freetype2 -lfreetype"
|
||||
cc_os_gfx="-lX11 -lXext"
|
||||
cc_os_gfx="-lX11 -lXext -lXfixes -lXrandr"
|
||||
cc_render="-lGL -lEGL"
|
||||
fi
|
||||
|
||||
# --- Icons -------------------------------------------------------------------
|
||||
cc_icon="-DLNX_WM_ICON=1"
|
||||
|
||||
# --- Choose Compile/Link Lines -----------------------------------------------
|
||||
if [[ "${gcc:-0}" == "1" ]]; then compiler="${CC:-gcc} $cc_cflags_gcc"; echo "[gcc compile]";
|
||||
elif [[ "${clang:-1}" == "1" ]]; then compiler="${CC:-clang} $cc_cflags_clang"; echo "[clang compile]";
|
||||
if [[ "${gcc:-0}" == "1" ]]; then compiler="${CC:-gcc} $cc_cflags_gcc"; ar="${AR:-ar}"; echo "[gcc compile]";
|
||||
elif [[ "${clang:-1}" == "1" ]]; then compiler="${CC:-clang} $cc_cflags_clang"; ar="${AR:-llvm-ar}"; echo "[clang compile]";
|
||||
fi
|
||||
if [[ "${release:-0}" == "1" ]]; then echo "[release mode]"; compile="$compiler $cc_release";
|
||||
elif [[ "${debug:-1}" == "1" ]]; then echo "[debug mode]"; compile="$compiler $cc_debug";
|
||||
fi
|
||||
|
||||
oodle_flags=()
|
||||
compile() {
|
||||
$compile "${oodle_flags[@]}" -Wl,--start-group "$@" blake3.a -latomic -Wl,--end-group
|
||||
}
|
||||
|
||||
# --- Prep Directories --------------------------------------------------------
|
||||
mkdir -p build local
|
||||
|
||||
# --- Build & Run Metaprogram -------------------------------------------------
|
||||
if [[ "${no_meta:-0}" == "0" ]]
|
||||
then
|
||||
echo "[building metagen]"
|
||||
cd build
|
||||
if [[ ! -f metagen ]]; then meta='1'; fi
|
||||
if [[ "${meta:-0}" == "1" ]]; then
|
||||
echo "[building metagen]"
|
||||
$compiler $cc_debug ../src/metagen/metagen_main.c $cc_link -o metagen
|
||||
fi
|
||||
if [[ ! -v no_meta ]]; then
|
||||
./metagen
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# --- Assemble BLAKE3 ---------------------------------------------------------
|
||||
if [[ ! -f "build/blake3.a" ]]; then
|
||||
echo "[assembling blake3]"
|
||||
$compiler -c -g -o build/blake3_sse2_x86-64_unix.o src/third_party/blake3/blake3_sse2_x86-64_unix.S
|
||||
$compiler -c -g -o build/blake3_sse41_x86-64_unix.o src/third_party/blake3/blake3_sse41_x86-64_unix.S
|
||||
$compiler -c -g -o build/blake3_avx2_x86-64_unix.o src/third_party/blake3/blake3_avx2_x86-64_unix.S
|
||||
$compiler -c -g -o build/blake3_avx512_x86-64_unix.o src/third_party/blake3/blake3_avx512_x86-64_unix.S
|
||||
$ar rs build/blake3.a build/blake3_*_unix.o
|
||||
fi
|
||||
|
||||
# --- Set up Oodle SDK -------------------------------------------------------
|
||||
if [[ "${oodle:-0}" == "1" ]]; then
|
||||
oodle_sdk_path="${OODLE_SDK_DIR:-}"
|
||||
if [[ -z "$oodle_sdk_path" ]]; then
|
||||
for sdk in "$PWD"/local/oodle2*; do
|
||||
if [[ -f "$sdk/linux/include/oodle2.h" ]]; then
|
||||
if [[ -n "$oodle_sdk_path" ]]; then
|
||||
echo "Multiple Oodle SDKs found: $oodle_sdk_path and $sdk/linux" >&2
|
||||
echo "Set OODLE_SDK_DIR to select the SDK root." >&2
|
||||
exit 1
|
||||
fi
|
||||
oodle_sdk_path="$sdk/linux"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ -z "$oodle_sdk_path" ]]; then
|
||||
echo "Oodle SDK not found. Put an oodle2* SDK with a linux subdirectory in $PWD/local or set OODLE_SDK_DIR." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -f "$oodle_sdk_path/linux/include/oodle2.h" ]]; then
|
||||
oodle_sdk_path="$oodle_sdk_path/linux"
|
||||
fi
|
||||
if [[ ! -f "$oodle_sdk_path/include/oodle2.h" ]]; then
|
||||
echo "Oodle SDK directory '$oodle_sdk_path' must contain include/oodle2.h" >&2
|
||||
exit 1
|
||||
fi
|
||||
oodle_sdk_path="$(cd "$oodle_sdk_path" && pwd)"
|
||||
echo "[Oodle SDK: $oodle_sdk_path]"
|
||||
# Keep the include path as one argument, including when it contains spaces.
|
||||
oodle_flags=(-DOODLE_SDK=1 "-I$oodle_sdk_path/include")
|
||||
for library in "$oodle_sdk_path"/lib/liboo2corelinux64.so "$oodle_sdk_path"/lib/liboo2corelinux64.so.*; do
|
||||
if [[ -f "$library" ]]; then
|
||||
cp -- "$library" "$PWD/build/"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# --- Build Everything (@build_targets) ---------------------------------------
|
||||
cd build
|
||||
if [[ "${raddbg:-0}" == "1" ]]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c $cc_link $cc_os_gfx $cc_render $cc_font_provider -o raddbg; fi
|
||||
if [[ "${raddbg_non_graphical:-0}" == "1" ]]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c -DWM_STUB=1 -DR_BACKEND=R_BACKEND_STUB $cc_link $cc_os_gfx $cc_render $cc_font_provider -o raddbg_non_graphical; fi
|
||||
if [[ "${radbin:-0}" == "1" ]]; then didbuild=1 && $compile ../src/radbin/radbin_main.c $cc_link -o radbin; fi
|
||||
if [[ "${radlink:-0}" == "1" ]]; then didbuild=1 && $compile ../src/linker/lnk.c $cc_link -o radlink; fi
|
||||
if [[ "${torture:-0}" == "1" ]]; then didbuild=1 && $compile ../src/torture/torture_main.c $cc_link $cc_os_gfx $cc_render $cc_font_provider -o torture; fi
|
||||
if [[ "${raddbg:-0}" == "1" ]]; then didbuild=1 && compile ../src/raddbg/raddbg_main.c $cc_icon $cc_link $cc_os_gfx $cc_render $cc_font_provider -o raddbg; fi
|
||||
if [[ "${raddbg_non_graphical:-0}" == "1" ]]; then didbuild=1 && compile ../src/raddbg/raddbg_main.c -DWM_STUB=1 -DR_BACKEND=R_BACKEND_STUB $cc_link $cc_os_gfx $cc_render $cc_font_provider -o raddbg_non_graphical; fi
|
||||
if [[ "${radbin:-0}" == "1" ]]; then didbuild=1 && compile ../src/radbin/radbin_main.c $cc_link -o radbin; fi
|
||||
if [[ "${radlink:-0}" == "1" ]]; then didbuild=1 && compile ../src/linker/lnk.c $cc_link -o radlink; fi
|
||||
if [[ "${torture:-0}" == "1" ]]; then didbuild=1 && compile ../src/torture/torture_main.c $cc_link $cc_os_gfx $cc_render $cc_font_provider -o torture; fi
|
||||
cd ..
|
||||
|
||||
# --- Warn On No Builds -------------------------------------------------------
|
||||
if [[ "${didbuild:-0}" == "0" ]]
|
||||
then
|
||||
if [[ "${didbuild:-0}" == "0" ]]; then
|
||||
echo "[WARNING] no valid build target specified; must use build target names as arguments to this script, like \`./build.sh raddbg\` or \`./build.sh radlink\`."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Warn On Debug Builds (if debug not explicitly specified) ----------------
|
||||
if [[ ! -v debug && ! -v release ]]; then
|
||||
echo "[INFO] Debug build complete. For a faster build, call this script with the \`release\` argument (this will take significantly longer than a debug build)."
|
||||
fi
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal LNX_DMN_Process *
|
||||
lnx_dmn_event_attach(Arena *arena, DMN_EventList *events, pid_t pid)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// create process
|
||||
LNX_DMN_Process *process = lnx_dmn_event_create_process(arena, events, pid, 0, LNX_DMN_CreateProcessFlag_DebugSubprocesses|LNX_DMN_CreateProcessFlag_Rebased);
|
||||
|
||||
// extract threads from /proc/pid/task
|
||||
{
|
||||
String8 task_path = str8f(scratch.arena, "/proc/%d/task", pid);
|
||||
DIR *task_dirp = opendir((char *)task_path.str);
|
||||
if(task_dirp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct dirent *dirent = readdir(task_dirp);
|
||||
if(dirent == 0) { break; }
|
||||
|
||||
String8 tid_str = str8_cstring_capped(dirent->d_name, dirent->d_name + NAME_MAX);
|
||||
if(str8_match(tid_str, str8_lit(".."), 0) || str8_match(tid_str, str8_lit("."), 0)) { continue; }
|
||||
U64 tid_64 = u64_from_str8(tid_str, 10);
|
||||
pid_t tid = (pid_t)tid_64;
|
||||
AssertAlways(tid == tid_64);
|
||||
|
||||
if(tid == pid) { continue; } // main thread was created during create process sequence
|
||||
lnx_dmn_event_create_thread(arena, events, process, tid);
|
||||
}
|
||||
|
||||
LNX_RETRY_ON_EINTR(closedir(task_dirp));
|
||||
}
|
||||
}
|
||||
|
||||
// extract modules from r_debug
|
||||
{
|
||||
B32 is_64bit = process->ctx->dl_class == ELF_Class_64;
|
||||
GNU_RDebugInfoList rdebug_list = gnu_parse_rdebug(scratch.arena, is_64bit, process->ctx->rdebug_vaddr, lnx_dmn_machine_op_mem_read, &process->fd);
|
||||
U64 name_space_id = 0;
|
||||
for EachNode(rdebug_n, GNU_RDebugInfoNode, rdebug_list.first)
|
||||
{
|
||||
lnx_dmn_event_load_module(arena, events, process->first_thread, name_space_id, rdebug_n->v.r_map);
|
||||
name_space_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// handshake complete
|
||||
lnx_dmn_push_event_handshake_complete(arena, events, process);
|
||||
|
||||
scratch_end(scratch);
|
||||
return process;
|
||||
}
|
||||
+2
-2
@@ -49,7 +49,7 @@ commands =
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build torture && build ryan_scratch && pushd build && torture eval2/* && ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg raddbg_server telemetry debug", .linux = "./build.sh raddbg debug meta", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [raddbg wsl]
|
||||
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
@@ -68,7 +68,7 @@ commands =
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: running target
|
||||
.f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f3 = { .win = "raddbg_stable --ipc run", .linux = "cd build && ./raddbg && cd ..", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f3 = { .win = "build torture", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f3 = { .win = "wsl ./build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f3 = { .win = "pushd build && raddbg --user:dev.raddbg_user && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
Regular → Executable
+23
-42
@@ -1,75 +1,56 @@
|
||||
// raddbg 0.9.28 project file
|
||||
// raddbg 0.9.30 project file
|
||||
|
||||
name: "The RAD Debugger"
|
||||
target:
|
||||
{
|
||||
executable: "build/raddbg.exe"
|
||||
working_directory: "../raddebugger"
|
||||
arguments: "--user:C:/devel/raddebugger/build/raddbg_test.user"
|
||||
working_directory: build
|
||||
arguments: "--user:raddbg_test.user"
|
||||
debug_subprocesses: 0
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/raddbg.exe"
|
||||
working_directory: "../raddebugger"
|
||||
arguments: "--user:test123"
|
||||
debug_subprocesses: 0
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/mule_main.exe"
|
||||
executable: "build/raddbg_server.exe"
|
||||
working_directory: build
|
||||
output_label: output_a
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/torture.exe"
|
||||
working_directory: build
|
||||
arguments: "eval2/*"
|
||||
debug_subprocesses: 1
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/metagen.exe"
|
||||
working_directory: build
|
||||
enabled: 1
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/radbin.exe"
|
||||
executable: "build/mule_main.exe"
|
||||
working_directory: build
|
||||
arguments: "--rdi raddbg"
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/release_version/raddbg.exe"
|
||||
working_directory: "build/release_version"
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/radbin.exe"
|
||||
executable: "build/torture.exe"
|
||||
working_directory: build
|
||||
arguments: "--rdi fat.so --capture"
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/radbin.exe"
|
||||
working_directory: build
|
||||
arguments: "--rdi fat.debug --capture"
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/radbin.exe"
|
||||
working_directory: build
|
||||
arguments: "--rdi raddbg"
|
||||
arguments: *
|
||||
}
|
||||
watch_pin: expression: tag_hash_slots
|
||||
target:
|
||||
{
|
||||
executable: "build/ryan_scratch.exe"
|
||||
working_directory: build
|
||||
enabled: 1
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "../../Program Files/SuperTux/bin/supertux2.exe"
|
||||
working_directory: "../../Program Files/SuperTux/bin"
|
||||
executable: "build/raddbg"
|
||||
working_directory: build
|
||||
arguments: "--user:raddbg_test.user"
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "build/metagen"
|
||||
working_directory: build
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "../jai/examples/invaders/invaders"
|
||||
working_directory: "../jai/examples/invaders"
|
||||
}
|
||||
linux_sigpipe: 1
|
||||
@@ -681,6 +681,7 @@ ac_async_tick(void)
|
||||
internal void
|
||||
ac_cancel_thread_entry_point(void *p)
|
||||
{
|
||||
ThreadNameF("ac_cancel_thread");
|
||||
for(;;)
|
||||
{
|
||||
sleep_ms(50);
|
||||
|
||||
+11
-11
@@ -69,13 +69,13 @@ arena_alloc_(ArenaParams *params)
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
wm_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
#if defined(SHELL_H)
|
||||
sh_message(1, s("Fatal Allocation Failure"), s("Unexpected memory allocation failure."));
|
||||
#endif
|
||||
abort_self(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
@@ -227,8 +227,8 @@ arena_push(Arena *arena, U64 size, U64 align, B32 zero)
|
||||
|
||||
if(new_block == 0)
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
U64 res_size = arena->res_size;
|
||||
U64 cmt_size = arena->cmt_size;
|
||||
if(size + ARENA_HEADER_SIZE > res_size)
|
||||
{
|
||||
res_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
|
||||
@@ -236,9 +236,9 @@ arena_push(Arena *arena, U64 size, U64 align, B32 zero)
|
||||
}
|
||||
new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags,
|
||||
.allocation_site_file = current->allocation_site_file,
|
||||
.allocation_site_line = current->allocation_site_line);
|
||||
.flags = arena->flags,
|
||||
.allocation_site_file = arena->allocation_site_file,
|
||||
.allocation_site_line = arena->allocation_site_line);
|
||||
|
||||
size_to_zero = 0;
|
||||
}
|
||||
@@ -295,13 +295,13 @@ arena_push(Arena *arena, U64 size, U64 align, B32 zero)
|
||||
#endif
|
||||
|
||||
// rjf: panic on failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(result == 0))
|
||||
{
|
||||
wm_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
#if defined(SHELL_H)
|
||||
sh_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
#endif
|
||||
abort_self(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 28
|
||||
# define BUILD_VERSION_PATCH 30
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
|
||||
@@ -659,39 +659,6 @@ wrapped_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 rea
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64
|
||||
u64_array_bsearch(U64 *arr, U64 count, U64 value)
|
||||
{
|
||||
if(count > 1 && arr[0] <= value && value < arr[count-1])
|
||||
{
|
||||
U64 l = 0;
|
||||
U64 r = count - 1;
|
||||
for(; l <= r; )
|
||||
{
|
||||
U64 m = l + (r - l) / 2;
|
||||
if(arr[m] == value)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
else if(arr[m] < value)
|
||||
{
|
||||
l = m + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = m - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (count == 1 && arr[0] == value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return max_U64;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U32
|
||||
idx_of_zero_byte64(U8 *ptr, U64 size)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define STB_SPRINTF_DECORATE(name) raddbg_##name
|
||||
#define STB_SPRINTF_STATIC
|
||||
#include "third_party/stb/stb_sprintf.h"
|
||||
#include "third_party/radsort/radsort.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Codebase Keywords
|
||||
@@ -54,7 +55,7 @@
|
||||
#if COMPILER_MSVC
|
||||
# define force_inline __forceinline
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
# define force_inline __attribute__((always_inline))
|
||||
# define force_inline inline __attribute__((always_inline))
|
||||
#else
|
||||
# error force_inline not defined for this compiler.
|
||||
#endif
|
||||
@@ -199,7 +200,7 @@
|
||||
#define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1))
|
||||
#define EachInRange(it, range) (U64 it = (range).min; it < (range).max; it += 1)
|
||||
#define EachNode(it, T, first) (T *it = first; it != 0; it = it->next)
|
||||
#define EachBit(it, flags) (U64 (_i_) = (flags), it = (flags) & -(flags); (_i_) != 0; (_i_) &= ((_i_) - 1), it = (flags) & -(flags))
|
||||
#define EachBit(it, flags) (U64 (_i_) = (flags), it = (_i_) & -(_i_); (_i_) != 0; (_i_) &= ((_i_) - 1), it = (_i_) & -(_i_))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory Operation Macros
|
||||
@@ -241,8 +242,8 @@
|
||||
#else
|
||||
# define Assert(x) (void)(x)
|
||||
#endif
|
||||
#define InvalidPath Assert(!"Invalid Path!")
|
||||
#define NotImplemented Assert(!"Not Implemented!")
|
||||
#define InvalidPath AssertAlways(!"Invalid Path!")
|
||||
#define NotImplemented AssertAlways(!"Not Implemented!")
|
||||
#define NoOp ((void)0)
|
||||
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
|
||||
|
||||
@@ -695,6 +696,7 @@ enum
|
||||
AccessFlag_ShareRead = (1<<4),
|
||||
AccessFlag_ShareWrite = (1<<5),
|
||||
AccessFlag_Inherited = (1<<6),
|
||||
AccessFlag_CreateNew = (1<<7), // fail if file already exists; never truncates
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -1123,10 +1125,6 @@ internal U64 wrapped_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U32 idx_of_zero_byte64(U8 *ptr, U64 size); // size must be exactly 8 bytes
|
||||
internal U64 index_of_zero_u32(U32 *ptr, U64 count);
|
||||
internal U64 index_of_zero_u64(U64 *ptr, U64 count);
|
||||
|
||||
@@ -58,6 +58,9 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
}
|
||||
|
||||
//- rjf: initialize all included layers
|
||||
#if defined(SOCKET_H) && !defined(SOCKET_INIT_MANUAL)
|
||||
sock_init();
|
||||
#endif
|
||||
#if defined(HTTP_H) && !defined(HTTP_INIT_MANUAL)
|
||||
http_init();
|
||||
#endif
|
||||
@@ -79,7 +82,7 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
#if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL)
|
||||
di_init(&cmdline);
|
||||
#endif
|
||||
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
|
||||
#if defined(DEMON_H) && !defined(DMN_INIT_MANUAL)
|
||||
dmn_init();
|
||||
#endif
|
||||
#if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL)
|
||||
@@ -222,6 +225,9 @@ async_thread_entry_point(void *params)
|
||||
#if defined(FILE_STREAM_H)
|
||||
fs_async_tick();
|
||||
#endif
|
||||
#if defined(SOCKET_H)
|
||||
sock_async_tick();
|
||||
#endif
|
||||
#if defined(HTTP_H)
|
||||
http_async_tick();
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,13 @@ struct File
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct FilePair FilePair;
|
||||
struct FilePair
|
||||
{
|
||||
File read;
|
||||
File write;
|
||||
};
|
||||
|
||||
typedef struct FileMap FileMap;
|
||||
struct FileMap
|
||||
{
|
||||
@@ -70,6 +77,11 @@ internal String8 file_read_cstring(Arena *arena, File file, U64 off);
|
||||
//- rjf: files
|
||||
internal File file_open(AccessFlags flags, String8 path);
|
||||
internal void file_close(File file);
|
||||
internal FilePair file_pipe_make(B32 read_inherited, B32 write_inherited);
|
||||
internal U64 file_pipe_read(File file, void *out_data, U64 size);
|
||||
internal U64 file_pipe_write(File file, void *data, U64 size);
|
||||
internal U64 file_pipe_bytes_available(File file);
|
||||
internal B32 file_pipe_is_end(File file);
|
||||
internal U64 file_read(File file, Rng1U64 rng, void *out_data);
|
||||
#define file_read_struct(f, off, ptr) file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr))
|
||||
internal U64 file_write(File file, Rng1U64 rng, void *data);
|
||||
@@ -77,9 +89,12 @@ internal B32 file_set_times(File file, DateTime time);
|
||||
internal FileProperties properties_from_file(File file);
|
||||
internal FileID id_from_file(File file);
|
||||
internal B32 file_reserve_size(File file, U64 size);
|
||||
internal B32 file_set_size(File file, U64 size);
|
||||
internal B32 file_flush(File file);
|
||||
internal B32 delete_file_at_path(String8 path);
|
||||
internal B32 copy_file_path(String8 dst, String8 src);
|
||||
internal B32 move_file_path(String8 dst, String8 src);
|
||||
internal B32 replace_file_path(String8 dst, String8 src);
|
||||
internal String8 full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 file_path_exists(String8 path);
|
||||
internal B32 folder_path_exists(String8 path);
|
||||
@@ -89,6 +104,7 @@ internal FileProperties properties_from_file_path(String8 path);
|
||||
internal FileMap file_map_open(AccessFlags flags, File file);
|
||||
internal void file_map_close(FileMap map);
|
||||
internal void * file_map_view_open(FileMap map, AccessFlags flags, Rng1U64 range);
|
||||
internal void * file_map_view_replace_placeholder(FileMap map, void *ptr, Rng1U64 range);
|
||||
internal void file_map_view_close(FileMap map, void *ptr, Rng1U64 range);
|
||||
|
||||
//- rjf: directory iteration
|
||||
|
||||
+1
-5
@@ -4,11 +4,7 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals/Thread-Locals
|
||||
|
||||
C_LINKAGE thread_static Log *log_active;
|
||||
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||
C_LINKAGE thread_static Log *log_active = 0;
|
||||
#endif
|
||||
|
||||
thread_static Log *log_active;
|
||||
String8 g_logs_folder;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -40,6 +40,7 @@ struct Log
|
||||
// Globals
|
||||
|
||||
extern String8 g_logs_folder;
|
||||
extern thread_static Log *log_active;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Creation/Selection
|
||||
|
||||
@@ -13,6 +13,20 @@ internal B32 commit_memory(void *ptr, U64 size);
|
||||
internal void decommit_memory(void *ptr, U64 size);
|
||||
internal void release_memory(void *ptr, U64 size);
|
||||
|
||||
// memory placeholders
|
||||
internal B32 memory_placeholders_supported(void);
|
||||
internal void *reserve_memory_placeholders(U64 size, U64 block_size);
|
||||
internal void release_memory_placeholders(void *ptr, U64 size, U64 block_size);
|
||||
internal B32 unmap_memory_preserve_placeholder(void *ptr, U64 size);
|
||||
internal B32 split_memory_placeholder(void *ptr, U64 size, U64 first_size);
|
||||
internal B32 coalesce_memory_placeholders(void *ptr, U64 size);
|
||||
union Rng1U64;
|
||||
internal void prefetch_memory_ranges(U64 count, union Rng1U64 *ranges);
|
||||
|
||||
// generic memory page fault handler (calls may run concurrently)
|
||||
typedef B32 MemoryReadFaultFunction(void *address, void *user_data);
|
||||
internal B32 memory_read_fault_handler_set(MemoryReadFaultFunction *func, void *user_data);
|
||||
|
||||
//- rjf: large pages
|
||||
internal void *reserve_memory_large(U64 size);
|
||||
internal B32 commit_memory_large(void *ptr, U64 size);
|
||||
|
||||
@@ -10,7 +10,7 @@ memory_map_push(Arena *arena, MemoryMap *map, Rng1U64 vaddr_range, void *data)
|
||||
MemoryMapRangeNode *n = push_array(arena, MemoryMapRangeNode, 1);
|
||||
n->v.vaddr_range = vaddr_range;
|
||||
n->v.base = data;
|
||||
SLLQueuePush(map->first_range, map->last_range, n);
|
||||
SLLQueuePushFront(map->first_range, map->last_range, n);
|
||||
}
|
||||
|
||||
internal U64
|
||||
|
||||
@@ -25,6 +25,12 @@ struct Process
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct ProcessGroup ProcessGroup;
|
||||
struct ProcessGroup
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct ProcessNode ProcessNode;
|
||||
struct ProcessNode
|
||||
{
|
||||
@@ -49,6 +55,8 @@ struct ProcessLaunchParams
|
||||
B32 inherit_env;
|
||||
B32 debug_subprocesses;
|
||||
B32 consoleless;
|
||||
B32 new_console;
|
||||
ProcessGroup process_group;
|
||||
File stdout_file;
|
||||
File stderr_file;
|
||||
File stdin_file;
|
||||
@@ -84,8 +92,15 @@ internal U32 get_process_start_time_unix(void);
|
||||
|
||||
internal Process process_launch(ProcessLaunchParams *params);
|
||||
internal U64 pid_from_process(Process process);
|
||||
internal B32 process_poll(Process process, U64 *exit_code_out);
|
||||
internal B32 process_is_active(Process process);
|
||||
internal B32 process_join(Process process, U64 endt_us, U64 *exit_code_out);
|
||||
internal void process_detach(Process process);
|
||||
internal B32 process_kill(Process process);
|
||||
internal B32 process_send_ctrl_c(Process process);
|
||||
|
||||
internal ProcessGroup process_group_make(B32 kill_on_close);
|
||||
internal B32 process_group_add(ProcessGroup group, Process process);
|
||||
internal void process_group_close(ProcessGroup group);
|
||||
|
||||
#endif // BASE_PROCESSES_H
|
||||
@@ -8,22 +8,22 @@ spall_begin(char *fmt, ...)
|
||||
if(spall_buffer.data == 0)
|
||||
{
|
||||
spall_buffer.length = MB(1);
|
||||
spall_buffer.data = os_reserve(spall_buffer.length);
|
||||
os_commit(spall_buffer.data, spall_buffer.length);
|
||||
spall_buffer.data = reserve_memory(spall_buffer.length);
|
||||
commit_memory(spall_buffer.data, spall_buffer.length);
|
||||
spall_buffer_init(&spall_profile, &spall_buffer);
|
||||
}
|
||||
if(spall_pid == 0)
|
||||
{
|
||||
spall_pid = os_get_process_info()->pid;
|
||||
spall_pid = get_process_info()->pid;
|
||||
}
|
||||
if(spall_tid == 0)
|
||||
{
|
||||
spall_tid = os_tid();
|
||||
spall_tid = tid();
|
||||
}
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
String8 string = str8fv(scratch.arena, fmt, args);
|
||||
spall_buffer_begin_ex(&spall_profile, &spall_buffer, string.str, string.size, now_time_us(), spall_tid, spall_pid);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
|
||||
@@ -46,22 +46,18 @@ ring_try_read(Ring *ring, U64 size, void *ptr)
|
||||
internal GuardedRing *
|
||||
guarded_ring_alloc(Arena *arena, U64 size)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
GuardedRing *gr = push_array(arena, GuardedRing, 1);
|
||||
gr->ring = make_ring(arena, size);
|
||||
gr->mutex = mutex_alloc();
|
||||
gr->cv = cond_var_alloc();
|
||||
ProfEnd();
|
||||
return gr;
|
||||
}
|
||||
|
||||
internal void
|
||||
guarded_ring_release(GuardedRing *ring)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
mutex_release(ring->mutex);
|
||||
cond_var_release(ring->cv);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
internal RingGuard
|
||||
|
||||
@@ -18,5 +18,6 @@ internal SharedMemory shared_memory_open(String8 name);
|
||||
internal void shared_memory_close(SharedMemory handle);
|
||||
internal void * shared_memory_view_open(SharedMemory handle, Rng1U64 range);
|
||||
internal void shared_memory_view_close(SharedMemory handle, void *ptr, Rng1U64 range);
|
||||
internal void * shared_memory_view_replace_placeholder(SharedMemory handle, void *ptr, Rng1U64 range, AccessFlags flags);
|
||||
|
||||
#endif // BASE_SHARED_MEMORY_H
|
||||
@@ -196,7 +196,7 @@ str32_zero(void)
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_cstring(char *c)
|
||||
str8_cstring(const char *c)
|
||||
{
|
||||
String8 result = {(U8*)c, cstring8_length((U8*)c)};
|
||||
return result;
|
||||
@@ -1856,7 +1856,7 @@ path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src)
|
||||
if(dst.size != 0 && dst_style == PathStyle_Relative)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 dst_from_src_absolute = push_str8f(scratch.arena, "%S/%S", src, dst);
|
||||
String8 dst_from_src_absolute = str8f(scratch.arena, "%S/%S", src, dst);
|
||||
String8List dst_from_src_absolute_parts = str8_split_path(scratch.arena, dst_from_src_absolute);
|
||||
PathStyle dst_from_src_absolute_style = path_style_from_str8(src);
|
||||
str8_path_list_resolve_dots_in_place(&dst_from_src_absolute_parts, dst_from_src_absolute_style);
|
||||
@@ -2487,7 +2487,7 @@ try_guid_from_string(String8 string, Guid *guid_out)
|
||||
guid_out->data1 = (U32)data1;
|
||||
guid_out->data2 = (U16)data2;
|
||||
guid_out->data3 = (U16)data3;
|
||||
U64 data4 = (data4_hi << 48) | data4_lo;
|
||||
U64 data4 = from_be_u64((data4_hi << 48) | data4_lo);
|
||||
MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4));
|
||||
is_parsed = 1;
|
||||
}
|
||||
@@ -3076,7 +3076,7 @@ str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out)
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
force_inline int
|
||||
internal force_inline int
|
||||
str8_compar(String8 a, String8 b, B32 ignore_case)
|
||||
{
|
||||
U64 size = Min(a.size, b.size);
|
||||
@@ -3095,19 +3095,19 @@ str8_compar(String8 a, String8 b, B32 ignore_case)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
force_inline int
|
||||
internal force_inline int
|
||||
str8_compar_ignore_case(const void *a, const void *b)
|
||||
{
|
||||
return str8_compar(*(String8*)a, *(String8*)b, 1);
|
||||
}
|
||||
|
||||
force_inline int
|
||||
internal force_inline int
|
||||
str8_compar_case_sensitive(const void *a, const void *b)
|
||||
{
|
||||
return str8_compar(*(String8*)a, *(String8*)b, 0);
|
||||
}
|
||||
|
||||
force_inline int
|
||||
internal force_inline int
|
||||
str8_is_before_case_sensitive(const void *a, const void *b)
|
||||
{
|
||||
int cmp = str8_compar_case_sensitive(a, b);
|
||||
|
||||
@@ -180,7 +180,7 @@ internal String16 str16_zero(void);
|
||||
internal String32 str32(U32 *str, U64 size);
|
||||
internal String32 str32_range(U32 *first, U32 *one_past_last);
|
||||
internal String32 str32_zero(void);
|
||||
internal String8 str8_cstring(char *c);
|
||||
internal String8 str8_cstring(const char *c);
|
||||
internal String16 str16_cstring(U16 *c);
|
||||
internal String32 str32_cstring(U32 *c);
|
||||
internal String8 str8_cstring_capped(void *cstr, void *cap);
|
||||
@@ -234,6 +234,8 @@ internal String8 str8f(Arena *arena, char *fmt, ...);
|
||||
#define push_str8f(arena, ...) str8f((arena), __VA_ARGS__)
|
||||
internal String8 push_cstr(Arena *arena, String8 str); // TODO(rjf): this is unnecessary - this is implied by `push_str8_copy`. need to remove.
|
||||
|
||||
#define sf(...) str8f((scratch.arena), __VA_ARGS__)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String <=> Integer Conversions
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ struct SystemInfo
|
||||
U64 page_size;
|
||||
U64 large_page_size;
|
||||
U64 allocation_granularity;
|
||||
U64 physical_memory_size;
|
||||
String8 machine_name;
|
||||
};
|
||||
|
||||
|
||||
+12
-5
@@ -32,16 +32,23 @@ test_exemplar_path(Arena *arena, TestCtx *ctx, String8 name)
|
||||
return path;
|
||||
}
|
||||
|
||||
internal String8
|
||||
test_layer_from_file_path(String8 file_path)
|
||||
{
|
||||
U64 src_min = str8_find_needle(file_path, 0, s("src/"), StringMatchFlag_SlashInsensitive);
|
||||
if (src_min == file_path.size) { return str8_zero(); }
|
||||
U64 src_max = src_min + str8_lit("src/").size;
|
||||
U64 layer_slash_max = str8_find_needle(file_path, src_max, s("/"), StringMatchFlag_SlashInsensitive);
|
||||
if (layer_slash_max == file_path.size) { return str8_zero(); }
|
||||
return str8_substr(file_path, r1u64(src_max, layer_slash_max));
|
||||
}
|
||||
|
||||
internal void
|
||||
base_register_test(char *func_name_cstr, TestFunctionType *fn, char *file_path_cstr, int line, int skip)
|
||||
{
|
||||
String8 file_path = str8_cstring(file_path_cstr);
|
||||
U64 src_min = str8_find_needle(file_path, 0, s("src/"), StringMatchFlag_SlashInsensitive);
|
||||
U64 src_max = src_min + str8_lit("src/").size;
|
||||
U64 layer_slash_max = str8_find_needle(file_path, src_max, s("/"), StringMatchFlag_SlashInsensitive);
|
||||
|
||||
TestInfo *t = &test_infos[test_infos_count++];
|
||||
t->layer = str8_substr(file_path, r1u64(src_max, layer_slash_max));
|
||||
t->layer = test_layer_from_file_path(file_path);
|
||||
t->label = str8_cstring(func_name_cstr);
|
||||
t->decl_line = line;
|
||||
t->skip = skip;
|
||||
|
||||
@@ -30,6 +30,7 @@ struct TestCtx
|
||||
String8 exemplars_path;
|
||||
String8 artifacts_path;
|
||||
String8 input_data_path;
|
||||
String8 user_data;
|
||||
TestResult *result_out;
|
||||
String8List *test_out;
|
||||
};
|
||||
@@ -46,6 +47,7 @@ struct TestInfo
|
||||
S64 decl_line;
|
||||
B32 skip;
|
||||
TestFunctionType *test_fn;
|
||||
String8 user_data;
|
||||
};
|
||||
|
||||
#if BUILD_TESTS
|
||||
@@ -58,6 +60,7 @@ internal String8 test_build_exe_path(Arena *arena, String8 name);
|
||||
internal String8 test_input_path(Arena *arena, TestCtx *ctx, String8 name);
|
||||
internal String8 test_input_exe_path(Arena *arena, TestCtx *ctx, String8 name);
|
||||
internal String8 test_exemplar_path(Arena *arena, TestCtx *ctx, String8 name);
|
||||
internal String8 test_layer_from_file_path(String8 file_path);
|
||||
internal void base_register_test(char *func_name, TestFunctionType *fn, char *file_path, int line, int skip);
|
||||
|
||||
#define AddTest(name, file_path, line, skip_, ...) \
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
C_LINKAGE thread_static TCTX *tctx_thread_local;
|
||||
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||
C_LINKAGE thread_static TCTX *tctx_thread_local = 0;
|
||||
#endif
|
||||
thread_static TCTX *tctx_thread_local;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Context Functions
|
||||
|
||||
@@ -79,6 +79,11 @@ struct TCTX
|
||||
U64 *progress_target_ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Globals
|
||||
|
||||
extern thread_static TCTX *tctx_thread_local;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Context Functions
|
||||
|
||||
|
||||
@@ -102,6 +102,17 @@ TEST(count_digits)
|
||||
T_Ok(count_digits_u64(999999, 10) == 6);
|
||||
}
|
||||
|
||||
TEST(guid_from_string)
|
||||
{
|
||||
String8 string = str8_lit("01234567-89AB-CDEF-0011-223344556677");
|
||||
U8 data4[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
Guid guid = {0};
|
||||
T_Ok(try_guid_from_string(string, &guid));
|
||||
T_Ok(guid.data1 == 0x01234567 && guid.data2 == 0x89AB && guid.data3 == 0xCDEF);
|
||||
T_Ok(MemoryMatch(guid.data4, data4, sizeof(data4)));
|
||||
T_Ok(str8_match(string_from_guid(arena, guid), string, 0));
|
||||
}
|
||||
|
||||
TEST(match_wildcard)
|
||||
{
|
||||
// empty strings
|
||||
|
||||
@@ -131,7 +131,6 @@ cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg)
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Enum -> String
|
||||
|
||||
|
||||
@@ -1161,7 +1161,7 @@ struct CV_SymPub32
|
||||
|
||||
//- (SymKind: LPROC32, GPROC32)
|
||||
|
||||
#define CV_IsProc32(x) (x == CV_SymKind_LPROC32_ID || x == CV_SymKind_GPROC32_ID || x == CV_SymKind_LPROC32_DPC)
|
||||
#define CV_IsProc32(x) ((x) == CV_SymKind_GPROC32 || (x) == CV_SymKind_LPROC32 || (x) == CV_SymKind_GPROC32_ID || (x) == CV_SymKind_LPROC32_ID || (x) == CV_SymKind_LPROC32_DPC || (x) == CV_SymKind_LPROC32_DPC_ID)
|
||||
|
||||
typedef struct CV_SymProc32 CV_SymProc32;
|
||||
struct CV_SymProc32
|
||||
|
||||
@@ -291,6 +291,8 @@ cv_c13_inline_site_decoder_step(CV_C13InlineSiteDecoder *decoder, String8 binary
|
||||
} break;
|
||||
case CV_InlineBinaryAnnotation_CodeOffset: {
|
||||
decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_offset);
|
||||
decoder->code_offset_lo = decoder->code_offset;
|
||||
decoder->code_offset_lo_changed = 1;
|
||||
decoder->code_offset_changed = 1;
|
||||
} break;
|
||||
case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: {
|
||||
@@ -948,6 +950,7 @@ cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data
|
||||
case CV_LeafKind_NESTTYPEEX: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestTypeEx, itype));
|
||||
} break;
|
||||
case CV_LeafKind_ENDPRECOMP: {} break;
|
||||
default: {
|
||||
NotImplemented;
|
||||
} break;
|
||||
|
||||
+35
-5
@@ -55,11 +55,41 @@ internal String8
|
||||
coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header)
|
||||
{
|
||||
String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name));
|
||||
if (name.str[0] == '/') {
|
||||
String8 name_off_str = str8_skip(name, 1);
|
||||
U64 name_off = u64_from_str8(name_off_str, 10);
|
||||
name = str8_cstring_capped(string_table.str + name_off, string_table.str+string_table.size);
|
||||
|
||||
if (name.size > 0 && name.str[0] == '/') {
|
||||
U64 name_off = max_U64;
|
||||
|
||||
// LLVM/GNU Base64 offset encoding, most significant digit first
|
||||
if (name.size > 1 && name.str[1] == '/') {
|
||||
if (name.size > 2) {
|
||||
name_off = 0;
|
||||
for (U64 i = 2; i < name.size; ++i) {
|
||||
U8 c = name.str[i];
|
||||
U64 digit = 0;
|
||||
if (char_is_upper(c)) { digit = c - 'A'; }
|
||||
else if (char_is_lower(c)) { digit = c - 'a' + 26; }
|
||||
else if (char_is_digit(c, 10)) { digit = c - '0' + 52; }
|
||||
else if (c == '+') { digit = 62; }
|
||||
else if (c == '/') { digit = 63; }
|
||||
else {
|
||||
name_off = max_U64;
|
||||
break;
|
||||
}
|
||||
name_off = (name_off << 6) | digit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// parse standard COFF long name encoding
|
||||
name_off = u64_from_str8(str8_skip(name, 1), 10);
|
||||
}
|
||||
|
||||
if (name_off < string_table.size) {
|
||||
name = str8_cstring_capped(string_table.str + name_off, string_table.str+string_table.size);
|
||||
} else {
|
||||
name = str8_zero();
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -232,7 +262,7 @@ coff_pick_reloc_value_x64(COFF_Reloc_X64 type,
|
||||
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5));
|
||||
} break;
|
||||
case COFF_Reloc_X64_Section: {
|
||||
reloc_value_size = 4;
|
||||
reloc_value_size = 2;
|
||||
reloc_value = symbol_section_number;
|
||||
} break;
|
||||
case COFF_Reloc_X64_SecRel: {
|
||||
|
||||
@@ -149,13 +149,13 @@ coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine
|
||||
imp_symbol.member_idx = member_idx;
|
||||
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
|
||||
} break;
|
||||
case COFF_ImportHeader_Data: {
|
||||
case COFF_ImportHeader_Data:
|
||||
case COFF_ImportHeader_Const: {
|
||||
COFF_LibWriterSymbol imp_symbol = {0};
|
||||
imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name);
|
||||
imp_symbol.member_idx = member_idx;
|
||||
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
|
||||
} break;
|
||||
case COFF_ImportHeader_Const: { NotImplemented; } break;
|
||||
default: { InvalidPath; } break;
|
||||
}
|
||||
}
|
||||
|
||||
+67
-38
@@ -32,22 +32,26 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size));
|
||||
|
||||
//
|
||||
// assing section numbers
|
||||
// assign section numbers
|
||||
//
|
||||
U64 obj_sections_count;
|
||||
COFF_ObjSection **obj_sections;
|
||||
{
|
||||
obj_sections_count = obj_writer->sect_count;
|
||||
AssertAlways(obj_sections_count < COFF_Symbol_DebugSection32);
|
||||
obj_sections = push_array(scratch.arena, COFF_ObjSection *, obj_writer->sect_count);
|
||||
U64 sect_idx = 0;
|
||||
for (COFF_ObjSectionNode *sect_n = obj_writer->sect_first; sect_n != 0; sect_n = sect_n->next, sect_idx += 1) {
|
||||
for EachNode(sect_n, COFF_ObjSectionNode, obj_writer->sect_first) {
|
||||
COFF_ObjSection *sect = §_n->v;
|
||||
sect->section_number = sect_idx+1;
|
||||
obj_sections[sect_idx] = sect;
|
||||
sect_idx += 1;
|
||||
|
||||
}
|
||||
}
|
||||
AssertAlways(obj_sections_count <= max_U16);
|
||||
|
||||
B32 is_big_obj = obj_sections_count > 0xfeff;
|
||||
U64 symbol_size = is_big_obj ? sizeof(COFF_Symbol32) : sizeof(COFF_Symbol16);
|
||||
|
||||
//
|
||||
// serialize symbol table
|
||||
@@ -56,7 +60,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
{
|
||||
{
|
||||
U64 symbol_idx = 0;
|
||||
for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) {
|
||||
for EachNode(symbol_n, COFF_ObjSymbolNode, obj_writer->symbol_first) {
|
||||
COFF_ObjSymbol *s = &symbol_n->v;
|
||||
|
||||
// assign symbol index
|
||||
@@ -66,12 +70,9 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
}
|
||||
|
||||
U64 symbol_idx = 0;
|
||||
for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) {
|
||||
for EachNode(symbol_n, COFF_ObjSymbolNode, obj_writer->symbol_first) {
|
||||
COFF_ObjSymbol *s = &symbol_n->v;
|
||||
|
||||
COFF_Symbol16 *d = push_array(scratch.arena, COFF_Symbol16, 1);
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d));
|
||||
|
||||
COFF_SymbolName name = {0};
|
||||
// long name
|
||||
if (s->name.size > sizeof(name.short_name)) {
|
||||
@@ -90,28 +91,43 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
|
||||
// symbol header
|
||||
AssertAlways(s->aux_symbols.node_count <= max_U8);
|
||||
d->name = name;
|
||||
d->value = s->value;
|
||||
U32 section_number = 0;
|
||||
switch (s->loc.type) {
|
||||
case COFF_SymbolLocation_Null: break;
|
||||
case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break;
|
||||
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break;
|
||||
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Common: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Section: section_number = s->loc.u.section->section_number; break;
|
||||
case COFF_SymbolLocation_Abs: section_number = is_big_obj ? COFF_Symbol_AbsSection32 : COFF_Symbol_AbsSection16; break;
|
||||
case COFF_SymbolLocation_Undef: section_number = COFF_Symbol_UndefinedSection; break;
|
||||
case COFF_SymbolLocation_Common: section_number = COFF_Symbol_UndefinedSection; break;
|
||||
}
|
||||
if (is_big_obj) {
|
||||
COFF_Symbol32 *d = push_array(scratch.arena, COFF_Symbol32, 1);
|
||||
d->name = name;
|
||||
d->value = s->value;
|
||||
d->section_number = section_number;
|
||||
d->type = s->type;
|
||||
d->storage_class = s->storage_class;
|
||||
d->aux_symbol_count = 0;
|
||||
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d));
|
||||
} else {
|
||||
COFF_Symbol16 *d = push_array(scratch.arena, COFF_Symbol16, 1);
|
||||
d->name = name;
|
||||
d->value = s->value;
|
||||
d->section_number = safe_cast_u16(section_number);
|
||||
d->type = s->type;
|
||||
d->storage_class = s->storage_class;
|
||||
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d));
|
||||
}
|
||||
|
||||
U64 start_symbol_idx = symbol_idx;
|
||||
if (s->storage_class == COFF_SymStorageClass_WeakExternal) {
|
||||
if (s->aux_symbols.node_count > 0) {
|
||||
COFF_ObjSymbolWeak *s_weak = (COFF_ObjSymbolWeak *)s->aux_symbols.first->string.str;
|
||||
COFF_SymbolWeakExt *d_weak = push_array(scratch.arena, COFF_SymbolWeakExt, 1);
|
||||
COFF_SymbolWeakExt *d_weak = (COFF_SymbolWeakExt *)push_array(scratch.arena, U8, symbol_size);
|
||||
d_weak->tag_index = s_weak->tag ? s_weak->tag->idx : max_U32;
|
||||
d_weak->characteristics = s_weak->characteristics;
|
||||
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_weak));
|
||||
str8_list_push(scratch.arena, &symbol_table, str8((U8 *)d_weak, symbol_size));
|
||||
symbol_idx += 1;
|
||||
}
|
||||
} else if (s->storage_class == COFF_SymStorageClass_Static) {
|
||||
@@ -120,15 +136,17 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
COFF_ObjSection *sect = s->loc.u.section;
|
||||
|
||||
COFF_ObjSymbolSecDef *s_sd = (COFF_ObjSymbolSecDef *)s->aux_symbols.first->string.str;
|
||||
COFF_SymbolSecDef *d_sd = push_array(scratch.arena, COFF_SymbolSecDef, 1);
|
||||
COFF_SymbolSecDef *d_sd = (COFF_SymbolSecDef *)push_array(scratch.arena, U8, symbol_size);
|
||||
|
||||
d_sd->length = safe_cast_u32(sect->data.total_size);
|
||||
d_sd->number_of_relocations = (U16)sect->reloc_count;
|
||||
d_sd->check_sum = 0;
|
||||
d_sd->number_lo = s_sd->selection == COFF_ComdatSelect_Associative ? safe_cast_u16(s_sd->associate->section_number) : 0;
|
||||
U32 associate_number = s_sd->selection == COFF_ComdatSelect_Associative ? s_sd->associate->section_number : 0;
|
||||
d_sd->number_lo = (U16)associate_number;
|
||||
d_sd->number_hi = (U16)(associate_number >> 16);
|
||||
d_sd->selection = s_sd->selection;
|
||||
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_sd));
|
||||
str8_list_push(scratch.arena, &symbol_table, str8((U8 *)d_sd, symbol_size));
|
||||
symbol_idx += 1;
|
||||
}
|
||||
}
|
||||
@@ -136,26 +154,37 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
U8 processed_aux_symbol_count = (U8)(symbol_idx - start_symbol_idx);
|
||||
|
||||
for (U64 aux_idx = processed_aux_symbol_count; aux_idx < s->aux_symbols.node_count; aux_idx += 1) {
|
||||
COFF_Symbol16 *a = push_array(scratch.arena, COFF_Symbol16, 1);
|
||||
str8_list_push(scratch.arena, &symbol_table, str8_struct(a));
|
||||
U8 *a = push_array(scratch.arena, U8, symbol_size);
|
||||
str8_list_push(scratch.arena, &symbol_table, str8(a, symbol_size));
|
||||
}
|
||||
|
||||
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// file header
|
||||
//
|
||||
COFF_FileHeader *file_header = push_array(scratch.arena, COFF_FileHeader, 1);
|
||||
file_header->machine = obj_writer->machine;
|
||||
file_header->section_count = obj_sections_count;
|
||||
file_header->time_stamp = obj_writer->time_stamp;
|
||||
file_header->symbol_table_foff = 0;
|
||||
file_header->symbol_count = safe_cast_u32(symbol_table.node_count);
|
||||
file_header->optional_header_size = 0;
|
||||
file_header->flags = 0;
|
||||
str8_list_push(scratch.arena, &srl, str8_struct(file_header));
|
||||
U32 *symbol_table_foff;
|
||||
if (is_big_obj) {
|
||||
COFF_BigObjHeader *header = push_array(scratch.arena, COFF_BigObjHeader, 1);
|
||||
header->sig1 = COFF_MachineType_Unknown;
|
||||
header->sig2 = max_U16;
|
||||
header->version = 2;
|
||||
header->machine = obj_writer->machine;
|
||||
header->time_stamp = obj_writer->time_stamp;
|
||||
MemoryCopy(header->magic, g_coff_big_header_magic, sizeof(header->magic));
|
||||
header->section_count = safe_cast_u32(obj_sections_count);
|
||||
header->symbol_count = safe_cast_u32(symbol_table.node_count);
|
||||
symbol_table_foff = &header->symbol_table_foff;
|
||||
str8_list_push(scratch.arena, &srl, str8_struct(header));
|
||||
} else {
|
||||
COFF_FileHeader *header = push_array(scratch.arena, COFF_FileHeader, 1);
|
||||
header->machine = obj_writer->machine;
|
||||
header->section_count = safe_cast_u16(obj_sections_count);
|
||||
header->time_stamp = obj_writer->time_stamp;
|
||||
header->symbol_count = safe_cast_u32(symbol_table.node_count);
|
||||
symbol_table_foff = &header->symbol_table_foff;
|
||||
str8_list_push(scratch.arena, &srl, str8_struct(header));
|
||||
}
|
||||
|
||||
//
|
||||
// section table
|
||||
@@ -164,7 +193,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
COFF_SectionHeader *sectab = push_array(scratch.arena, COFF_SectionHeader, obj_sections_count);
|
||||
str8_list_push(scratch.arena, &srl, str8_array(sectab, obj_sections_count));
|
||||
{
|
||||
for (U64 sect_idx = 0; sect_idx < obj_sections_count; sect_idx += 1) {
|
||||
for EachIndex(sect_idx, obj_sections_count) {
|
||||
COFF_ObjSection *s = obj_sections[sect_idx];
|
||||
COFF_SectionHeader *d = §ab[sect_idx];
|
||||
|
||||
@@ -179,7 +208,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
}
|
||||
|
||||
// alloc zero nodes
|
||||
for (String8Node *data_n = s->data.first; data_n != 0; data_n = data_n->next) {
|
||||
for EachNode(data_n, String8Node, s->data.first) {
|
||||
if (data_n->string.str == 0 && data_n->string.size > 0) {
|
||||
data_n->string = str8(push_array(scratch.arena, U8, data_n->string.size), data_n->string.size);
|
||||
}
|
||||
@@ -200,9 +229,9 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
AssertAlways(s->reloc_count <= max_U16);
|
||||
COFF_Reloc *relocs = push_array(scratch.arena, COFF_Reloc, s->reloc_count);
|
||||
U64 reloc_idx = 0;
|
||||
for (COFF_ObjRelocNode *reloc_n = s->reloc_first; reloc_n != 0; reloc_n = reloc_n->next, reloc_idx += 1) {
|
||||
for EachNode(reloc_n, COFF_ObjRelocNode, s->reloc_first) {
|
||||
COFF_ObjReloc *rs = &reloc_n->v;
|
||||
COFF_Reloc *rd = &relocs[reloc_idx];
|
||||
COFF_Reloc *rd = &relocs[reloc_idx++];
|
||||
rd->apply_off = rs->apply_off;
|
||||
rd->isymbol = rs->symbol->idx;
|
||||
rd->type = rs->type;
|
||||
@@ -230,7 +259,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
// symbol table
|
||||
//
|
||||
if (symbol_table.total_size || string_table.total_size > sizeof(*string_table_size)) {
|
||||
file_header->symbol_table_foff = srl.total_size;
|
||||
*symbol_table_foff = safe_cast_u32(srl.total_size);
|
||||
str8_list_concat_in_place(&srl, &symbol_table);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ entry_point(CmdLine *cmd_line)
|
||||
}
|
||||
str8_list_push(scratch.arena, &command_parts, exe_name);
|
||||
str8_list_push(scratch.arena, &command_parts, s("--cli"));
|
||||
for EachIndex(idx, cmd_line->argc)
|
||||
for(U64 idx = 1; idx < cmd_line->argc; idx += 1)
|
||||
{
|
||||
String8 arg = str8_cstring(cmd_line->argv[idx]);
|
||||
str8_list_push(scratch.arena, &command_parts, arg);
|
||||
|
||||
+23
-10
@@ -184,19 +184,19 @@ cfg_node_from_id(CFG_ID id)
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&id));
|
||||
U64 hash = id;
|
||||
U64 slot_idx = hash%cfg_ctx->id_slots_count;
|
||||
for(CFG_NodePtrNode *n = cfg_ctx->id_slots[slot_idx].first; n != 0; n = n->next)
|
||||
{
|
||||
if(n->v->id == id)
|
||||
{
|
||||
result = n->v;
|
||||
cfg_ctx->last_accessed_id = id;
|
||||
cfg_ctx->last_accessed = result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg_ctx->last_accessed_id = id;
|
||||
cfg_ctx->last_accessed = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -619,7 +619,7 @@ cfg_node_alloc(CFG_State *state)
|
||||
{
|
||||
cfg_id_node = push_array(state->arena, CFG_NodePtrNode, 1);
|
||||
}
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&result->id));
|
||||
U64 hash = result->id;
|
||||
U64 slot_idx = hash%state->ctx.id_slots_count;
|
||||
DLLPushBack(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, cfg_id_node);
|
||||
cfg_id_node->v = result;
|
||||
@@ -632,7 +632,6 @@ internal void
|
||||
cfg_node_release(CFG_State *state, CFG_Node *node)
|
||||
{
|
||||
state->ctx.change_gen += 1;
|
||||
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
// rjf: unhook from context
|
||||
@@ -648,23 +647,37 @@ cfg_node_release(CFG_State *state, CFG_Node *node)
|
||||
// rjf: release all nodes
|
||||
for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next)
|
||||
{
|
||||
// rjf: unpack node
|
||||
CFG_Node *c = n->v;
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&c->id));
|
||||
U64 hash = c->id;
|
||||
U64 slot_idx = hash%state->ctx.id_slots_count;
|
||||
|
||||
// rjf: release string, recycle node
|
||||
cfg_string_release(state, c->string);
|
||||
SLLStackPush(state->free, c);
|
||||
|
||||
// rjf: zero node's contents
|
||||
c->first = c->last = c->prev = c->parent = 0;
|
||||
c->id = 0;
|
||||
c->string = str8_zero();
|
||||
for(CFG_NodePtrNode *n = state->ctx.id_slots[slot_idx].first; n != 0; n = n->next)
|
||||
|
||||
// rjf: remove from id -> node map
|
||||
for(CFG_NodePtrNode *id_n = state->ctx.id_slots[slot_idx].first; id_n != 0; id_n = id_n->next)
|
||||
{
|
||||
if(n->v == c)
|
||||
if(id_n->v == c)
|
||||
{
|
||||
DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, n);
|
||||
SLLStackPush(state->free_id_node, n);
|
||||
DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, id_n);
|
||||
SLLStackPush(state->free_id_node, id_n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: if this was the last accessed node, clear that slot
|
||||
if(c == state->ctx.last_accessed)
|
||||
{
|
||||
state->ctx.last_accessed = &cfg_nil_node;
|
||||
state->ctx.last_accessed_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
+27
-14
@@ -7,7 +7,7 @@ cfg_window_from_cfg(CFG_Node *cfg)
|
||||
CFG_Node *result = &cfg_nil_node;
|
||||
for(CFG_Node *c = cfg; c != &cfg_nil_node; c = c->parent)
|
||||
{
|
||||
if(c->parent->parent == cfg_node_root() && str8_match(c->string, str8_lit("window"), 0))
|
||||
if(c->parent->parent == cfg_node_root() && str8_match(c->string, s("window"), 0))
|
||||
{
|
||||
result = c;
|
||||
break;
|
||||
@@ -21,17 +21,26 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
CFG_Node *wcfg = cfg_window_from_cfg(cfg_root);
|
||||
CFG_Node *src_root = cfg_node_child_from_string(wcfg, str8_lit("panels"));
|
||||
CFG_Node *src_root = cfg_node_child_from_string(wcfg, s("panels"));
|
||||
CFG_PanelNode *dst_root = &cfg_nil_panel_node;
|
||||
CFG_PanelNode *dst_focused = &cfg_nil_panel_node;
|
||||
CFG_PanelNode *dst_zoom_root = &cfg_nil_panel_node;
|
||||
{
|
||||
Axis2 active_split_axis = cfg_node_child_from_string(wcfg, str8_lit("split_x")) != &cfg_nil_node ? Axis2_X : Axis2_Y;
|
||||
Axis2 active_split_axis = cfg_node_child_from_string(wcfg, s("split_x")) != &cfg_nil_node ? Axis2_X : Axis2_Y;
|
||||
CFG_NodeRec rec = {0};
|
||||
CFG_PanelNode *dst_active_parent = &cfg_nil_panel_node;
|
||||
for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next)
|
||||
{
|
||||
// rjf: build a panel node
|
||||
CFG_PanelNode *dst = push_array(arena, CFG_PanelNode, 1);
|
||||
// rjf: unpack this config string
|
||||
MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src->string);
|
||||
|
||||
// rjf: build a panel node if this is a child panel
|
||||
CFG_PanelNode *dst = &cfg_nil_panel_node;
|
||||
B32 panel_has_children = 0;
|
||||
if(src == src_root || (tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric))
|
||||
{
|
||||
// rjf: allocate
|
||||
dst = push_array(arena, CFG_PanelNode, 1);
|
||||
MemoryCopyStruct(dst, &cfg_nil_panel_node);
|
||||
dst->parent = dst_active_parent;
|
||||
if(dst_active_parent != &cfg_nil_panel_node)
|
||||
@@ -45,10 +54,9 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
|
||||
}
|
||||
|
||||
// rjf: extract cfg info
|
||||
B32 panel_has_children = 0;
|
||||
dst->cfg = src;
|
||||
dst->pct_of_parent = (src == src_root ? 1.f : (F32)f64_from_str8(src->string));
|
||||
dst->tab_side = (cfg_node_child_from_string(src, str8_lit("tabs_on_bottom")) != &cfg_nil_node ? Side_Max : Side_Min);
|
||||
dst->tab_side = (cfg_node_child_from_string(src, s("tabs_on_bottom")) != &cfg_nil_node ? Side_Max : Side_Min);
|
||||
dst->split_axis = active_split_axis;
|
||||
for(CFG_Node *src_child = src->first; src_child != &cfg_nil_node; src_child = src_child->next)
|
||||
{
|
||||
@@ -57,23 +65,28 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
|
||||
{
|
||||
panel_has_children = 1;
|
||||
}
|
||||
else if(str8_match(src_child->string, str8_lit("tabs_on_bottom"), 0))
|
||||
if(str8_match(src_child->string, s("tabs_on_bottom"), 0))
|
||||
{
|
||||
// NOTE(rjf): skip - this is a panel option.
|
||||
}
|
||||
else if(str8_match(src_child->string, str8_lit("selected"), 0))
|
||||
else if(str8_match(src_child->string, s("selected"), 0))
|
||||
{
|
||||
dst_focused = dst;
|
||||
}
|
||||
else if(str8_match(src_child->string, s("zoom_root"), 0))
|
||||
{
|
||||
dst_zoom_root = dst;
|
||||
}
|
||||
else if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Identifier)
|
||||
{
|
||||
cfg_node_ptr_list_push(arena, &dst->tabs, src_child);
|
||||
if(cfg_node_child_from_string(src_child, str8_lit("selected")) != &cfg_nil_node)
|
||||
if(cfg_node_child_from_string(src_child, s("selected")) != &cfg_nil_node)
|
||||
{
|
||||
dst->selected_tab = src_child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: recurse
|
||||
rec = cfg_node_rec__depth_first(src_root, src);
|
||||
@@ -103,7 +116,7 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
CFG_PanelTree tree = {dst_root, dst_focused};
|
||||
CFG_PanelTree tree = {dst_root, dst_focused, dst_zoom_root};
|
||||
return tree;
|
||||
}
|
||||
|
||||
@@ -179,7 +192,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane
|
||||
|
||||
// rjf: count ancestors
|
||||
U64 ancestor_count = 0;
|
||||
for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent)
|
||||
for(CFG_PanelNode *p = panel->parent; p != root->parent; p = p->parent)
|
||||
{
|
||||
ancestor_count += 1;
|
||||
}
|
||||
@@ -188,7 +201,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane
|
||||
CFG_PanelNode **ancestors = push_array(scratch.arena, CFG_PanelNode *, ancestor_count);
|
||||
{
|
||||
U64 ancestor_idx = 0;
|
||||
for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent)
|
||||
for(CFG_PanelNode *p = panel->parent; p != root->parent; p = p->parent)
|
||||
{
|
||||
ancestors[ancestor_idx] = p;
|
||||
ancestor_idx += 1;
|
||||
@@ -203,7 +216,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane
|
||||
{
|
||||
CFG_PanelNode *ancestor = ancestors[ancestor_idx];
|
||||
CFG_PanelNode *parent = ancestor->parent;
|
||||
if(parent != &cfg_nil_panel_node)
|
||||
if(parent != root->parent)
|
||||
{
|
||||
parent_rect = cfg_target_rect_from_panel_node_child(parent_rect, parent, ancestor);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ struct CFG_PanelTree
|
||||
{
|
||||
CFG_PanelNode *root;
|
||||
CFG_PanelNode *focused;
|
||||
CFG_PanelNode *zoom_root;
|
||||
};
|
||||
|
||||
typedef struct CFG_PanelNodeRec CFG_PanelNodeRec;
|
||||
|
||||
@@ -272,7 +272,7 @@ c_submit_data(C_Key key, Arena **data_arena, String8 data)
|
||||
// rjf: key is new -> add this key to the associated root
|
||||
if(key_is_new)
|
||||
{
|
||||
U64 root_hash = u64_hash_from_str8(str8_struct(&key.root));
|
||||
U64 root_hash = key.root.u64[0];
|
||||
U64 root_slot_idx = root_hash%c_shared->root_slots_count;
|
||||
U64 root_stripe_idx = root_slot_idx%c_shared->root_stripes_count;
|
||||
C_RootSlot *root_slot = &c_shared->root_slots[root_slot_idx];
|
||||
|
||||
+27
-129
@@ -39,10 +39,10 @@ D_CmdTable: // | | |
|
||||
{ThawThread 1 1 "query:threads" Thread 0 0 0 0 0 1 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" "" }
|
||||
{FreezeProcess 1 1 "query:processes" Process 0 0 0 0 0 1 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" "" }
|
||||
{ThawProcess 1 1 "query:processes" Process 0 0 0 0 0 1 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" "" }
|
||||
{FreezeMachine 0 1 "query:machines" Machine 0 0 0 0 0 1 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" "" }
|
||||
{ThawMachine 0 1 "query:machines" Machine 0 0 0 0 0 1 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" "" }
|
||||
{FreezeLocalMachine 1 1 "" Null 0 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" "" }
|
||||
{ThawLocalMachine 1 1 "" Null 0 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" "" }
|
||||
{FreezeServer 0 1 "query:servers" Server 0 0 0 0 0 1 1 Locked "freeze_server " "Freeze Server " "Freezes the passed server." "" "" }
|
||||
{ThawServer 0 1 "query:servers" Server 0 0 0 0 0 1 1 Unlocked "thaw_server" "Thaw Server" "Thaws the passed server." "" "" }
|
||||
{FreezeLocalServer 1 1 "" Null 0 0 0 0 0 0 0 Machine "freeze_local_server" "Freeze Local Server" "Freezes the local server." "" "" }
|
||||
{ThawLocalServer 1 1 "" Null 0 0 0 0 0 0 0 Machine "thaw_local_server" "Thaw Local Server" "Thaws the local server." "" "" }
|
||||
{FreezeEntity 0 0 "" Null 0 0 0 0 0 0 0 Unlocked "freeze_entity" "Freeze Entity" "Freezes an entity." "" "" }
|
||||
{ThawEntity 0 0 "" Null 0 0 0 0 0 0 0 Locked "thaw_entity" "Thaw Entity" "Thaws an entity." "" "" }
|
||||
|
||||
@@ -57,7 +57,11 @@ D_CmdTable: // | | |
|
||||
{Attach 1 1 "query:unattached_processes" PID 0 0 0 0 0 1 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" "" }
|
||||
|
||||
//- rjf: crash dump opening
|
||||
{OpenCrashDump 0 0 `folder:\\"$input\\"` FilePath 0 0 0 0 0 1 1 FileOutline "open_crash_dump" "Open Crash Dump" "Opens a crash dump file and recreates debuggee state at the time of the crash." "" "" }
|
||||
{OpenCrashDump 1 1 `folder:\\"$input\\"` FilePath 0 0 0 0 0 1 1 FileOutline "open_crash_dump" "Open Crash Dump" "Opens a crash dump file and recreates debuggee state at the time of the crash." "" "" }
|
||||
|
||||
//- rjf: remote debug server connecting
|
||||
{OpenRemoteServer 1 1 "" String 0 0 0 0 0 1 1 Machine "open_remote_server" "Open Remote Server" "Opens a remote debug server by IP address." "" "" }
|
||||
{CloseRemoteServer 1 1 "query:servers" CtrlEntity 0 0 0 0 0 1 1 Machine "close_remote_server" "Close Remote Server" "Closes a remote debug server." "" "" }
|
||||
}
|
||||
|
||||
@enum D_CmdKind:
|
||||
@@ -104,7 +108,7 @@ D_DevToggleTable:
|
||||
D_EntityKindTable:
|
||||
{
|
||||
{Root root "Root" }
|
||||
{Machine machine "Machine" }
|
||||
{Server server "Server" }
|
||||
{Process process "Process" }
|
||||
{Thread thread "Thread" }
|
||||
{Module module "Module" }
|
||||
@@ -139,151 +143,45 @@ D_EntityKindTable:
|
||||
////////////////////////////////
|
||||
//~ rjf: Exception Codes
|
||||
|
||||
@table(name lower_name code default display_string)
|
||||
D_ExceptionCodeKindTable:
|
||||
{
|
||||
{Win32CtrlC win32_ctrl_c 0x40010005 1 "(Win32) Control-C" }
|
||||
{Win32CtrlBreak win32_ctrl_break 0x40010008 1 "(Win32) Control-Break" }
|
||||
{Win32WinRTOriginateError win32_win_rt_originate_error 0x40080201 0 "(Win32) WinRT Originate Error" }
|
||||
{Win32WinRTTransformError win32_win_rt_transform_error 0x40080202 0 "(Win32) WinRT Transform Error" }
|
||||
{Win32RPCCallCancelled win32_rpc_call_cancelled 0x0000071a 0 "(Win32) RPC Call Cancelled" }
|
||||
{Win32DatatypeMisalignment win32_datatype_misalignment 0x80000002 0 "(Win32) Data Type Misalignment" }
|
||||
{Win32AccessViolation win32_access_violation 0xc0000005 1 "(Win32) Access Violation" }
|
||||
{Win32InPageError win32_in_page_error 0xc0000006 0 "(Win32) In Page Error" }
|
||||
{Win32InvalidHandle win32_invalid_handle 0xc0000008 1 "(Win32) Invalid Handle Specified" }
|
||||
{Win32NotEnoughQuota win32_not_enough_quota 0xc0000017 0 "(Win32) Not Enough Quota" }
|
||||
{Win32IllegalInstruction win32_illegal_instruction 0xc000001d 0 "(Win32) Illegal Instruction" }
|
||||
{Win32CannotContinueException win32_cannot_continue_exception 0xc0000025 0 "(Win32) Cannot Continue From Exception" }
|
||||
{Win32InvalidExceptionDisposition win32_invalid_exception_disposition 0xc0000026 0 "(Win32) Invalid Exception Disposition Returned By Handler" }
|
||||
{Win32ArrayBoundsExceeded win32_array_bounds_exceeded 0xc000008c 0 "(Win32) Array Bounds Exceeded" }
|
||||
{Win32FloatingPointDenormalOperand win32_floating_point_denormal_operand 0xc000008d 0 "(Win32) Floating-Point Denormal Operand" }
|
||||
{Win32FloatingPointDivisionByZero win32_floating_point_division_by_zero 0xc000008e 0 "(Win32) Floating-Point Division By Zero" }
|
||||
{Win32FloatingPointInexactResult win32_floating_point_inexact_result 0xc000008f 0 "(Win32) Floating-Point Inexact Result" }
|
||||
{Win32FloatingPointInvalidOperation win32_floating_point_invalid_operation 0xc0000090 0 "(Win32) Floating-Point Invalid Operation" }
|
||||
{Win32FloatingPointOverflow win32_floating_point_overflow 0xc0000091 0 "(Win32) Floating-Point Overflow" }
|
||||
{Win32FloatingPointStackCheck win32_floating_point_stack_check 0xc0000092 0 "(Win32) Floating-Point Stack Check" }
|
||||
{Win32FloatingPointUnderflow win32_floating_point_underflow 0xc0000093 0 "(Win32) Floating-Point Underflow" }
|
||||
{Win32IntegerDivisionByZero win32_integer_division_by_zero 0xc0000094 0 "(Win32) Integer Division By Zero" }
|
||||
{Win32IntegerOverflow win32_integer_overflow 0xc0000095 0 "(Win32) Integer Overflow" }
|
||||
{Win32PrivilegedInstruction win32_privileged_instruction 0xc0000096 0 "(Win32) Privileged Instruction" }
|
||||
{Win32StackOverflow win32_stack_overflow 0xc00000fd 0 "(Win32) Stack Overflow" }
|
||||
{Win32UnableToLocateDLL win32_unable_to_locate_dll 0xc0000135 0 "(Win32) Unable To Locate DLL" }
|
||||
{Win32OrdinalNotFound win32_ordinal_not_found 0xc0000138 0 "(Win32) Ordinal Not Found" }
|
||||
{Win32EntryPointNotFound win32_entry_point_not_found 0xc0000139 0 "(Win32) Entry Point Not Found" }
|
||||
{Win32DLLInitializationFailed win32_dll_initialization_failed 0xc0000142 0 "(Win32) DLL Initialization Failed" }
|
||||
{Win32FloatingPointSSEMultipleFaults win32_floating_point_sse_multiple_faults 0xc00002b4 0 "(Win32) Floating Point SSE Multiple Faults" }
|
||||
{Win32FloatingPointSSEMultipleTraps win32_floating_point_sse_multiple_traps 0xc00002b5 0 "(Win32) Floating Point SSE Multiple Traps" }
|
||||
{Win32AssertionFailed win32_assertion_failed 0xc0000420 1 "(Win32) Assertion Failed" }
|
||||
{Win32ModuleNotFound win32_module_not_found 0xc06d007e 0 "(Win32) Module Not Found" }
|
||||
{Win32ProcedureNotFound win32_procedure_not_found 0xc06d007f 0 "(Win32) Procedure Not Found" }
|
||||
{Win32SanitizerErrorDetected win32_sanitizer_error_detected 0xe073616e 1 "(Win32) Sanitizer Error Detected" }
|
||||
{Win32SanitizerRawAccessViolation win32_sanitizer_raw_access_violation 0xe0736171 0 "(Win32) Sanitizer Raw Access Violation" }
|
||||
{Win32DirectXDebugLayer win32_directx_debug_layer 0x0000087a 1 "(Win32) DirectX Debug Layer" }
|
||||
}
|
||||
|
||||
@enum D_ExceptionCodeKind:
|
||||
{
|
||||
Null,
|
||||
@expand(D_ExceptionCodeKindTable a) `$(a.name)`,
|
||||
@expand(W32_ExceptionCodeKindTable a) `Win32$(a.name)`,
|
||||
@expand(LNX_SignalCodeTable a) `Linux$(a.name)`,
|
||||
COUNT,
|
||||
}
|
||||
|
||||
@data(U32) d_exception_code_kind_code_table:
|
||||
{
|
||||
`0`;
|
||||
@expand(D_ExceptionCodeKindTable a) `$(a.code)`;
|
||||
@expand(W32_ExceptionCodeKindTable a) `$(a.code)`;
|
||||
@expand(LNX_SignalCodeTable a) `$(a.code)`,
|
||||
}
|
||||
|
||||
@data(OperatingSystem) d_exception_code_kind_os_table:
|
||||
{
|
||||
`OperatingSystem_Null`;
|
||||
@expand(W32_ExceptionCodeKindTable a) `OperatingSystem_Windows`;
|
||||
@expand(LNX_SignalCodeTable a) `OperatingSystem_Linux`,
|
||||
}
|
||||
|
||||
@data(String8) d_exception_code_kind_display_string_table:
|
||||
{
|
||||
`{0}`;
|
||||
@expand(D_ExceptionCodeKindTable a) `str8_lit_comp("$(a.display_string)")`;
|
||||
@expand(W32_ExceptionCodeKindTable a) `str8_lit_comp("$(a.display_string)")`;
|
||||
@expand(LNX_SignalCodeTable a) `str8_lit_comp("$(a.name) ($(a.desc))")`,
|
||||
}
|
||||
|
||||
@data(String8) d_exception_code_kind_lowercase_code_string_table:
|
||||
{
|
||||
`{0}`;
|
||||
@expand(D_ExceptionCodeKindTable a) `str8_lit_comp("$(a.lower_name)")`;
|
||||
@expand(W32_ExceptionCodeKindTable a) `str8_lit_comp("win32_$(a.lower_name)")`;
|
||||
@expand(LNX_SignalCodeTable a) `str8_lit_comp("linux_$(a.name_lower)")`,
|
||||
}
|
||||
|
||||
@data(B8) d_exception_code_kind_default_enable_table:
|
||||
{
|
||||
`0`;
|
||||
@expand(D_ExceptionCodeKindTable a) `$(a.default)`;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Exception Sub-Codes
|
||||
|
||||
@table(name, value)
|
||||
DL_ExceptionSubCodeKindTable:
|
||||
{
|
||||
{ W32_FAST_FAIL_LEGACY_GS_VIOLATION 0 }
|
||||
{ W32_FAST_FAIL_VTGUARD_CHECK_FAILURE 1 }
|
||||
{ W32_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE 2 }
|
||||
{ W32_FAST_FAIL_CORRUPT_LIST_ENTRY 3 }
|
||||
{ W32_FAST_FAIL_INCORRECT_STACK 4 }
|
||||
{ W32_FAST_FAIL_INVALID_ARG 5 }
|
||||
{ W32_FAST_FAIL_GS_COOKIE_INIT 6 }
|
||||
{ W32_FAST_FAIL_FATAL_APP_EXIT 7 }
|
||||
{ W32_FAST_FAIL_RANGE_CHECK_FAILURE 8 }
|
||||
{ W32_FAST_FAIL_UNSAFE_REGISTRY_ACCESS 9 }
|
||||
{ W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE 10 }
|
||||
{ W32_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE 11 }
|
||||
{ W32_FAST_FAIL_INVALID_FIBER_SWITCH 12 }
|
||||
{ W32_FAST_FAIL_INVALID_SET_OF_CONTEXT 13 }
|
||||
{ W32_FAST_FAIL_INVALID_REFERENCE_COUNT 14 }
|
||||
{ W32_FAST_FAIL_INVALID_JUMP_BUFFER 18 }
|
||||
{ W32_FAST_FAIL_MRDATA_MODIFIED 19 }
|
||||
{ W32_FAST_FAIL_CERTIFICATION_FAILURE 20 }
|
||||
{ W32_FAST_FAIL_INVALID_EXCEPTION_CHAIN 21 }
|
||||
{ W32_FAST_FAIL_CRYPTO_LIBRARY 22 }
|
||||
{ W32_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT 23 }
|
||||
{ W32_FAST_FAIL_INVALID_IMAGE_BASE 24 }
|
||||
{ W32_FAST_FAIL_DLOAD_PROTECTION_FAILURE 25 }
|
||||
{ W32_FAST_FAIL_UNSAFE_EXTENSION_CALL 26 }
|
||||
{ W32_FAST_FAIL_DEPRECATED_SERVICE_INVOKED 27 }
|
||||
{ W32_FAST_FAIL_INVALID_BUFFER_ACCESS 28 }
|
||||
{ W32_FAST_FAIL_INVALID_BALANCED_TREE 29 }
|
||||
{ W32_FAST_FAIL_INVALID_NEXT_THREAD 30 }
|
||||
{ W32_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED 31 }
|
||||
{ W32_FAST_FAIL_APCS_DISABLED 32 }
|
||||
{ W32_FAST_FAIL_INVALID_IDLE_STATE 33 }
|
||||
{ W32_FAST_FAIL_MRDATA_PROTECTION_FAILURE 34 }
|
||||
{ W32_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION 35 }
|
||||
{ W32_FAST_FAIL_INVALID_LOCK_STATE 36 }
|
||||
{ W32_FAST_FAIL_GUARD_JUMPTABLE 37 }
|
||||
{ W32_FAST_FAIL_INVALID_LONGJUMP_TARGET 38 }
|
||||
{ W32_FAST_FAIL_INVALID_DISPATCH_CONTEXT 39 }
|
||||
{ W32_FAST_FAIL_INVALID_THREAD 40 }
|
||||
{ W32_FAST_FAIL_INVALID_SYSCALL_NUMBER 41 }
|
||||
{ W32_FAST_FAIL_INVALID_FILE_OPERATION 42 }
|
||||
{ W32_FAST_FAIL_LPAC_ACCESS_DENIED 43 }
|
||||
{ W32_FAST_FAIL_GUARD_SS_FAILURE 44 }
|
||||
{ W32_FAST_FAIL_LOADER_CONTINUITY_FAILURE 45 }
|
||||
{ W32_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE 46 }
|
||||
{ W32_FAST_FAIL_INVALID_CONTROL_STACK 47 }
|
||||
{ W32_FAST_FAIL_SET_CONTEXT_DENIED 48 }
|
||||
{ W32_FAST_FAIL_INVALID_IAT 49 }
|
||||
{ W32_FAST_FAIL_HEAP_METADATA_CORRUPTION 50 }
|
||||
{ W32_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION 51 }
|
||||
{ W32_FAST_FAIL_LOW_LABEL_ACCESS_DENIED 52 }
|
||||
{ W32_FAST_FAIL_ENCLAVE_CALL_FAILURE 53 }
|
||||
{ W32_FAST_FAIL_UNHANDLED_LSS_EXCEPTON 54 }
|
||||
{ W32_FAST_FAIL_ADMINLESS_ACCESS_DENIED 55 }
|
||||
{ W32_FAST_FAIL_UNEXPECTED_CALL 56 }
|
||||
{ W32_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS 57 }
|
||||
{ W32_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR 58 }
|
||||
{ W32_FAST_FAIL_FLAGS_CORRUPTION 59 }
|
||||
{ W32_FAST_FAIL_VEH_CORRUPTION 60 }
|
||||
{ W32_FAST_FAIL_ETW_CORRUPTION 61 }
|
||||
{ W32_FAST_FAIL_RIO_ABORT 62 }
|
||||
{ W32_FAST_FAIL_INVALID_PFN 63 }
|
||||
{ W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG 64 }
|
||||
{ W32_FAST_FAIL_CAST_GUARD 65 }
|
||||
{ W32_FAST_FAIL_HOST_VISIBILITY_CHANGE 66 }
|
||||
{ W32_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST 67 }
|
||||
{ W32_FAST_FAIL_PATCH_CALLBACK_FAILED 68 }
|
||||
{ W32_FAST_FAIL_NTDLL_PATCH_FAILED 69 }
|
||||
{ W32_FAST_FAIL_INVALID_FLS_DATA 70 }
|
||||
@expand(W32_ExceptionCodeKindTable a) `$(a.default)`;
|
||||
@expand(LNX_SignalCodeTable a) `$(a.break_default)`;
|
||||
}
|
||||
@@ -6,6 +6,93 @@
|
||||
|
||||
#include "generated/dbg_engine.meta.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @eval2 Bundled Evaluation Path
|
||||
|
||||
internal D_Eval
|
||||
d_eval_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
D_Eval eval = {0};
|
||||
{
|
||||
E2_MsgList msgs = {0};
|
||||
|
||||
//- rjf: string -> expr
|
||||
E2_Expr *expr = &e2_expr_nil;
|
||||
{
|
||||
E2_ParseState state = {0};
|
||||
B32 identifier_is_type = 0;
|
||||
for(;;)
|
||||
{
|
||||
E2_Parse parse = e2_parse_from_string(arena, &state, identifier_is_type, E2_LangKind_CLike, string);
|
||||
identifier_is_type = 0;
|
||||
expr = parse.expr;
|
||||
e2_msg_list_concat_in_place(&msgs, &parse.msgs);
|
||||
if(e2_parse_status_is_terminal(parse.status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: expr -> irtree
|
||||
E2_IRNode *irtree = &e2_irnode_nil;
|
||||
{
|
||||
E2_IRNode *resolve_result = &e2_irnode_nil;
|
||||
E2_Val compile_time_eval_result = {0};
|
||||
E2_CompileState state = {0};
|
||||
for(;;)
|
||||
{
|
||||
E2_Compile compile = e2_compile_from_expr(arena, &state, resolve_result, compile_time_eval_result, expr);
|
||||
resolve_result = &e2_irnode_nil;
|
||||
MemoryZeroStruct(&compile_time_eval_result);
|
||||
irtree = compile.irtree;
|
||||
e2_msg_list_concat_in_place(&msgs, &compile.msgs);
|
||||
switch(compile.status)
|
||||
{
|
||||
default:{}break;
|
||||
case E2_CompileStatus_MissedIdentifierResolution:
|
||||
{
|
||||
resolve_result = e2_irnode_const_u64_or_smaller(arena, 123);
|
||||
}break;
|
||||
}
|
||||
if(e2_compile_status_is_terminal(compile.status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: ir tree -> bytecode
|
||||
String8 bytecode = e2_bytecode_from_irnode(arena, irtree);
|
||||
|
||||
//- rjf: bytecode -> value
|
||||
E2_Val val = {0};
|
||||
{
|
||||
E2_InterpState state = {0};
|
||||
E2_SpaceMap space_map = {0};
|
||||
for(;;)
|
||||
{
|
||||
E2_Interp interp = e2_interp_from_bytecode(arena, &state, &space_map, bytecode);
|
||||
val = interp.val;
|
||||
e2_msg_list_concat_in_place(&msgs, &interp.msgs);
|
||||
if(e2_interp_status_is_terminal(interp.status))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: fill
|
||||
eval.string = string;
|
||||
eval.expr = expr;
|
||||
eval.irtree = irtree;
|
||||
eval.bytecode = bytecode;
|
||||
eval.val = val;
|
||||
eval.msgs = msgs;
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Layer Initialization
|
||||
|
||||
@@ -17,6 +104,7 @@ d_init(void)
|
||||
Arena *arena = arena_alloc();
|
||||
d_ctrl_state = push_array(arena, D_CtrlState, 1);
|
||||
d_ctrl_state->arena = arena;
|
||||
d_ctrl_state->sock_session = sock_session_open(0, d_ctrl_sock_wakeup);
|
||||
for EachEnumVal(Arch, arch)
|
||||
{
|
||||
ARCH_Info *arch_info = arch_info_from_arch(arch);
|
||||
@@ -57,9 +145,21 @@ d_init(void)
|
||||
d_ctrl_state->ctrl_thread_entity_store = d_entity_ctx_rw_store_alloc();
|
||||
d_ctrl_state->ctrl_thread_eval_cache = e_cache_alloc();
|
||||
d_ctrl_state->ctrl_thread_msg_process_arena = arena_alloc();
|
||||
d_ctrl_state->server_slots_count = 16;
|
||||
d_ctrl_state->server_slots = push_array(arena, D_ServerSlot, d_ctrl_state->server_slots_count);
|
||||
{
|
||||
D_ServerState *ss = push_array(arena, D_ServerState, 1);
|
||||
ss->server_id = D_ServerID_LocalHost;
|
||||
ss->dmn_event_arena = arena_alloc();
|
||||
U64 slot_idx = ss->server_id%d_ctrl_state->server_slots_count;
|
||||
DLLPushBack_NP(d_ctrl_state->first_server, d_ctrl_state->last_server, ss, order_next, order_prev);
|
||||
DLLPushBack_NP(d_ctrl_state->server_slots[slot_idx].first, d_ctrl_state->server_slots[slot_idx].last, ss, hash_next, hash_prev);
|
||||
d_ctrl_state->next_dequeue_server = ss;
|
||||
}
|
||||
#if 0
|
||||
d_ctrl_state->dmn_event_arena = arena_alloc();
|
||||
#endif
|
||||
d_ctrl_state->user_entry_point_arena = arena_alloc();
|
||||
d_ctrl_state->dbg_dir_arena = arena_alloc();
|
||||
for(D_ExceptionCodeKind k = (D_ExceptionCodeKind)0; k < D_ExceptionCodeKind_COUNT; k = (D_ExceptionCodeKind)(k+1))
|
||||
{
|
||||
if(d_exception_code_kind_default_enable_table[k])
|
||||
|
||||
@@ -4,11 +4,25 @@
|
||||
#ifndef DBG_ENGINE_CORE_H
|
||||
#define DBG_ENGINE_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @eval2 Evaluation Bundle
|
||||
|
||||
typedef struct D_Eval D_Eval;
|
||||
struct D_Eval
|
||||
{
|
||||
String8 string;
|
||||
E2_Expr *expr;
|
||||
E2_IRNode *irtree;
|
||||
String8 bytecode;
|
||||
E2_Val val;
|
||||
E2_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ID Types
|
||||
|
||||
typedef U64 D_MsgID;
|
||||
typedef U32 D_MachineID;
|
||||
typedef U32 D_ServerID;
|
||||
typedef U32 D_ControllerKind;
|
||||
typedef enum D_ControllerKindEnum
|
||||
{
|
||||
@@ -17,7 +31,7 @@ typedef enum D_ControllerKindEnum
|
||||
}
|
||||
D_ControllerKindEnum;
|
||||
|
||||
#define D_MachineID_Local (1)
|
||||
#define D_ServerID_LocalHost (1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Handle Types
|
||||
@@ -25,7 +39,7 @@ D_ControllerKindEnum;
|
||||
typedef struct D_Handle D_Handle;
|
||||
struct D_Handle
|
||||
{
|
||||
D_MachineID machine_id;
|
||||
D_ServerID server_id;
|
||||
D_ControllerKind controller_kind;
|
||||
U64 entity_id;
|
||||
};
|
||||
@@ -66,6 +80,7 @@ enum
|
||||
D_BreakpointFlag_BreakOnWrite = (1<<0),
|
||||
D_BreakpointFlag_BreakOnRead = (1<<1),
|
||||
D_BreakpointFlag_BreakOnExecute = (1<<2),
|
||||
D_BreakpointFlag_BreakSelectedThreadOnly = (1<<3),
|
||||
};
|
||||
|
||||
typedef struct D_Breakpoint D_Breakpoint;
|
||||
@@ -236,8 +251,10 @@ struct D_Target
|
||||
String8 stdout_path;
|
||||
String8 stderr_path;
|
||||
String8 stdin_path;
|
||||
String8 remote_address;
|
||||
D_MsgID msg_id;
|
||||
B32 debug_subprocesses;
|
||||
B32 deploy;
|
||||
String8List env;
|
||||
};
|
||||
|
||||
@@ -318,6 +335,11 @@ struct D_TrapNet
|
||||
B32 good_read;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @eval2 Bundled Evaluation Path
|
||||
|
||||
internal D_Eval d_eval_from_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Layer Initialization
|
||||
|
||||
|
||||
+1084
-476
File diff suppressed because it is too large.
Load diff
@@ -218,6 +218,7 @@ struct D_DumpThread
|
||||
D_Handle thread_handle;
|
||||
U32 id;
|
||||
U64 context_foff;
|
||||
String8 name;
|
||||
};
|
||||
|
||||
typedef struct D_DumpModule D_DumpModule;
|
||||
@@ -312,6 +313,45 @@ struct D_ModuleReqCacheNode
|
||||
#define D_WAKEUP_FUNCTION_DEF(name) void name(void)
|
||||
typedef D_WAKEUP_FUNCTION_DEF(D_WakeupFunctionType);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Server State Types
|
||||
//
|
||||
// Each call to `dmn_ctrl_run` can generate a sequence of debug events. We handle
|
||||
// these one at a time, and so after a `dmn_ctrl_run`, we need to store all returned
|
||||
// events in a queue, and process the full queue before doing another `dmn_ctrl_run`.
|
||||
//
|
||||
// Initially, there was just one of these queues, but on moving to multi-server
|
||||
// debugging, we will have a sequence of events generated per-server. Then, we
|
||||
// will just want to round-robin drain the queues before we dispatch another run
|
||||
// to all servers.
|
||||
//
|
||||
|
||||
typedef struct D_ServerState D_ServerState;
|
||||
struct D_ServerState
|
||||
{
|
||||
// rjf: links
|
||||
D_ServerState *hash_next;
|
||||
D_ServerState *hash_prev;
|
||||
D_ServerState *order_next;
|
||||
D_ServerState *order_prev;
|
||||
|
||||
// rjf: server identifier
|
||||
D_ServerID server_id;
|
||||
|
||||
// rjf: demon event queue
|
||||
Arena *dmn_event_arena;
|
||||
DMN_EventNode *first_dmn_event_node;
|
||||
DMN_EventNode *last_dmn_event_node;
|
||||
DMN_EventNode *free_dmn_event_node;
|
||||
};
|
||||
|
||||
typedef struct D_ServerSlot D_ServerSlot;
|
||||
struct D_ServerSlot
|
||||
{
|
||||
D_ServerState *first;
|
||||
D_ServerState *last;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main State Types
|
||||
|
||||
@@ -320,11 +360,12 @@ struct D_CtrlState
|
||||
{
|
||||
Arena *arena;
|
||||
D_WakeupFunctionType *wakeup_hook;
|
||||
SOCK_Session sock_session;
|
||||
|
||||
// rjf: name -> register hash tables for eval
|
||||
E_String2NumMap arch_string2reg_tables[Arch_COUNT];
|
||||
|
||||
// rjf: caches
|
||||
// rjf: shared caches
|
||||
D_ThreadRegCache thread_reg_cache;
|
||||
D_ModuleInfoCache module_info_cache;
|
||||
D_DumpCache dump_cache;
|
||||
@@ -361,17 +402,24 @@ struct D_CtrlState
|
||||
D_EntityCtxRWStore *ctrl_thread_entity_store;
|
||||
E_Cache *ctrl_thread_eval_cache;
|
||||
Arena *ctrl_thread_msg_process_arena;
|
||||
U64 server_slots_count;
|
||||
D_ServerSlot *server_slots;
|
||||
D_ServerState *first_server;
|
||||
D_ServerState *last_server;
|
||||
D_ServerState *free_server;
|
||||
D_ServerState *next_dequeue_server;
|
||||
B32 ctrl_thread_dmn_run_block;
|
||||
#if 0
|
||||
Arena *dmn_event_arena;
|
||||
DMN_EventNode *first_dmn_event_node;
|
||||
DMN_EventNode *last_dmn_event_node;
|
||||
DMN_EventNode *free_dmn_event_node;
|
||||
#endif
|
||||
Arena *user_entry_point_arena;
|
||||
String8List user_entry_points;
|
||||
U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64];
|
||||
B32 auto_download_debug_info;
|
||||
U64 process_counter;
|
||||
Arena *dbg_dir_arena;
|
||||
D_DbgDirNode *dbg_dir_root;
|
||||
D_ServerID server_id_gen;
|
||||
U64 module_req_cache_slots_count;
|
||||
D_ModuleReqCacheNode **module_req_cache_slots;
|
||||
String8List msg_user_bp_touched_files;
|
||||
@@ -425,8 +473,8 @@ internal D_HandleArray d_handle_array_from_list(Arena *arena, D_HandleList *src
|
||||
internal String8 d_string_from_handle(Arena *arena, D_Handle handle);
|
||||
internal D_Handle d_handle_from_string(String8 string);
|
||||
internal DMN_Handle d_dmn_from_handle(D_Handle handle);
|
||||
internal D_Handle d_handle_from_dmn(D_MachineID machine_id, DMN_Handle handle);
|
||||
internal D_Handle d_dump_handle_make(D_MachineID machine_id, U64 id);
|
||||
internal D_Handle d_handle_from_dmn(D_ServerID server_id, DMN_Handle handle);
|
||||
internal D_Handle d_dump_handle_make(D_ServerID server_id, U64 id);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Type Functions
|
||||
@@ -488,6 +536,7 @@ internal D_Entity *d_entity_ancestor_from_kind(D_Entity *entity, D_EntityKind ki
|
||||
internal D_Entity *d_process_from_entity(D_Entity *entity);
|
||||
internal D_Entity *d_module_from_process_vaddr(D_Entity *process, U64 vaddr);
|
||||
internal DI_Key d_dbgi_key_from_module(D_Entity *module);
|
||||
internal DI_Key d_dbgi_key_from_debug_info_path(D_Entity *dbg_path);
|
||||
internal D_Entity *d_module_from_thread_candidates(D_Entity *thread, D_EntityList *candidates);
|
||||
internal U64 d_vaddr_from_voff(D_Entity *module, U64 voff);
|
||||
internal U64 d_voff_from_vaddr(D_Entity *module, U64 vaddr);
|
||||
@@ -548,9 +597,14 @@ internal U64 d_cached_sp_from_thread(D_Handle handle);
|
||||
////////////////////////////////
|
||||
//~ rjf: Module Image Info Functions
|
||||
|
||||
//- rjf: module info stores / evictions
|
||||
internal void d_module_info_store(D_Handle module, Arena **stored_arena, D_ModuleInfo *info);
|
||||
internal void d_module_info_evict(D_Handle module);
|
||||
|
||||
//- rjf: cache lookups
|
||||
internal D_ModuleInfo *d_info_from_module(Access *access, D_Handle module);
|
||||
internal U64 d_entry_point_voff_from_module(D_Handle module_handle);
|
||||
internal U64 d_raddbg_attached_marker_voff_from_module(D_Handle module_handle);
|
||||
internal String8 d_initial_debug_info_path_from_module(Arena *arena, D_Handle module_handle);
|
||||
|
||||
////////////////////////////////
|
||||
@@ -599,10 +653,6 @@ internal void d_ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena,
|
||||
internal void d_ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, D_EvalScope *eval_scope, D_Handle process, D_BreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void d_ctrl_thread__append_program_defined_bp_traps(Arena *arena, D_Entity *bp, DMN_TrapChunkList *traps_out);
|
||||
|
||||
//- rjf: module lifetime open/close work
|
||||
internal void d_ctrl_thread__module_open(D_Handle process, D_Handle module, U64 base_vaddr, DMN_ModuleInfo *module_info);
|
||||
internal void d_ctrl_thread__module_close(D_Handle process, D_Handle module, U64 base_vaddr);
|
||||
|
||||
//- rjf: dump process closing work
|
||||
internal void d_ctrl_thread__close_dump_process(D_MsgID msg_id, D_Handle process);
|
||||
|
||||
@@ -617,10 +667,18 @@ internal B32 d_ctrl_eval_space_read(E_Space space, void *out, E_SpaceRangeInfo *
|
||||
internal D_EvalScope *d_ctrl_thread__eval_scope_begin(Arena *arena, D_BreakpointList *user_bps, D_Entity *thread);
|
||||
internal void d_ctrl_thread__eval_scope_end(D_EvalScope *scope);
|
||||
|
||||
//- rjf: server connection lookups
|
||||
internal D_Handle d_ctrl_thread__handle_from_addr_or_connect(String8 addr);
|
||||
|
||||
//- rjf: control system socket wakeup function
|
||||
internal void d_ctrl_sock_wakeup(void);
|
||||
|
||||
//- rjf: log flusher
|
||||
internal void d_ctrl_thread__end_and_flush_log(void);
|
||||
|
||||
//- rjf: msg kind implementations
|
||||
internal void d_ctrl_thread__open_remote_server(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
|
||||
internal void d_ctrl_thread__close_remote_server(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
|
||||
internal void d_ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
|
||||
internal void d_ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
|
||||
internal void d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
|
||||
|
||||
@@ -53,7 +53,7 @@ d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src)
|
||||
//~ rjf: Path Map Application
|
||||
|
||||
internal String8List
|
||||
d_possible_path_overrides_from_maps_path(Arena *arena, D_Entity *primary_module, D_PathMapArray *path_maps, String8 file_path)
|
||||
d_possible_path_overrides_from_maps_path(Arena *arena, D_PathMapArray *path_maps, String8 file_path)
|
||||
{
|
||||
// NOTE(rjf): This path, given some target file path, scans all file path map
|
||||
// overrides, and collects the set of file paths which could've redirected
|
||||
@@ -73,20 +73,6 @@ d_possible_path_overrides_from_maps_path(Arena *arena, D_Entity *primary_module,
|
||||
PathStyle pth_style = PathStyle_Relative;
|
||||
String8List pth_parts = path_normalized_list_from_string(scratch.arena, file_path, &pth_style);
|
||||
|
||||
//- rjf: push possible overrides by relativizing according to module / debug info
|
||||
{
|
||||
String8 module_folder = str8_chop_last_slash(primary_module->string);
|
||||
String8 path_relative_to_module = path_relative_dst_from_absolute_dst_src(arena, file_path, module_folder);
|
||||
String8 debug_info_path = d_entity_child_from_kind(primary_module, D_EntityKind_DebugInfoPath)->string;
|
||||
String8 debug_info_folder = str8_chop_last_slash(debug_info_path);
|
||||
str8_list_push(arena, &result, path_relative_to_module);
|
||||
if(!path_match_normalized(debug_info_folder, module_folder))
|
||||
{
|
||||
String8 path_relative_to_debug_info = path_relative_dst_from_absolute_dst_src(arena, file_path, debug_info_folder);
|
||||
str8_list_push(arena, &result, path_relative_to_debug_info);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: push possible overrides based on path map rules
|
||||
{
|
||||
for(U64 idx = 0; idx < path_maps->count; idx += 1)
|
||||
@@ -345,7 +331,9 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread)
|
||||
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||
D_Entity *dbg_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath);
|
||||
String8 dbgi_path = dbg_path->string;
|
||||
DI_Key dbgi_key = d_dbgi_key_from_debug_info_path(dbg_path);
|
||||
log_infof("ip_vaddr: 0x%I64x\n", ip_vaddr);
|
||||
log_infof("dbgi_key: {0x%I64x, 0x%I64x}\n", dbgi_key.u64[0], dbgi_key.u64[1]);
|
||||
|
||||
@@ -355,7 +343,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread)
|
||||
Rng1U64 line_vaddr_rng = {0};
|
||||
{
|
||||
U64 ip_voff = d_voff_from_vaddr(module, ip_vaddr);
|
||||
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, ip_voff);
|
||||
D_LineList lines = d_lines_from_dbgi_key_path_voff(scratch.arena, dbgi_key, dbgi_path, ip_voff);
|
||||
Rng1U64 line_voff_rng = {0};
|
||||
if(lines.first != 0)
|
||||
{
|
||||
@@ -404,7 +392,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread)
|
||||
// is enabled. This is enabled by default normally.
|
||||
{
|
||||
U64 opl_line_voff_rng = d_voff_from_vaddr(module, line_vaddr_rng.max);
|
||||
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, opl_line_voff_rng);
|
||||
D_LineList lines = d_lines_from_dbgi_key_path_voff(scratch.arena, dbgi_key, dbgi_path, opl_line_voff_rng);
|
||||
if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee))
|
||||
{
|
||||
line_vaddr_rng.max = d_vaddr_from_voff(module, lines.first->v.voff_range.max);
|
||||
@@ -583,7 +571,9 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
||||
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||
D_Entity *dbg_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath);
|
||||
String8 dbgi_path = dbg_path->string;
|
||||
DI_Key dbgi_key = d_dbgi_key_from_debug_info_path(dbg_path);
|
||||
|
||||
// rjf: ip => line info
|
||||
String8 file_path = {0};
|
||||
@@ -591,7 +581,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
||||
Rng1U64 line_vaddr_rng = {0};
|
||||
{
|
||||
U64 ip_voff = d_voff_from_vaddr(module, ip_vaddr);
|
||||
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, ip_voff);
|
||||
D_LineList lines = d_lines_from_dbgi_key_path_voff(scratch.arena, dbgi_key, dbgi_path, ip_voff);
|
||||
Rng1U64 line_voff_rng = {0};
|
||||
if(lines.first != 0)
|
||||
{
|
||||
@@ -623,7 +613,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
||||
// is enabled. This is enabled by default normally.
|
||||
{
|
||||
U64 opl_line_voff_rng = d_voff_from_vaddr(module, line_vaddr_rng.max);
|
||||
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, opl_line_voff_rng);
|
||||
D_LineList lines = d_lines_from_dbgi_key_path_voff(scratch.arena, dbgi_key, dbgi_path, opl_line_voff_rng);
|
||||
if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee))
|
||||
{
|
||||
line_vaddr_rng.max = d_vaddr_from_voff(module, lines.first->v.voff_range.max);
|
||||
@@ -686,8 +676,10 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
||||
U64 jump_dest_vaddr = point->jump_dest_vaddr;
|
||||
D_Entity *jump_dest_module = d_module_from_process_vaddr(process, jump_dest_vaddr);
|
||||
U64 jump_dest_voff = d_voff_from_vaddr(jump_dest_module, jump_dest_vaddr);
|
||||
DI_Key jump_dest_dbgi_key = d_dbgi_key_from_module(jump_dest_module);
|
||||
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, jump_dest_dbgi_key, jump_dest_voff);
|
||||
D_Entity *jump_dest_dbg_path = d_entity_child_from_kind(jump_dest_module, D_EntityKind_DebugInfoPath);
|
||||
String8 jump_dest_dbgi_path = jump_dest_dbg_path->string;
|
||||
DI_Key jump_dest_dbgi_key = d_dbgi_key_from_debug_info_path(jump_dest_dbg_path);
|
||||
D_LineList lines = d_lines_from_dbgi_key_path_voff(scratch.arena, jump_dest_dbgi_key, jump_dest_dbgi_path, jump_dest_voff);
|
||||
if(lines.count == 0)
|
||||
{
|
||||
add = 0;
|
||||
@@ -996,7 +988,7 @@ d_trap_net_from_thread__step_to_exit(Arena *arena, D_Entity *thread)
|
||||
//- rjf: voff -> line info
|
||||
|
||||
internal D_LineList
|
||||
d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff)
|
||||
d_lines_from_dbgi_key_path_voff(Arena *arena, DI_Key dbgi_key, String8 dbgi_path, U64 voff)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Access *access = access_open();
|
||||
@@ -1064,12 +1056,18 @@ d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff)
|
||||
StringJoin join = {0};
|
||||
join.sep = str8_lit("/");
|
||||
String8 file_normalized_full_path = str8_list_join(arena, &path_parts, &join);
|
||||
String8 file_normalized_full_path_absolute = file_normalized_full_path;
|
||||
if(dbgi_path.size != 0)
|
||||
{
|
||||
String8 dbgi_path_folder = str8_chop_last_slash(dbgi_path);
|
||||
file_normalized_full_path_absolute = path_absolute_dst_from_relative_dst_src(arena, file_normalized_full_path, dbgi_path_folder);
|
||||
}
|
||||
D_LineNode *n = push_array(arena, D_LineNode, 1);
|
||||
SLLQueuePush(result.first, result.last, n);
|
||||
result.count += 1;
|
||||
if(line->file_idx != 0 && file_normalized_full_path.size != 0)
|
||||
if(line->file_idx != 0 && file_normalized_full_path_absolute.size != 0)
|
||||
{
|
||||
n->v.file_path = file_normalized_full_path;
|
||||
n->v.file_path = file_normalized_full_path_absolute;
|
||||
}
|
||||
n->v.pt = txt_pt(line->line_num, column ? column->col_first : 1);
|
||||
n->v.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]);
|
||||
@@ -1145,6 +1143,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key,
|
||||
// rjf: good src-id -> look up line info for visible range
|
||||
if(good_src_id) ProfScope("good src-id -> look up line info for visible range")
|
||||
{
|
||||
String8 match_file_path = str8_copy(arena, file_path);
|
||||
RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id);
|
||||
RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx);
|
||||
RDI_ParsedSourceLineMap line_map = {0};
|
||||
@@ -1171,6 +1170,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key,
|
||||
Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]);
|
||||
S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num;
|
||||
D_LineNode *n = push_array(arena, D_LineNode, 1);
|
||||
n->v.file_path = match_file_path;
|
||||
n->v.voff_range = range;
|
||||
n->v.pt.line = (S64)actual_line;
|
||||
n->v.pt.column = 1;
|
||||
@@ -1569,7 +1569,7 @@ d_next_cmd(D_Cmd **cmd)
|
||||
//~ rjf: Main Layer Top-Level Calls
|
||||
|
||||
internal D_EventList
|
||||
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64], B32 auto_download_debug_info)
|
||||
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, D_Handle selected_thread, U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64], B32 auto_download_debug_info)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
@@ -1683,6 +1683,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
// rjf: build data strings of all param data
|
||||
String8List strings = {0};
|
||||
{
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&selected_thread));
|
||||
D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread);
|
||||
for EachIndex(idx, threads.count)
|
||||
{
|
||||
@@ -1696,6 +1697,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
for(U64 idx = 0; idx < breakpoints->count; idx += 1)
|
||||
{
|
||||
D_Breakpoint *bp = &breakpoints->v[idx];
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->flags));
|
||||
str8_list_push(scratch.arena, &strings, bp->file_path);
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt));
|
||||
str8_list_push(scratch.arena, &strings, bp->vaddr_expr);
|
||||
@@ -1772,6 +1774,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
String8 stdout_path = str8_skip_chop_whitespace(target->stdout_path);
|
||||
String8 stderr_path = str8_skip_chop_whitespace(target->stderr_path);
|
||||
String8 stdin_path = str8_skip_chop_whitespace(target->stdin_path);
|
||||
String8 remote_address = str8_skip_chop_whitespace(target->remote_address);
|
||||
String8List env = target->env;
|
||||
if(working_directory.size == 0)
|
||||
{
|
||||
@@ -1811,12 +1814,14 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
|
||||
msg->msg_id = target->msg_id;
|
||||
msg->kind = D_MsgKind_Launch;
|
||||
msg->address = str8_copy(scratch.arena, remote_address);
|
||||
msg->path = str8_copy(scratch.arena, working_directory);
|
||||
msg->cmd_line_string_list = str8_list_copy(scratch.arena, &cmdln_strings);
|
||||
msg->stdout_path = str8_copy(scratch.arena, stdout_path);
|
||||
msg->stderr_path = str8_copy(scratch.arena, stderr_path);
|
||||
msg->stdin_path = str8_copy(scratch.arena, stdin_path);
|
||||
msg->debug_subprocesses = target->debug_subprocesses;
|
||||
msg->deploy = target->deploy;
|
||||
msg->env_inherit = 1;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
msg->auto_download_debug_info = auto_download_debug_info;
|
||||
@@ -1835,7 +1840,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
// rjf: no targets -> error
|
||||
if(targets_to_launch->count == 0)
|
||||
{
|
||||
log_user_error(str8_lit("No active targets exist; cannot launch. You must select a target first."));
|
||||
log_user_error(s("No active targets exist; cannot launch. You must select a target first."));
|
||||
}
|
||||
}break;
|
||||
case D_CmdKind_Kill:
|
||||
@@ -1843,7 +1848,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Entity *process = d_entity_from_handle(params->process);
|
||||
if(process == &d_entity_nil)
|
||||
{
|
||||
log_user_error(str8_lit("Cannot kill; no process was specified."));
|
||||
log_user_error(s("Cannot kill; no process was specified."));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1868,7 +1873,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Entity *process = d_entity_from_handle(params->process);
|
||||
if(process == &d_entity_nil)
|
||||
{
|
||||
log_user_error(str8_lit("Cannot detach; no process specified."));
|
||||
log_user_error(s("Cannot detach; no process specified."));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1882,19 +1887,28 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
case D_CmdKind_Continue:
|
||||
{
|
||||
B32 good_to_run = 0;
|
||||
B32 any_non_dump_threads = 0;
|
||||
D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread);
|
||||
if(threads.count > 0)
|
||||
{
|
||||
for EachIndex(idx, threads.count)
|
||||
{
|
||||
D_Entity *thread = threads.v[idx];
|
||||
if(threads.v[idx]->handle.controller_kind != D_ControllerKind_Dump)
|
||||
{
|
||||
any_non_dump_threads = 1;
|
||||
}
|
||||
if(!thread->is_frozen)
|
||||
{
|
||||
good_to_run = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(good_to_run)
|
||||
if(!any_non_dump_threads)
|
||||
{
|
||||
log_user_error(s("Cannot run with only dump file threads."));
|
||||
}
|
||||
else if(good_to_run)
|
||||
{
|
||||
need_run = 1;
|
||||
run_kind = D_RunKind_Run;
|
||||
@@ -1902,7 +1916,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
else
|
||||
{
|
||||
log_user_error(str8_lit("Cannot run with all threads frozen."));
|
||||
log_user_error(s("Cannot run with all threads frozen."));
|
||||
}
|
||||
}
|
||||
}break;
|
||||
@@ -1916,18 +1930,22 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Entity *thread = d_entity_from_handle(params->thread);
|
||||
if(thread == &d_entity_nil)
|
||||
{
|
||||
log_user_error(str8_lit("Must have a selected thread to step."));
|
||||
log_user_error(s("Must have a selected thread to step."));
|
||||
}
|
||||
else if(thread->handle.controller_kind == D_ControllerKind_Dump)
|
||||
{
|
||||
log_user_error(s("Cannot step a thread from a dump file."));
|
||||
}
|
||||
else if(d_ctrl_targets_running())
|
||||
{
|
||||
if(d_ctrl_last_run_kind() == D_RunKind_Run)
|
||||
{
|
||||
log_user_error(str8_lit("Must halt before stepping."));
|
||||
log_user_error(s("Must halt before stepping."));
|
||||
}
|
||||
}
|
||||
else if(thread->is_frozen)
|
||||
{
|
||||
log_user_error(str8_lit("Must thaw selected thread before stepping."));
|
||||
log_user_error(s("Must thaw selected thread before stepping."));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1967,7 +1985,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
else if(!good_trap_net)
|
||||
{
|
||||
log_user_error(str8_lit("Could not successfully step."));
|
||||
log_user_error(s("Could not successfully step."));
|
||||
}
|
||||
}
|
||||
}break;
|
||||
@@ -1981,19 +1999,26 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
{
|
||||
need_run = 1;
|
||||
run_kind = d_user_state->ctrl_last_run_kind;
|
||||
run_thread = d_entity_from_handle(d_user_state->ctrl_last_run_thread_handle);
|
||||
run_thread = d_entity_from_handle(selected_thread);
|
||||
run_flags = d_user_state->ctrl_last_run_flags;
|
||||
run_traps = d_user_state->ctrl_last_run_traps;
|
||||
}break;
|
||||
case D_CmdKind_SetThreadIP:
|
||||
{
|
||||
D_Entity *thread = d_entity_from_handle(params->thread);
|
||||
if(thread->handle.controller_kind == D_ControllerKind_Dump)
|
||||
{
|
||||
log_user_error(s("Cannot write register values to dump file threads."));
|
||||
}
|
||||
else
|
||||
{
|
||||
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
||||
U64 vaddr = params->vaddr;
|
||||
void *block = d_cached_reg_block_from_thread(scratch.arena, thread->handle);
|
||||
arch_reg_block_write_ip(arch_info, block, vaddr);
|
||||
B32 result = d_thread_write_reg_block(thread->handle, block);
|
||||
(void)result;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: high-level composite target control operations
|
||||
@@ -2010,6 +2035,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
{
|
||||
run_extra_bps.v[0].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr);
|
||||
}
|
||||
run_extra_bps.v[0].flags |= D_BreakpointFlag_BreakSelectedThreadOnly;
|
||||
d_cmd(D_CmdKind_Run);
|
||||
}break;
|
||||
case D_CmdKind_RunToName:
|
||||
@@ -2024,7 +2050,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process);
|
||||
if(processes.count != 0)
|
||||
{
|
||||
d_cmd(D_CmdKind_Continue, .machine = params->machine, .process = params->process, .thread = params->thread);
|
||||
d_cmd(D_CmdKind_Continue, .server = params->server, .process = params->process, .thread = params->thread);
|
||||
}
|
||||
else if(!d_ctrl_targets_running())
|
||||
{
|
||||
@@ -2069,25 +2095,25 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
case D_CmdKind_ThawThread:
|
||||
case D_CmdKind_FreezeProcess:
|
||||
case D_CmdKind_ThawProcess:
|
||||
case D_CmdKind_FreezeMachine:
|
||||
case D_CmdKind_ThawMachine:
|
||||
case D_CmdKind_FreezeServer:
|
||||
case D_CmdKind_ThawServer:
|
||||
{
|
||||
D_CmdKind disptch_kind = ((cmd->kind == D_CmdKind_FreezeThread ||
|
||||
cmd->kind == D_CmdKind_FreezeProcess ||
|
||||
cmd->kind == D_CmdKind_FreezeMachine)
|
||||
cmd->kind == D_CmdKind_FreezeServer)
|
||||
? D_CmdKind_FreezeEntity
|
||||
: D_CmdKind_ThawEntity);
|
||||
d_push_cmd(disptch_kind, params);
|
||||
}break;
|
||||
case D_CmdKind_FreezeLocalMachine:
|
||||
case D_CmdKind_FreezeLocalServer:
|
||||
{
|
||||
D_MachineID machine_id = D_MachineID_Local;
|
||||
d_cmd(D_CmdKind_FreezeMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero()));
|
||||
D_ServerID server_id = D_ServerID_LocalHost;
|
||||
d_cmd(D_CmdKind_FreezeServer, .entity = d_handle_from_dmn(server_id, dmn_handle_zero()));
|
||||
}break;
|
||||
case D_CmdKind_ThawLocalMachine:
|
||||
case D_CmdKind_ThawLocalServer:
|
||||
{
|
||||
D_MachineID machine_id = D_MachineID_Local;
|
||||
d_cmd(D_CmdKind_ThawMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero()));
|
||||
D_ServerID server_id = D_ServerID_LocalHost;
|
||||
d_cmd(D_CmdKind_ThawServer, .entity = d_handle_from_dmn(server_id, dmn_handle_zero()));
|
||||
}break;
|
||||
case D_CmdKind_FreezeEntity:
|
||||
case D_CmdKind_ThawEntity:
|
||||
@@ -2110,7 +2136,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
{
|
||||
need_run = 1;
|
||||
run_kind = d_user_state->ctrl_last_run_kind;
|
||||
run_thread = d_entity_from_handle(d_user_state->ctrl_last_run_thread_handle);
|
||||
run_thread = d_entity_from_handle(selected_thread);
|
||||
run_flags = d_user_state->ctrl_last_run_flags;
|
||||
run_traps = d_user_state->ctrl_last_run_traps;
|
||||
}
|
||||
@@ -2133,7 +2159,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
{
|
||||
Access *access = access_open();
|
||||
D_ModuleInfo *info = d_info_from_module(access, params->entity);
|
||||
String8 symbol_server_local_cache_path = smsv_local_path_from_key(scratch.arena, info->dbg_name, info->dbg_guid, info->dbg_age);
|
||||
String8 symbol_server_local_cache_path = smsv_local_debug_info_path_from_key(scratch.arena, info->dbg_name, info->dbg_guid, info->dbg_age);
|
||||
smsv_fill_local_path(symbol_server_local_cache_path);
|
||||
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
|
||||
msg->kind = D_MsgKind_SetModuleDebugInfoPath;
|
||||
@@ -2168,6 +2194,24 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
msg->auto_download_debug_info = auto_download_debug_info;
|
||||
}break;
|
||||
|
||||
//- rjf: opening/closing remote debuggers
|
||||
case D_CmdKind_OpenRemoteServer:
|
||||
{
|
||||
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
|
||||
msg->kind = D_MsgKind_OpenRemoteServer;
|
||||
msg->address = str8_copy(scratch.arena, params->string);
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
msg->auto_download_debug_info = auto_download_debug_info;
|
||||
}break;
|
||||
case D_CmdKind_CloseRemoteServer:
|
||||
{
|
||||
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
|
||||
msg->kind = D_MsgKind_CloseRemoteServer;
|
||||
msg->entity = params->entity;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
msg->auto_download_debug_info = auto_download_debug_info;
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: do run if needed
|
||||
@@ -2178,12 +2222,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
d_user_state->ctrl_last_run_param_state_hash = ctrl_param_state_hash;
|
||||
}
|
||||
|
||||
// rjf: unpack target thread/module
|
||||
D_Entity *thread = d_entity_from_handle(params->thread);
|
||||
D_Entity *process = d_process_from_entity(thread);
|
||||
U64 thread_ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, thread_ip_vaddr);
|
||||
|
||||
// rjf: push & fill run message
|
||||
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
|
||||
{
|
||||
@@ -2211,7 +2249,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
// rjf: textual location -> add breakpoints for all possible override locations
|
||||
if(bp->file_path.size != 0 && bp->pt.line != 0)
|
||||
{
|
||||
String8List overrides = d_possible_path_overrides_from_maps_path(scratch.arena, module, path_maps, bp->file_path);
|
||||
String8List overrides = d_possible_path_overrides_from_maps_path(scratch.arena, path_maps, bp->file_path);
|
||||
for(String8Node *n = overrides.first; n != 0; n = n->next)
|
||||
{
|
||||
D_Breakpoint dst_bp = {0};
|
||||
@@ -2238,7 +2276,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
arena_clear(d_user_state->ctrl_last_run_arena);
|
||||
d_user_state->ctrl_last_run_kind = run_kind;
|
||||
d_user_state->ctrl_last_run_frame_idx = d_frame_index();
|
||||
d_user_state->ctrl_last_run_thread_handle = run_thread->handle;
|
||||
d_user_state->ctrl_last_run_flags = run_flags;
|
||||
d_user_state->ctrl_last_run_traps = d_trap_list_copy(d_user_state->ctrl_last_run_arena, &run_traps_copy);
|
||||
d_user_state->ctrl_last_run_extra_bps = d_breakpoint_array_copy(d_user_state->ctrl_last_run_arena, &run_extra_bps_copy);
|
||||
|
||||
@@ -59,7 +59,7 @@ D_RunKind;
|
||||
typedef struct D_CmdParams D_CmdParams;
|
||||
struct D_CmdParams
|
||||
{
|
||||
D_Handle machine;
|
||||
D_Handle server;
|
||||
D_Handle process;
|
||||
D_Handle thread;
|
||||
D_Handle entity;
|
||||
@@ -160,6 +160,8 @@ struct D_RunLocalsCache
|
||||
typedef enum D_MsgKind
|
||||
{
|
||||
D_MsgKind_Null,
|
||||
D_MsgKind_OpenRemoteServer,
|
||||
D_MsgKind_CloseRemoteServer,
|
||||
D_MsgKind_Launch,
|
||||
D_MsgKind_Attach,
|
||||
D_MsgKind_OpenCrashDump,
|
||||
@@ -195,7 +197,9 @@ struct D_Msg
|
||||
B32 env_inherit;
|
||||
B32 debug_subprocesses;
|
||||
B32 auto_download_debug_info;
|
||||
B32 deploy;
|
||||
U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64];
|
||||
String8 address;
|
||||
String8 path;
|
||||
String8List entry_points;
|
||||
String8List cmd_line_string_list;
|
||||
@@ -263,6 +267,14 @@ typedef enum D_EventKind
|
||||
D_EventKind_MemDecommit,
|
||||
D_EventKind_MemRelease,
|
||||
|
||||
//- rjf: remote server connections
|
||||
D_EventKind_ServerConnect,
|
||||
D_EventKind_ServerDisconnect,
|
||||
|
||||
//- rjf: remote controllers
|
||||
D_EventKind_RemoteControllerConnect,
|
||||
D_EventKind_RemoteControllerDisconnect,
|
||||
|
||||
D_EventKind_COUNT
|
||||
}
|
||||
D_EventKind;
|
||||
@@ -366,7 +378,6 @@ struct D_UserState
|
||||
Arena *ctrl_last_run_arena;
|
||||
D_RunKind ctrl_last_run_kind;
|
||||
U64 ctrl_last_run_frame_idx;
|
||||
D_Handle ctrl_last_run_thread_handle;
|
||||
D_RunFlags ctrl_last_run_flags;
|
||||
D_TrapList ctrl_last_run_traps;
|
||||
D_BreakpointArray ctrl_last_run_extra_bps;
|
||||
@@ -404,7 +415,7 @@ internal D_BreakpointArray d_breakpoint_array_copy(Arena *arena, D_BreakpointArr
|
||||
////////////////////////////////
|
||||
//~ rjf: Path Map Application
|
||||
|
||||
internal String8List d_possible_path_overrides_from_maps_path(Arena *arena, D_Entity *primary_module, D_PathMapArray *path_maps, String8 file_path);
|
||||
internal String8List d_possible_path_overrides_from_maps_path(Arena *arena, D_PathMapArray *path_maps, String8 file_path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug Info Extraction Type Pure Functions
|
||||
@@ -433,7 +444,7 @@ internal D_TrapNet d_trap_net_from_thread__step_to_exit(Arena *arena, D_Entity *
|
||||
//~ rjf: Debug Info Lookups
|
||||
|
||||
//- rjf: voff -> line info
|
||||
internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff);
|
||||
internal D_LineList d_lines_from_dbgi_key_path_voff(Arena *arena, DI_Key dbgi_key, String8 dbgi_path, U64 voff);
|
||||
|
||||
//- rjf: file:line -> line info
|
||||
// TODO(rjf): this depends on file path maps, needs to move
|
||||
@@ -481,6 +492,6 @@ internal B32 d_next_cmd(D_Cmd **cmd);
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Layer Top-Level Calls
|
||||
|
||||
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64], B32 auto_download_debug_info);
|
||||
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, D_Handle selected_thread, U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64], B32 auto_download_debug_info);
|
||||
|
||||
#endif // DBG_ENGINE_USER_H
|
||||
@@ -8,7 +8,7 @@ String8 d_entity_kind_code_name_table[13] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("root"),
|
||||
str8_lit_comp("machine"),
|
||||
str8_lit_comp("server"),
|
||||
str8_lit_comp("process"),
|
||||
str8_lit_comp("thread"),
|
||||
str8_lit_comp("module"),
|
||||
@@ -25,7 +25,7 @@ String8 d_entity_kind_display_string_table[13] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("Root"),
|
||||
str8_lit_comp("Machine"),
|
||||
str8_lit_comp("Server"),
|
||||
str8_lit_comp("Process"),
|
||||
str8_lit_comp("Thread"),
|
||||
str8_lit_comp("Module"),
|
||||
@@ -38,7 +38,7 @@ str8_lit_comp("Breakpoint"),
|
||||
str8_lit_comp("AddressRangeAnnotation"),
|
||||
};
|
||||
|
||||
U32 d_exception_code_kind_code_table[38] =
|
||||
U32 d_exception_code_kind_code_table[69] =
|
||||
{
|
||||
0,
|
||||
0x40010005,
|
||||
@@ -78,51 +78,186 @@ U32 d_exception_code_kind_code_table[38] =
|
||||
0xe073616e,
|
||||
0xe0736171,
|
||||
0x0000087a,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
};
|
||||
|
||||
String8 d_exception_code_kind_display_string_table[38] =
|
||||
OperatingSystem d_exception_code_kind_os_table[69] =
|
||||
{
|
||||
OperatingSystem_Null,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Linux,
|
||||
};
|
||||
|
||||
String8 d_exception_code_kind_display_string_table[69] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("(Win32) Control-C"),
|
||||
str8_lit_comp("(Win32) Control-Break"),
|
||||
str8_lit_comp("(Win32) WinRT Originate Error"),
|
||||
str8_lit_comp("(Win32) WinRT Transform Error"),
|
||||
str8_lit_comp("(Win32) RPC Call Cancelled"),
|
||||
str8_lit_comp("(Win32) Data Type Misalignment"),
|
||||
str8_lit_comp("(Win32) Access Violation"),
|
||||
str8_lit_comp("(Win32) In Page Error"),
|
||||
str8_lit_comp("(Win32) Invalid Handle Specified"),
|
||||
str8_lit_comp("(Win32) Not Enough Quota"),
|
||||
str8_lit_comp("(Win32) Illegal Instruction"),
|
||||
str8_lit_comp("(Win32) Cannot Continue From Exception"),
|
||||
str8_lit_comp("(Win32) Invalid Exception Disposition Returned By Handler"),
|
||||
str8_lit_comp("(Win32) Array Bounds Exceeded"),
|
||||
str8_lit_comp("(Win32) Floating-Point Denormal Operand"),
|
||||
str8_lit_comp("(Win32) Floating-Point Division By Zero"),
|
||||
str8_lit_comp("(Win32) Floating-Point Inexact Result"),
|
||||
str8_lit_comp("(Win32) Floating-Point Invalid Operation"),
|
||||
str8_lit_comp("(Win32) Floating-Point Overflow"),
|
||||
str8_lit_comp("(Win32) Floating-Point Stack Check"),
|
||||
str8_lit_comp("(Win32) Floating-Point Underflow"),
|
||||
str8_lit_comp("(Win32) Integer Division By Zero"),
|
||||
str8_lit_comp("(Win32) Integer Overflow"),
|
||||
str8_lit_comp("(Win32) Privileged Instruction"),
|
||||
str8_lit_comp("(Win32) Stack Overflow"),
|
||||
str8_lit_comp("(Win32) Unable To Locate DLL"),
|
||||
str8_lit_comp("(Win32) Ordinal Not Found"),
|
||||
str8_lit_comp("(Win32) Entry Point Not Found"),
|
||||
str8_lit_comp("(Win32) DLL Initialization Failed"),
|
||||
str8_lit_comp("(Win32) Floating Point SSE Multiple Faults"),
|
||||
str8_lit_comp("(Win32) Floating Point SSE Multiple Traps"),
|
||||
str8_lit_comp("(Win32) Assertion Failed"),
|
||||
str8_lit_comp("(Win32) Module Not Found"),
|
||||
str8_lit_comp("(Win32) Procedure Not Found"),
|
||||
str8_lit_comp("(Win32) Sanitizer Error Detected"),
|
||||
str8_lit_comp("(Win32) Sanitizer Raw Access Violation"),
|
||||
str8_lit_comp("(Win32) DirectX Debug Layer"),
|
||||
str8_lit_comp("Control-C"),
|
||||
str8_lit_comp("Control-Break"),
|
||||
str8_lit_comp("WinRT Originate Error"),
|
||||
str8_lit_comp("WinRT Transform Error"),
|
||||
str8_lit_comp("RPC Call Cancelled"),
|
||||
str8_lit_comp("Data Type Misalignment"),
|
||||
str8_lit_comp("Access Violation"),
|
||||
str8_lit_comp("In Page Error"),
|
||||
str8_lit_comp("Invalid Handle Specified"),
|
||||
str8_lit_comp("Not Enough Quota"),
|
||||
str8_lit_comp("Illegal Instruction"),
|
||||
str8_lit_comp("Cannot Continue From Exception"),
|
||||
str8_lit_comp("Invalid Exception Disposition Returned By Handler"),
|
||||
str8_lit_comp("Array Bounds Exceeded"),
|
||||
str8_lit_comp("Floating-Point Denormal Operand"),
|
||||
str8_lit_comp("Floating-Point Division By Zero"),
|
||||
str8_lit_comp("Floating-Point Inexact Result"),
|
||||
str8_lit_comp("Floating-Point Invalid Operation"),
|
||||
str8_lit_comp("Floating-Point Overflow"),
|
||||
str8_lit_comp("Floating-Point Stack Check"),
|
||||
str8_lit_comp("Floating-Point Underflow"),
|
||||
str8_lit_comp("Integer Division By Zero"),
|
||||
str8_lit_comp("Integer Overflow"),
|
||||
str8_lit_comp("Privileged Instruction"),
|
||||
str8_lit_comp("Stack Overflow"),
|
||||
str8_lit_comp("Unable To Locate DLL"),
|
||||
str8_lit_comp("Ordinal Not Found"),
|
||||
str8_lit_comp("Entry Point Not Found"),
|
||||
str8_lit_comp("DLL Initialization Failed"),
|
||||
str8_lit_comp("Floating Point SSE Multiple Faults"),
|
||||
str8_lit_comp("Floating Point SSE Multiple Traps"),
|
||||
str8_lit_comp("Assertion Failed"),
|
||||
str8_lit_comp("Module Not Found"),
|
||||
str8_lit_comp("Procedure Not Found"),
|
||||
str8_lit_comp("Sanitizer Error Detected"),
|
||||
str8_lit_comp("Sanitizer Raw Access Violation"),
|
||||
str8_lit_comp("DirectX Debug Layer"),
|
||||
str8_lit_comp("SIGHUP (Hangup detected on controlling terminal or death of controlling process)"),
|
||||
str8_lit_comp("SIGINT (Interrupt from keyboard)"),
|
||||
str8_lit_comp("SIGQUIT (Quit from keyboard)"),
|
||||
str8_lit_comp("SIGILL (Illegal Instruction)"),
|
||||
str8_lit_comp("SIGTRAP (Trace/breakpoint trap)"),
|
||||
str8_lit_comp("SIGABRT (Abort signal)"),
|
||||
str8_lit_comp("SIGBUS (Bus error (bad address))"),
|
||||
str8_lit_comp("SIGFPE (Erroneous arithmetic operation)"),
|
||||
str8_lit_comp("SIGKILL (Kill signal)"),
|
||||
str8_lit_comp("SIGUSR1 (User-defined signal 1)"),
|
||||
str8_lit_comp("SIGSEGV (Invalid memory reference)"),
|
||||
str8_lit_comp("SIGUSR2 (User-defined signal 2)"),
|
||||
str8_lit_comp("SIGPIPE (Broken pipe; write to pipe with no readers)"),
|
||||
str8_lit_comp("SIGALRM (Timer signal)"),
|
||||
str8_lit_comp("SIGTERM (Termination signal)"),
|
||||
str8_lit_comp("SIGSTKFLT (Stack fault on coprocessor)"),
|
||||
str8_lit_comp("SIGCHLD (Child stopped, terminated, or continued)"),
|
||||
str8_lit_comp("SIGCONT (Continue if stopped)"),
|
||||
str8_lit_comp("SIGSTOP (Stop process)"),
|
||||
str8_lit_comp("SIGTSTP (Stop typed at terminal)"),
|
||||
str8_lit_comp("SIGTTIN (Terminal input for background process)"),
|
||||
str8_lit_comp("SIGTTOU (Terminal output for background process)"),
|
||||
str8_lit_comp("SIGURG (Urgent condition on socket)"),
|
||||
str8_lit_comp("SIGXCPU (CPU time limit exceeded)"),
|
||||
str8_lit_comp("SIGXFSZ (File size limit exceeded)"),
|
||||
str8_lit_comp("SIGVTALRM (Virtual alarm clock)"),
|
||||
str8_lit_comp("SIGPROF (Profiling timer expired)"),
|
||||
str8_lit_comp("SIGWINCH (Window resize signal)"),
|
||||
str8_lit_comp("SIGIO (I/O now possible)"),
|
||||
str8_lit_comp("SIGPWR (Power failure)"),
|
||||
str8_lit_comp("SIGSYS (Bad system call)"),
|
||||
};
|
||||
|
||||
String8 d_exception_code_kind_lowercase_code_string_table[38] =
|
||||
String8 d_exception_code_kind_lowercase_code_string_table[69] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("win32_ctrl_c"),
|
||||
@@ -162,9 +297,40 @@ str8_lit_comp("win32_procedure_not_found"),
|
||||
str8_lit_comp("win32_sanitizer_error_detected"),
|
||||
str8_lit_comp("win32_sanitizer_raw_access_violation"),
|
||||
str8_lit_comp("win32_directx_debug_layer"),
|
||||
str8_lit_comp("linux_sighup"),
|
||||
str8_lit_comp("linux_sigint"),
|
||||
str8_lit_comp("linux_sigquit"),
|
||||
str8_lit_comp("linux_sigill"),
|
||||
str8_lit_comp("linux_sigtrap"),
|
||||
str8_lit_comp("linux_sigabrt"),
|
||||
str8_lit_comp("linux_sigbus"),
|
||||
str8_lit_comp("linux_sigfpe"),
|
||||
str8_lit_comp("linux_sigkill"),
|
||||
str8_lit_comp("linux_sigusr1"),
|
||||
str8_lit_comp("linux_sigsegv"),
|
||||
str8_lit_comp("linux_sigusr2"),
|
||||
str8_lit_comp("linux_sigpipe"),
|
||||
str8_lit_comp("linux_sigalrm"),
|
||||
str8_lit_comp("linux_sigterm"),
|
||||
str8_lit_comp("linux_sigstkflt"),
|
||||
str8_lit_comp("linux_sigchld"),
|
||||
str8_lit_comp("linux_sigcont"),
|
||||
str8_lit_comp("linux_sigstop"),
|
||||
str8_lit_comp("linux_sigtstp"),
|
||||
str8_lit_comp("linux_sigttin"),
|
||||
str8_lit_comp("linux_sigttou"),
|
||||
str8_lit_comp("linux_sigurg"),
|
||||
str8_lit_comp("linux_sigxcpu"),
|
||||
str8_lit_comp("linux_sigxfsz"),
|
||||
str8_lit_comp("linux_sigvtalrm"),
|
||||
str8_lit_comp("linux_sigprof"),
|
||||
str8_lit_comp("linux_sigwinch"),
|
||||
str8_lit_comp("linux_sigio"),
|
||||
str8_lit_comp("linux_sigpwr"),
|
||||
str8_lit_comp("linux_sigsys"),
|
||||
};
|
||||
|
||||
B8 d_exception_code_kind_default_enable_table[38] =
|
||||
B8 d_exception_code_kind_default_enable_table[69] =
|
||||
{
|
||||
0,
|
||||
1,
|
||||
@@ -204,6 +370,37 @@ B8 d_exception_code_kind_default_enable_table[38] =
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
};
|
||||
|
||||
C_LINKAGE_END
|
||||
|
||||
@@ -34,10 +34,10 @@ D_CmdKind_FreezeThread,
|
||||
D_CmdKind_ThawThread,
|
||||
D_CmdKind_FreezeProcess,
|
||||
D_CmdKind_ThawProcess,
|
||||
D_CmdKind_FreezeMachine,
|
||||
D_CmdKind_ThawMachine,
|
||||
D_CmdKind_FreezeLocalMachine,
|
||||
D_CmdKind_ThawLocalMachine,
|
||||
D_CmdKind_FreezeServer,
|
||||
D_CmdKind_ThawServer,
|
||||
D_CmdKind_FreezeLocalServer,
|
||||
D_CmdKind_ThawLocalServer,
|
||||
D_CmdKind_FreezeEntity,
|
||||
D_CmdKind_ThawEntity,
|
||||
D_CmdKind_SetEntityColor,
|
||||
@@ -45,6 +45,8 @@ D_CmdKind_SetEntityName,
|
||||
D_CmdKind_DownloadModuleDebugInfo,
|
||||
D_CmdKind_Attach,
|
||||
D_CmdKind_OpenCrashDump,
|
||||
D_CmdKind_OpenRemoteServer,
|
||||
D_CmdKind_CloseRemoteServer,
|
||||
D_CmdKind_COUNT,
|
||||
} D_CmdKind;
|
||||
|
||||
@@ -52,7 +54,7 @@ typedef enum D_EntityKind
|
||||
{
|
||||
D_EntityKind_Null,
|
||||
D_EntityKind_Root,
|
||||
D_EntityKind_Machine,
|
||||
D_EntityKind_Server,
|
||||
D_EntityKind_Process,
|
||||
D_EntityKind_Thread,
|
||||
D_EntityKind_Module,
|
||||
@@ -106,6 +108,37 @@ D_ExceptionCodeKind_Win32ProcedureNotFound,
|
||||
D_ExceptionCodeKind_Win32SanitizerErrorDetected,
|
||||
D_ExceptionCodeKind_Win32SanitizerRawAccessViolation,
|
||||
D_ExceptionCodeKind_Win32DirectXDebugLayer,
|
||||
D_ExceptionCodeKind_LinuxSIGHUP,
|
||||
D_ExceptionCodeKind_LinuxSIGINT,
|
||||
D_ExceptionCodeKind_LinuxSIGQUIT,
|
||||
D_ExceptionCodeKind_LinuxSIGILL,
|
||||
D_ExceptionCodeKind_LinuxSIGTRAP,
|
||||
D_ExceptionCodeKind_LinuxSIGABRT,
|
||||
D_ExceptionCodeKind_LinuxSIGBUS,
|
||||
D_ExceptionCodeKind_LinuxSIGFPE,
|
||||
D_ExceptionCodeKind_LinuxSIGKILL,
|
||||
D_ExceptionCodeKind_LinuxSIGUSR1,
|
||||
D_ExceptionCodeKind_LinuxSIGSEGV,
|
||||
D_ExceptionCodeKind_LinuxSIGUSR2,
|
||||
D_ExceptionCodeKind_LinuxSIGPIPE,
|
||||
D_ExceptionCodeKind_LinuxSIGALRM,
|
||||
D_ExceptionCodeKind_LinuxSIGTERM,
|
||||
D_ExceptionCodeKind_LinuxSIGSTKFLT,
|
||||
D_ExceptionCodeKind_LinuxSIGCHLD,
|
||||
D_ExceptionCodeKind_LinuxSIGCONT,
|
||||
D_ExceptionCodeKind_LinuxSIGSTOP,
|
||||
D_ExceptionCodeKind_LinuxSIGTSTP,
|
||||
D_ExceptionCodeKind_LinuxSIGTTIN,
|
||||
D_ExceptionCodeKind_LinuxSIGTTOU,
|
||||
D_ExceptionCodeKind_LinuxSIGURG,
|
||||
D_ExceptionCodeKind_LinuxSIGXCPU,
|
||||
D_ExceptionCodeKind_LinuxSIGXFSZ,
|
||||
D_ExceptionCodeKind_LinuxSIGVTALRM,
|
||||
D_ExceptionCodeKind_LinuxSIGPROF,
|
||||
D_ExceptionCodeKind_LinuxSIGWINCH,
|
||||
D_ExceptionCodeKind_LinuxSIGIO,
|
||||
D_ExceptionCodeKind_LinuxSIGPWR,
|
||||
D_ExceptionCodeKind_LinuxSIGSYS,
|
||||
D_ExceptionCodeKind_COUNT,
|
||||
} D_ExceptionCodeKind;
|
||||
|
||||
@@ -133,10 +166,11 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 d_entity_kind_code_name_table[13];
|
||||
extern String8 d_entity_kind_display_string_table[13];
|
||||
extern U32 d_exception_code_kind_code_table[38];
|
||||
extern String8 d_exception_code_kind_display_string_table[38];
|
||||
extern String8 d_exception_code_kind_lowercase_code_string_table[38];
|
||||
extern B8 d_exception_code_kind_default_enable_table[38];
|
||||
extern U32 d_exception_code_kind_code_table[69];
|
||||
extern OperatingSystem d_exception_code_kind_os_table[69];
|
||||
extern String8 d_exception_code_kind_display_string_table[69];
|
||||
extern String8 d_exception_code_kind_lowercase_code_string_table[69];
|
||||
extern B8 d_exception_code_kind_default_enable_table[69];
|
||||
|
||||
C_LINKAGE_END
|
||||
|
||||
|
||||
+10
-5
@@ -483,6 +483,10 @@ di_rdi_from_key(Access *access, DI_Key key, B32 high_priority, U64 endt_us)
|
||||
rdi = &n->rdi;
|
||||
access_touch(access, &n->access_pt, stripe->cv);
|
||||
}
|
||||
if(ins_atomic_u64_eval(&n->working_count) != 0)
|
||||
{
|
||||
rdi = &di_rdi_parsed_nil_waiting;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -748,7 +752,7 @@ di_async_tick(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
rdi_path = str8f(scratch.arena, "%S.rdi", str8_chop_last_dot(og_path));
|
||||
rdi_path = str8f(scratch.arena, "%S.rdi", og_path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,7 +789,7 @@ di_async_tick(void)
|
||||
make_directory(cache_folder);
|
||||
make_directory(raddbg_folder);
|
||||
make_directory(rdis_folder);
|
||||
rdi_path = str8f(scratch.arena, "%S/%S.rdi", rdis_folder, str8_chop_last_dot(str8_skip_last_slash(og_path)));
|
||||
rdi_path = str8f(scratch.arena, "%S/%S.rdi", rdis_folder, str8_skip_last_slash(og_path));
|
||||
}
|
||||
|
||||
//- rjf: determine if RDI is stale
|
||||
@@ -1699,6 +1703,8 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out,
|
||||
RDI_SectionKind_Procedures,
|
||||
RDI_SectionKind_TypeNodes,
|
||||
};
|
||||
for EachElement(name_map_kind_idx, name_map_kinds)
|
||||
{
|
||||
Rng1U64 range = lane_range(dbgi_keys.count);
|
||||
for EachInRange(dbgi_idx, range)
|
||||
{
|
||||
@@ -1711,8 +1717,7 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out,
|
||||
{
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx);
|
||||
for EachElement(name_map_kind_idx, name_map_kinds)
|
||||
{
|
||||
|
||||
// rjf: unpack name map
|
||||
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
|
||||
RDI_ParsedNameMap parsed_name_map = {0};
|
||||
@@ -1817,11 +1822,11 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out,
|
||||
lane_matches[lane_idx()].count = filtered_matches_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
access_close(access);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//- rjf: pick match
|
||||
|
||||
@@ -305,6 +305,7 @@ struct DI_Shared
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only RDI_Parsed di_rdi_parsed_nil_waiting = {0};
|
||||
global DI_Shared *di_shared = 0;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,522 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Parsing
|
||||
|
||||
internal DS_Msg
|
||||
ds_msg_from_packet(Arena *arena, String8 data)
|
||||
{
|
||||
//- rjf: read packet header
|
||||
DS_PacketHeader header = {0};
|
||||
{
|
||||
str8_deserial_read_struct(data, 0, &header);
|
||||
}
|
||||
|
||||
//- rjf: get message payload part
|
||||
String8 payload = str8_substr(data, r1u64(sizeof(header), sizeof(header)+header.payload_size));
|
||||
|
||||
//- rjf: read message
|
||||
DS_Msg msg = {0};
|
||||
if(header.magic == DS_PACKET_MAGIC && header.kind == DS_PacketKind_Msg && header.version == DS_PACKET_VERSION)
|
||||
{
|
||||
U64 off = 0;
|
||||
|
||||
// rjf: read flat parts
|
||||
off += str8_deserial_read_struct(payload, off, &msg.kind);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.flags);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.msg_id);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.vaddr_range);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.access_flags);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.entity);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.pid);
|
||||
|
||||
// rjf: read launch parameters extension
|
||||
{
|
||||
B8 has_launch_params = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &has_launch_params);
|
||||
if(has_launch_params)
|
||||
{
|
||||
msg.launch_params = push_array(arena, DS_LaunchParams, 1);
|
||||
|
||||
// rjf: read command line strings
|
||||
{
|
||||
U64 cmd_line_string_count = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &cmd_line_string_count);
|
||||
for EachIndex(idx, cmd_line_string_count)
|
||||
{
|
||||
String8 string = {0};
|
||||
off += str8_deserial_read_struct(payload, off, &string.size);
|
||||
string = str8_substr(payload, r1u64(off, off+string.size));
|
||||
off += string.size;
|
||||
str8_list_push(arena, &msg.launch_params->command_line, string);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: read path
|
||||
{
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->path.size);
|
||||
msg.launch_params->path = str8_substr(payload, r1u64(off, off+msg.launch_params->path.size));
|
||||
off += msg.launch_params->path.size;
|
||||
}
|
||||
|
||||
// rjf: read environment strings
|
||||
{
|
||||
U64 env_string_count = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &env_string_count);
|
||||
for EachIndex(idx, env_string_count)
|
||||
{
|
||||
String8 string = {0};
|
||||
off += str8_deserial_read_struct(payload, off, &string.size);
|
||||
string = str8_substr(payload, r1u64(off, off+string.size));
|
||||
off += string.size;
|
||||
str8_list_push(arena, &msg.launch_params->env, string);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: read std i/o paths
|
||||
{
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->stdout_path.size);
|
||||
msg.launch_params->stdout_path = str8_substr(payload, r1u64(off, off+msg.launch_params->stdout_path.size));
|
||||
off += msg.launch_params->stdout_path.size;
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->stdin_path.size);
|
||||
msg.launch_params->stdin_path = str8_substr(payload, r1u64(off, off+msg.launch_params->stdin_path.size));
|
||||
off += msg.launch_params->stdin_path.size;
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->stderr_path.size);
|
||||
msg.launch_params->stderr_path = str8_substr(payload, r1u64(off, off+msg.launch_params->stderr_path.size));
|
||||
off += msg.launch_params->stderr_path.size;
|
||||
}
|
||||
|
||||
// rjf: read bits
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->debug_subprocesses);
|
||||
off += str8_deserial_read_struct(payload, off, &msg.launch_params->inherit_env);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: read traps
|
||||
{
|
||||
U64 trap_count = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &trap_count);
|
||||
for EachIndex(idx, trap_count)
|
||||
{
|
||||
DMN_Trap trap = {0};
|
||||
off += str8_deserial_read_struct(payload, off, &trap.process);
|
||||
off += str8_deserial_read_struct(payload, off, &trap.vaddr);
|
||||
off += str8_deserial_read_struct(payload, off, &trap.id);
|
||||
off += str8_deserial_read_struct(payload, off, &trap.flags);
|
||||
off += str8_deserial_read_struct(payload, off, &trap.size);
|
||||
dmn_trap_chunk_list_push(arena, &msg.traps, trap_count, &trap);
|
||||
}
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ds_packet_from_msg(Arena *arena, DS_Msg *msg)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(scratch.arena, &srl);
|
||||
{
|
||||
// NOTE(rjf): (header wrote to beginning of `srl` at end of path)
|
||||
|
||||
// rjf: write flat parts
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->kind);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->flags);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->msg_id);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->vaddr_range);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->access_flags);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->entity);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->pid);
|
||||
|
||||
// rjf: write launch parameters extension
|
||||
B8 has_launch_params = (msg->launch_params != 0);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &has_launch_params);
|
||||
if(has_launch_params)
|
||||
{
|
||||
// rjf: write command line strings
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->command_line.node_count);
|
||||
for EachNode(n, String8Node, msg->launch_params->command_line.first)
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->string.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, n->string);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: write path
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, msg->launch_params->path);
|
||||
}
|
||||
|
||||
// rjf: write environment strings
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->env.node_count);
|
||||
for EachNode(n, String8Node, msg->launch_params->env.first)
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->string.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, n->string);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: write std i/o paths
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->stdout_path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, msg->launch_params->stdout_path);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->stdin_path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, msg->launch_params->stdin_path);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->stderr_path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, msg->launch_params->stderr_path);
|
||||
}
|
||||
|
||||
// rjf: write bits
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->debug_subprocesses);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->launch_params->inherit_env);
|
||||
}
|
||||
|
||||
// rjf: write traps
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &msg->traps.trap_count);
|
||||
for EachNode(n, DMN_TrapChunkNode, msg->traps.first)
|
||||
{
|
||||
for EachIndex(idx, n->count)
|
||||
{
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v[idx].process);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v[idx].vaddr);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v[idx].id);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v[idx].flags);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v[idx].size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: push packet header (to front)
|
||||
DS_PacketHeader header =
|
||||
{
|
||||
.magic = DS_PACKET_MAGIC,
|
||||
.kind = DS_PacketKind_Msg,
|
||||
.version = DS_PACKET_VERSION,
|
||||
.payload_size = (U32)srl.total_size,
|
||||
};
|
||||
str8_list_push_front(scratch.arena, &srl, str8_copy(scratch.arena, str8_struct(&header)));
|
||||
}
|
||||
String8 result = str8_serial_end(arena, &srl);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DS_Response
|
||||
ds_response_from_packet(Arena *arena, String8 data)
|
||||
{
|
||||
//- rjf: read packet header
|
||||
DS_PacketHeader header = {0};
|
||||
{
|
||||
str8_deserial_read_struct(data, 0, &header);
|
||||
}
|
||||
|
||||
//- rjf: get message payload part
|
||||
String8 payload = str8_substr(data, r1u64(sizeof(header), sizeof(header)+header.payload_size));
|
||||
|
||||
//- rjf: read response
|
||||
DS_Response result = {0};
|
||||
if(header.magic == DS_PACKET_MAGIC && header.kind == DS_PacketKind_Response && header.version == DS_PACKET_VERSION)
|
||||
{
|
||||
U64 off = 0;
|
||||
|
||||
// rjf: read flat parts
|
||||
off += str8_deserial_read_struct(payload, off, &result.msg_id);
|
||||
off += str8_deserial_read_struct(payload, off, &result.entity);
|
||||
off += str8_deserial_read_struct(payload, off, &result.pid);
|
||||
off += str8_deserial_read_struct(payload, off, &result.good);
|
||||
|
||||
// rjf: read data payload
|
||||
off += str8_deserial_read_struct(payload, off, &result.data.size);
|
||||
result.data.str = push_array(arena, U8, result.data.size);
|
||||
off += str8_deserial_read(payload, off, result.data.str, result.data.size, 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ds_packet_from_response(Arena *arena, DS_Response *response)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(scratch.arena, &srl);
|
||||
{
|
||||
// NOTE(rjf): (header wrote to beginning of `srl` at end of path)
|
||||
|
||||
// rjf: write flat parts
|
||||
str8_serial_push_struct(scratch.arena, &srl, &response->msg_id);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &response->entity);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &response->pid);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &response->good);
|
||||
|
||||
// rjf: write data payload
|
||||
str8_serial_push_struct(scratch.arena, &srl, &response->data.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, response->data);
|
||||
|
||||
// rjf: push packet header (to front)
|
||||
DS_PacketHeader header =
|
||||
{
|
||||
.magic = DS_PACKET_MAGIC,
|
||||
.kind = DS_PacketKind_Response,
|
||||
.version = DS_PACKET_VERSION,
|
||||
.payload_size = (U32)srl.total_size,
|
||||
};
|
||||
str8_list_push_front(scratch.arena, &srl, str8_copy(scratch.arena, str8_struct(&header)));
|
||||
}
|
||||
String8 result = str8_serial_end(arena, &srl);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DMN_EventList
|
||||
ds_dmn_events_from_packet(Arena *arena, String8 data)
|
||||
{
|
||||
//- rjf: read packet header
|
||||
DS_PacketHeader header = {0};
|
||||
{
|
||||
str8_deserial_read_struct(data, 0, &header);
|
||||
}
|
||||
|
||||
//- rjf: get message payload part
|
||||
String8 payload = str8_substr(data, r1u64(sizeof(header), sizeof(header)+header.payload_size));
|
||||
|
||||
//- rjf: read events
|
||||
DMN_EventList evts = {0};
|
||||
if(header.magic == DS_PACKET_MAGIC && header.kind == DS_PacketKind_Event && header.version == DS_PACKET_VERSION)
|
||||
{
|
||||
U64 off = 0;
|
||||
U64 demon_event_count = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &demon_event_count);
|
||||
for EachIndex(idx, demon_event_count)
|
||||
{
|
||||
DMN_Event *evt = dmn_event_list_push(arena, &evts);
|
||||
|
||||
// rjf: read flat parts
|
||||
off += str8_deserial_read_struct(payload, off, &evt->kind);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->error_kind);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->memory_kind);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->exception_kind);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->process);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->thread);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->arch);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->address);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->size);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->code);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->flags);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->instruction_pointer);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->stack_pointer);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->user_data);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->exception_repeated);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->tls_root_vaddr);
|
||||
|
||||
// rjf: read string
|
||||
off += str8_deserial_read_struct(payload, off, &evt->string.size);
|
||||
evt->string.str = push_array(arena, U8, evt->string.size);
|
||||
off += str8_deserial_read(payload, off, evt->string.str, evt->string.size, 1);
|
||||
|
||||
// rjf: read module info
|
||||
B8 has_module_info = 0;
|
||||
off += str8_deserial_read_struct(payload, off, &has_module_info);
|
||||
if(!has_module_info)
|
||||
{
|
||||
evt->module_info = &dmn_module_info_nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
evt->module_info = push_array(arena, DMN_ModuleInfo, 1);
|
||||
|
||||
// rjf: read flat parts
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->arch);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->vsize);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->entry_point_voff);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->debug_info_guid);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->debug_info_timestamp);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->debug_info_age);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->tls_index);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->tls_offset);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->pe_intel_pdatas_vaddr_range);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->eh_frame_header_vaddr_range);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->raddbg_info_voff_range);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->raddbg_is_attached_marker_voff);
|
||||
|
||||
// rjf: read paths
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->module_path.size);
|
||||
evt->module_info->module_path.str = push_array(arena, U8, evt->module_info->module_path.size);
|
||||
off += str8_deserial_read(payload, off, evt->module_info->module_path.str, evt->module_info->module_path.size, 1);
|
||||
off += str8_deserial_read_struct(payload, off, &evt->module_info->debug_info_path.size);
|
||||
evt->module_info->debug_info_path.str = push_array(arena, U8, evt->module_info->debug_info_path.size);
|
||||
off += str8_deserial_read(payload, off, evt->module_info->debug_info_path.str, evt->module_info->debug_info_path.size, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return evts;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ds_packet_from_dmn_events(Arena *arena, DMN_EventList evts)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(scratch.arena, &srl);
|
||||
{
|
||||
// NOTE(rjf): (header wrote to beginning of `srl` at end of path)
|
||||
|
||||
// rjf: write events
|
||||
str8_serial_push_struct(scratch.arena, &srl, &evts.count);
|
||||
for EachNode(n, DMN_EventNode, evts.first)
|
||||
{
|
||||
// rjf: write flat parts
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.kind);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.error_kind);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.memory_kind);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.exception_kind);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.process);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.thread);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.arch);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.address);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.size);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.code);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.flags);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.instruction_pointer);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.stack_pointer);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.user_data);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.exception_repeated);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.tls_root_vaddr);
|
||||
|
||||
// rjf: write string
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.string.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, n->v.string);
|
||||
|
||||
// rjf: write module info
|
||||
B8 has_module_info = (n->v.module_info != 0 && n->v.module_info != &dmn_module_info_nil);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &has_module_info);
|
||||
if(has_module_info)
|
||||
{
|
||||
// rjf: write flat parts
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->arch);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->vsize);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->entry_point_voff);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->debug_info_guid);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->debug_info_timestamp);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->debug_info_age);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->tls_index);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->tls_offset);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->pe_intel_pdatas_vaddr_range);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->eh_frame_header_vaddr_range);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->raddbg_info_voff_range);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->raddbg_is_attached_marker_voff);
|
||||
|
||||
// rjf: write paths
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->module_path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, n->v.module_info->module_path);
|
||||
str8_serial_push_struct(scratch.arena, &srl, &n->v.module_info->debug_info_path.size);
|
||||
str8_serial_push_string(scratch.arena, &srl, n->v.module_info->debug_info_path);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: push packet header (to front)
|
||||
DS_PacketHeader header =
|
||||
{
|
||||
.magic = DS_PACKET_MAGIC,
|
||||
.kind = DS_PacketKind_Event,
|
||||
.version = DS_PACKET_VERSION,
|
||||
.payload_size = (U32)srl.total_size,
|
||||
};
|
||||
str8_list_push_front(scratch.arena, &srl, str8_copy(scratch.arena, str8_struct(&header)));
|
||||
}
|
||||
String8 result = str8_serial_end(arena, &srl);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Local Server Functions
|
||||
|
||||
internal U64
|
||||
ds_ctrl_launch(DMN_CtrlCtx *ctrl_ctx, DS_LaunchParams *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//- rjf: produce full stdout/stderr/stdin paths
|
||||
String8 stdout_path = path_absolute_dst_from_relative_dst_src(scratch.arena, params->stdout_path, params->path);
|
||||
String8 stdin_path = path_absolute_dst_from_relative_dst_src(scratch.arena, params->stdin_path, params->path);
|
||||
String8 stderr_path = path_absolute_dst_from_relative_dst_src(scratch.arena, params->stderr_path, params->path);
|
||||
|
||||
//- rjf: obtain stdout/stderr/stdin handles
|
||||
File stdout_handle = {0};
|
||||
File stderr_handle = {0};
|
||||
File stdin_handle = {0};
|
||||
if(stdout_path.size != 0)
|
||||
{
|
||||
File f = file_open(AccessFlag_Write|AccessFlag_Read, stdout_path);
|
||||
file_close(f);
|
||||
stdout_handle = file_open(AccessFlag_Write|AccessFlag_Append|AccessFlag_ShareRead|AccessFlag_ShareWrite|AccessFlag_Inherited, params->stdout_path);
|
||||
}
|
||||
if(stderr_path.size != 0)
|
||||
{
|
||||
File f = file_open(AccessFlag_Write|AccessFlag_Read, stderr_path);
|
||||
file_close(f);
|
||||
stderr_handle = file_open(AccessFlag_Write|AccessFlag_Append|AccessFlag_ShareRead|AccessFlag_ShareWrite|AccessFlag_Inherited, params->stderr_path);
|
||||
}
|
||||
if(stdin_path.size != 0)
|
||||
{
|
||||
stdin_handle = file_open(AccessFlag_Read|AccessFlag_ShareRead|AccessFlag_ShareWrite|AccessFlag_Inherited, stdin_path);
|
||||
}
|
||||
|
||||
//- rjf: launch
|
||||
ProcessLaunchParams dmn_launch_params = {0};
|
||||
{
|
||||
dmn_launch_params.cmd_line = params->command_line;
|
||||
dmn_launch_params.path = params->path;
|
||||
dmn_launch_params.env = params->env;
|
||||
dmn_launch_params.inherit_env = params->inherit_env;
|
||||
dmn_launch_params.debug_subprocesses = params->debug_subprocesses;
|
||||
dmn_launch_params.stdout_file = stdout_handle;
|
||||
dmn_launch_params.stderr_file = stderr_handle;
|
||||
dmn_launch_params.stdin_file = stdin_handle;
|
||||
}
|
||||
U64 pid = dmn_ctrl_launch(ctrl_ctx, &dmn_launch_params);
|
||||
|
||||
//- rjf: close stdout/stderr/stdin files
|
||||
file_close(stdout_handle);
|
||||
file_close(stderr_handle);
|
||||
file_close(stdin_handle);
|
||||
|
||||
scratch_end(scratch);
|
||||
return pid;
|
||||
}
|
||||
|
||||
internal B32
|
||||
ds_ctrl_attach(DMN_CtrlCtx *ctrl_ctx, U32 pid)
|
||||
{
|
||||
B32 result = dmn_ctrl_attach(ctrl_ctx, pid);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
ds_ctrl_kill(DMN_CtrlCtx *ctrl_ctx, DMN_Handle process, U32 exit_code)
|
||||
{
|
||||
B32 result = dmn_ctrl_kill(ctrl_ctx, process, exit_code);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
ds_ctrl_detach(DMN_CtrlCtx *ctrl_ctx, DMN_Handle process)
|
||||
{
|
||||
B32 result = dmn_ctrl_detach(ctrl_ctx, process);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DMN_EventList
|
||||
ds_ctrl_run(Arena *arena, DMN_CtrlCtx *ctrl_ctx, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
DMN_EventList events = dmn_ctrl_run(arena, ctrl_ctx, ctrls);
|
||||
return events;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef DBG_SERVER_H
|
||||
#define DBG_SERVER_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Packet Headers
|
||||
|
||||
#define DS_PACKET_MAGIC 0x7273
|
||||
#define DS_PACKET_VERSION 0x0
|
||||
|
||||
typedef U8 DS_PacketKind;
|
||||
enum
|
||||
{
|
||||
DS_PacketKind_Msg,
|
||||
DS_PacketKind_Response,
|
||||
DS_PacketKind_Event,
|
||||
};
|
||||
|
||||
typedef struct DS_PacketHeader DS_PacketHeader;
|
||||
struct DS_PacketHeader
|
||||
{
|
||||
U16 magic;
|
||||
DS_PacketKind kind;
|
||||
U8 version;
|
||||
U32 payload_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Messages (Client -> Server)
|
||||
|
||||
typedef enum DS_MsgKind
|
||||
{
|
||||
DS_MsgKind_Null,
|
||||
|
||||
//- rjf: connection handshake
|
||||
DS_MsgKind_Handshake,
|
||||
|
||||
//- rjf: debuggee attaching/detaching ops
|
||||
DS_MsgKind_Launch,
|
||||
DS_MsgKind_Attach,
|
||||
DS_MsgKind_Kill,
|
||||
DS_MsgKind_Detach,
|
||||
|
||||
//- rjf: running ops
|
||||
DS_MsgKind_Run,
|
||||
DS_MsgKind_SingleStep,
|
||||
|
||||
//- rjf: halting
|
||||
DS_MsgKind_Halt,
|
||||
|
||||
//- rjf: memory ops
|
||||
DS_MsgKind_MemoryReserve,
|
||||
DS_MsgKind_MemoryCommit,
|
||||
DS_MsgKind_MemoryDecommit,
|
||||
DS_MsgKind_MemoryRelease,
|
||||
DS_MsgKind_MemoryProtect,
|
||||
DS_MsgKind_MemoryRead,
|
||||
DS_MsgKind_MemoryWrite,
|
||||
|
||||
//- rjf: thread ops
|
||||
DS_MsgKind_ThreadRegBlockRead,
|
||||
DS_MsgKind_ThreadRegBlockWrite,
|
||||
DS_MsgKind_ThreadGetModuleTLSVAddr,
|
||||
|
||||
//- rjf: system ops
|
||||
DS_MsgKind_ListSystemProcesses,
|
||||
}
|
||||
DS_MsgKind;
|
||||
|
||||
typedef U32 DS_MsgFlags;
|
||||
enum
|
||||
{
|
||||
DS_MsgFlag_IgnorePreviousException = (1<<0),
|
||||
DS_MsgFlag_RunEntitiesAreUnfrozen = (1<<1),
|
||||
DS_MsgFlag_RunEntitiesAreProcesses = (1<<2),
|
||||
};
|
||||
|
||||
typedef struct DS_LaunchParams DS_LaunchParams;
|
||||
struct DS_LaunchParams
|
||||
{
|
||||
String8List command_line;
|
||||
String8 path;
|
||||
String8List env;
|
||||
String8 stdout_path;
|
||||
String8 stdin_path;
|
||||
String8 stderr_path;
|
||||
B32 debug_subprocesses;
|
||||
B32 inherit_env;
|
||||
};
|
||||
|
||||
typedef struct DS_Msg DS_Msg;
|
||||
struct DS_Msg
|
||||
{
|
||||
DS_MsgKind kind;
|
||||
DS_MsgFlags flags;
|
||||
U64 msg_id;
|
||||
|
||||
//- rjf: general parameters
|
||||
Rng1U64 vaddr_range;
|
||||
AccessFlags access_flags;
|
||||
DMN_Handle entity;
|
||||
U64 pid;
|
||||
U64 code;
|
||||
|
||||
//- rjf: process launching parameter extension
|
||||
DS_LaunchParams *launch_params;
|
||||
|
||||
//- rjf: running parameters
|
||||
DMN_TrapChunkList traps;
|
||||
DMN_HandleArray run_entities;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Responses (Server -> Client responses to messages)
|
||||
|
||||
typedef struct DS_Response DS_Response;
|
||||
struct DS_Response
|
||||
{
|
||||
U64 msg_id;
|
||||
DMN_Handle entity;
|
||||
U64 pid;
|
||||
B32 good;
|
||||
String8 data;
|
||||
};
|
||||
|
||||
typedef struct DS_ResponseNode DS_ResponseNode;
|
||||
struct DS_ResponseNode
|
||||
{
|
||||
DS_ResponseNode *next;
|
||||
DS_Response v;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message/Response Parsing
|
||||
|
||||
internal DS_Msg ds_msg_from_packet(Arena *arena, String8 data);
|
||||
internal String8 ds_packet_from_msg(Arena *arena, DS_Msg *msg);
|
||||
internal DS_Response ds_response_from_packet(Arena *arena, String8 data);
|
||||
internal String8 ds_packet_from_response(Arena *arena, DS_Response *response);
|
||||
internal DMN_EventList ds_dmn_events_from_packet(Arena *arena, String8 data);
|
||||
internal String8 ds_packet_from_dmn_events(Arena *arena, DMN_EventList evts);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Local Server Functions
|
||||
|
||||
internal U64 ds_ctrl_launch(DMN_CtrlCtx *ctrl_ctx, DS_LaunchParams *params);
|
||||
internal B32 ds_ctrl_attach(DMN_CtrlCtx *ctrl_ctx, U32 pid);
|
||||
internal B32 ds_ctrl_kill(DMN_CtrlCtx *ctrl_ctx, DMN_Handle process, U32 exit_code);
|
||||
internal B32 ds_ctrl_detach(DMN_CtrlCtx *ctrl_ctx, DMN_Handle process);
|
||||
internal DMN_EventList ds_ctrl_run(Arena *arena, DMN_CtrlCtx *ctrl_ctx, DMN_RunCtrls *ctrls);
|
||||
|
||||
#endif // DBG_SERVER_H
|
||||
@@ -122,3 +122,17 @@ dmn_event_list_push(Arena *arena, DMN_EventList *list)
|
||||
result->module_info = &dmn_module_info_nil;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
dmn_event_deep_copy(Arena *arena, DMN_Event *dst, DMN_Event *src)
|
||||
{
|
||||
MemoryCopyStruct(dst, src);
|
||||
dst->string = str8_copy(arena, dst->string);
|
||||
if(dst->module_info != 0)
|
||||
{
|
||||
dst->module_info = push_array(arena, DMN_ModuleInfo, 1);
|
||||
MemoryCopyStruct(dst->module_info, src->module_info);
|
||||
dst->module_info->module_path = str8_copy(arena, dst->module_info->module_path);
|
||||
dst->module_info->debug_info_path = str8_copy(arena, dst->module_info->debug_info_path);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef DEMON_CORE_H
|
||||
#define DEMON_CORE_H
|
||||
#ifndef DEMON_H
|
||||
#define DEMON_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Control-Thread-Only Context
|
||||
@@ -18,17 +18,6 @@ struct DMN_CtrlCtx
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Dynamic Linker Types
|
||||
|
||||
typedef U32 DMN_TlsModel;
|
||||
enum
|
||||
{
|
||||
DMN_TlsModel_Null,
|
||||
DMN_TlsModel_WinodwsNt,
|
||||
DMN_TlsModel_Gnu
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Types
|
||||
|
||||
@@ -129,9 +118,6 @@ struct DMN_Event
|
||||
U64 user_data;
|
||||
B32 exception_repeated;
|
||||
|
||||
// rjf: process info
|
||||
DMN_TlsModel tls_model;
|
||||
|
||||
// rjf: module info
|
||||
DMN_ModuleInfo *module_info;
|
||||
|
||||
@@ -246,11 +232,7 @@ internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *sr
|
||||
|
||||
//- rjf: event list building
|
||||
internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once)
|
||||
|
||||
internal String8 dmn_data_from_process_vaddr_range(Arena *arena, DMN_Handle process, Rng1U64 vrange);
|
||||
internal void dmn_event_deep_copy(Arena *arena, DMN_Event *dst, DMN_Event *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS)
|
||||
@@ -302,4 +284,4 @@ internal void dmn_process_iter_begin(DMN_ProcessIter *iter);
|
||||
internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out);
|
||||
internal void dmn_process_iter_end(DMN_ProcessIter *iter);
|
||||
|
||||
#endif // DEMON_CORE_H
|
||||
#endif // DEMON_H
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Event Kind Tables
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "demon/demon_core.c"
|
||||
#include "demon/demon.c"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "win32/demon/win32_demon.c"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#ifndef DEMON_INC_H
|
||||
#define DEMON_INC_H
|
||||
|
||||
#include "demon/demon_core.h"
|
||||
#include "demon/demon.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "win32/demon/win32_demon.h"
|
||||
|
||||
@@ -437,13 +437,10 @@ dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_ge
|
||||
U64 buffer[] =
|
||||
{
|
||||
mesh_vertices.u64[0],
|
||||
mesh_vertices.u64[1],
|
||||
mesh_indices.u64[0],
|
||||
mesh_indices.u64[1],
|
||||
(U64)mesh_geo_topology,
|
||||
(U64)mesh_geo_vertex_flags,
|
||||
albedo_tex.u64[0],
|
||||
albedo_tex.u64[1],
|
||||
(U64)dr_top_tex2d_sample_kind(),
|
||||
};
|
||||
hash = dr_hash_from_string(str8((U8 *)buffer, sizeof(buffer)));
|
||||
|
||||
+50
-15
@@ -676,6 +676,7 @@ internal void
|
||||
dw2_parse_ctx_equip_unit_root_tag(DW2_ParseCtx *ctx_out, DW2_Tag *tag, DW2_OffsetTableSet *offset_tables)
|
||||
{
|
||||
// rjf: unpack attributes
|
||||
DW2_Attrib *name_attrib = &dw2_attrib_nil;
|
||||
DW2_Attrib *low_pc_attrib = &dw2_attrib_nil;
|
||||
DW2_Attrib *lang_attrib = &dw2_attrib_nil;
|
||||
DW2_Attrib *rnglists_base_off_attrib = &dw2_attrib_nil;
|
||||
@@ -689,6 +690,7 @@ dw2_parse_ctx_equip_unit_root_tag(DW2_ParseCtx *ctx_out, DW2_Tag *tag, DW2_Offse
|
||||
{
|
||||
default:{}break;
|
||||
#define Case(name, name_upper) case DW_AttribKind_##name_upper:{name##_attrib = &n->v;}break
|
||||
Case(name, Name);
|
||||
Case(low_pc, LowPc);
|
||||
Case(lang, Language);
|
||||
Case(rnglists_base_off, RngListsBase);
|
||||
@@ -704,6 +706,7 @@ dw2_parse_ctx_equip_unit_root_tag(DW2_ParseCtx *ctx_out, DW2_Tag *tag, DW2_Offse
|
||||
ctx_out->unit_base_addr = low_pc_attrib->val.addr;
|
||||
ctx_out->language = lang_attrib->val.u128.u64[0];
|
||||
ctx_out->unit_dir = comp_dir_attrib->val.string;
|
||||
ctx_out->unit_file = name_attrib->val.string;
|
||||
|
||||
// rjf: find offset tables
|
||||
Rng1U64Array rnglists_tables_ranges_array = {offset_tables->rnglists_tables_ranges, offset_tables->rnglists_tables_count};
|
||||
@@ -957,7 +960,10 @@ dw2_read_line_table_header(Arena *arena, DW_Raw *raw, DW2_ParseCtx *ctx, String8
|
||||
off += dw2_read_fmt_u64(data, off, format, &header_length);
|
||||
opl_header_length_off = off;
|
||||
off += str8_deserial_read_struct(data, off, &min_inst_length);
|
||||
if(version >= DW_Version_4)
|
||||
{
|
||||
off += str8_deserial_read_struct(data, off, &max_ops_per_inst);
|
||||
}
|
||||
off += str8_deserial_read_struct(data, off, &default_is_stmt);
|
||||
off += str8_deserial_read_struct(data, off, &line_base);
|
||||
off += str8_deserial_read_struct(data, off, &line_range);
|
||||
@@ -1199,7 +1205,7 @@ dw2_read_line_table_header(Arena *arena, DW_Raw *raw, DW2_ParseCtx *ctx, String8
|
||||
//~ rjf: String Offset Table Parsing (.debug_str_offsets)
|
||||
|
||||
internal U64
|
||||
dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out)
|
||||
dw2_read_offset_table(String8 data, U64 off, B32 offset_count_entry, DW2_OffsetTable *out)
|
||||
{
|
||||
U64 start_off = off;
|
||||
{
|
||||
@@ -1222,11 +1228,34 @@ dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out)
|
||||
off += str8_deserial_read_struct(data, off, &addr_size);
|
||||
off += str8_deserial_read_struct(data, off, &segment_selector_size);
|
||||
|
||||
// rjf: determine entry size
|
||||
U64 entry_size = dw_addr_size_from_format(format);
|
||||
if(addr_size != 0)
|
||||
// rjf: 0 addr size / segment selector size -> this is an offset table (e.g. stroffs).
|
||||
// this means the table immediately follows the header, and the entry size is based
|
||||
// on the format.
|
||||
U64 entry_size = 0;
|
||||
U64 entry_count = 0;
|
||||
if(addr_size == 0 && segment_selector_size == 0)
|
||||
{
|
||||
entry_size = dw_addr_size_from_format(format);
|
||||
entry_count = (unit_data_off_opl - off) / entry_size;
|
||||
}
|
||||
|
||||
// rjf: nonzero addr size / segment selector size -> if we have an explicitly
|
||||
// stored offset count entry, we need to parse it
|
||||
else if(offset_count_entry)
|
||||
{
|
||||
entry_size = dw_addr_size_from_format(format);
|
||||
off += str8_deserial_read(data, off, &entry_count, 4, 4);
|
||||
U64 entry_count_cap = (unit_data_off_opl - off) / entry_size;
|
||||
entry_count = Min(entry_count, entry_count_cap);
|
||||
}
|
||||
|
||||
// rjf: nonzero addr size / segment selector size -> no stored offset count,
|
||||
// then we infer the entry count from the data remaining, as we are just
|
||||
// storing address pairs.
|
||||
else
|
||||
{
|
||||
entry_size = addr_size + segment_selector_size;
|
||||
entry_count = (unit_data_off_opl - off) / entry_size;
|
||||
}
|
||||
|
||||
// rjf: fill table info
|
||||
@@ -1235,7 +1264,8 @@ dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out)
|
||||
out->addr_size = addr_size;
|
||||
out->segment_selector_size = segment_selector_size;
|
||||
out->entry_size = entry_size;
|
||||
out->entries_count = (unit_data_off_opl - off) / out->entry_size;
|
||||
out->entries_count = entry_count;
|
||||
out->entries_are_addrs = (!offset_count_entry && addr_size != 0);
|
||||
out->entries = data.str + off;
|
||||
|
||||
// rjf: skip table
|
||||
@@ -1247,14 +1277,14 @@ dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out)
|
||||
}
|
||||
|
||||
internal DW2_OffsetTableList
|
||||
dw2_offset_table_list_from_data(Arena *arena, String8 data)
|
||||
dw2_offset_table_list_from_data(Arena *arena, String8 data, B32 offset_count_entry)
|
||||
{
|
||||
DW2_OffsetTableList list = {0};
|
||||
for(U64 off = 0; off < data.size;)
|
||||
{
|
||||
U64 start_off = off;
|
||||
DW2_OffsetTable table = {0};
|
||||
off += dw2_read_offset_table(data, off, &table);
|
||||
off += dw2_read_offset_table(data, off, offset_count_entry, &table);
|
||||
if(table.entries != 0)
|
||||
{
|
||||
DW2_OffsetTableNode *n = push_array(arena, DW2_OffsetTableNode, 1);
|
||||
@@ -1279,7 +1309,7 @@ dw2_try_offset_from_table_idx(DW2_OffsetTable *tbl, U64 idx, U64 *out)
|
||||
{
|
||||
U64 entry_size = tbl->entry_size;
|
||||
U64 entry_off = idx * entry_size;
|
||||
if(tbl->addr_size != 0)
|
||||
if(tbl->entries_are_addrs)
|
||||
{
|
||||
U64 segment_off = entry_off;
|
||||
U64 addr_off = entry_off + tbl->segment_selector_size;
|
||||
@@ -1307,22 +1337,24 @@ dw2_offset_table_set_from_raw(Arena *arena, DW_Raw *raw)
|
||||
struct
|
||||
{
|
||||
String8 data;
|
||||
B32 offset_count_entry;
|
||||
U64 *tables_count_out;
|
||||
DW2_OffsetTable **tables_out;
|
||||
Rng1U64 **tables_ranges_out;
|
||||
}
|
||||
tasks[] =
|
||||
{
|
||||
{raw->sec[DW_SectionKind_StrOffsets].data, &result.str_offsets_tables_count, &result.str_offsets_tables, &result.str_offsets_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_RngLists].data, &result.rnglists_tables_count, &result.rnglists_tables, &result.rnglists_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_Addr].data, &result.addr_tables_count, &result.addr_tables, &result.addr_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_LocLists].data, &result.loclists_tables_count, &result.loclists_tables, &result.loclists_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_StrOffsets].data, 0, &result.str_offsets_tables_count, &result.str_offsets_tables, &result.str_offsets_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_RngLists].data, 1, &result.rnglists_tables_count, &result.rnglists_tables, &result.rnglists_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_Addr].data, 0, &result.addr_tables_count, &result.addr_tables, &result.addr_tables_ranges},
|
||||
{raw->sec[DW_SectionKind_LocLists].data, 1, &result.loclists_tables_count, &result.loclists_tables, &result.loclists_tables_ranges},
|
||||
};
|
||||
for EachElement(task_idx, tasks)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 data = tasks[task_idx].data;
|
||||
DW2_OffsetTableList tables = dw2_offset_table_list_from_data(scratch.arena, data);
|
||||
B32 offset_count_entry = tasks[task_idx].offset_count_entry;
|
||||
DW2_OffsetTableList tables = dw2_offset_table_list_from_data(scratch.arena, data, offset_count_entry);
|
||||
tasks[task_idx].tables_count_out[0] = tables.count;
|
||||
tasks[task_idx].tables_out[0] = push_array(arena, DW2_OffsetTable, tables.count);
|
||||
tasks[task_idx].tables_ranges_out[0] = push_array(arena, Rng1U64, tables.count);
|
||||
@@ -1418,7 +1450,10 @@ dw2_rnglist_from_form_val(Arena *arena, DW2_ParseCtx *ctx, DW_Raw *raw, DW2_Form
|
||||
if(ctx->rnglists_table != 0)
|
||||
{
|
||||
U64 rnglist_off_idx = form_val.u128.u64[0];
|
||||
dw2_try_offset_from_table_idx(ctx->rnglists_table, rnglist_off_idx, &rnglist_off);
|
||||
U64 rnglist_off_from_off_array = 0;
|
||||
dw2_try_offset_from_table_idx(ctx->rnglists_table, rnglist_off_idx, &rnglist_off_from_off_array);
|
||||
U64 rnglist_off_array_base_off = (U64)((U8 *)ctx->rnglists_table->entries - data.str);
|
||||
rnglist_off = rnglist_off_array_base_off + rnglist_off_from_off_array;
|
||||
}break;
|
||||
}
|
||||
|
||||
@@ -1621,7 +1656,7 @@ dw2_loclist_from_form_val(Arena *arena, DW2_ParseCtx *ctx, DW_Raw *raw, DW2_Form
|
||||
loclist_off = form_val.u128.u64[0];
|
||||
}break;
|
||||
case DW_FormKind_LocListx:
|
||||
if(ctx->rnglists_table != 0)
|
||||
if(ctx->loclists_table != 0)
|
||||
{
|
||||
U64 loclist_off_idx = form_val.u128.u64[0];
|
||||
dw2_try_offset_from_table_idx(ctx->loclists_table, loclist_off_idx, &loclist_off);
|
||||
|
||||
@@ -104,6 +104,7 @@ struct DW2_OffsetTable
|
||||
U8 segment_selector_size;
|
||||
U64 entry_size;
|
||||
U64 entries_count;
|
||||
B32 entries_are_addrs;
|
||||
void *entries;
|
||||
};
|
||||
|
||||
@@ -430,8 +431,8 @@ internal U64 dw2_read_line_table_header(Arena *arena, DW_Raw *raw, DW2_ParseCtx
|
||||
////////////////////////////////
|
||||
//~ rjf: Offset Table Parsing (.debug_str_offsets, .debug_rnglists)
|
||||
|
||||
internal U64 dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out);
|
||||
internal DW2_OffsetTableList dw2_offset_table_list_from_data(Arena *arena, String8 data);
|
||||
internal U64 dw2_read_offset_table(String8 data, U64 off, B32 offset_count_entry, DW2_OffsetTable *out);
|
||||
internal DW2_OffsetTableList dw2_offset_table_list_from_data(Arena *arena, String8 data, B32 offset_count_entry);
|
||||
internal B32 dw2_try_offset_from_table_idx(DW2_OffsetTable *tbl, U64 idx, U64 *out);
|
||||
internal DW2_OffsetTableSet dw2_offset_table_set_from_raw(Arena *arena, DW_Raw *raw);
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@ dw_raw_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin)
|
||||
// rjf: read compressed-section header
|
||||
ELF_Chdr64 chdr64 = {0};
|
||||
U64 chdr_size = 0;
|
||||
if(ELF_HdrIs64Bit(bin->hdr.e_ident))
|
||||
if(bin->hdr.e_ident[ELF_Identifier_Class] == ELF_Class_64)
|
||||
{
|
||||
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr64);
|
||||
}
|
||||
else if(ELF_HdrIs32Bit(bin->hdr.e_ident))
|
||||
else if(bin->hdr.e_ident[ELF_Identifier_Class] == ELF_Class_32)
|
||||
{
|
||||
ELF_Chdr32 chdr32 = {0};
|
||||
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32);
|
||||
|
||||
@@ -199,7 +199,7 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
|
||||
String8 raw_coff = coff_from_obj(scratch.arena, obj);
|
||||
|
||||
t_write_file(str8_lit("dwarf.obj"), raw_coff);
|
||||
t_invoke(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
|
||||
t_invoke(t_linker_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
|
||||
delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
|
||||
|
||||
String8 exe = t_read_file(arena, str8_lit("a.exe"));
|
||||
|
||||
@@ -133,6 +133,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
||||
// rjf: determine CIE's full address range
|
||||
Rng1U64 cie_vaddr_range = {0};
|
||||
DW_Format cie_fmt = DW_Format_Null;
|
||||
if(!done)
|
||||
{
|
||||
// rjf: read initial length data
|
||||
String8 initial_length_data = {0};
|
||||
@@ -686,6 +687,10 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
|
||||
//- rjf: commit new register values, if we succeeded
|
||||
if(!done)
|
||||
{
|
||||
if(cfa_out)
|
||||
{
|
||||
cfa_out[0] = cfa;
|
||||
}
|
||||
result.status = UWND_StepStatus_Good;
|
||||
}
|
||||
}
|
||||
|
||||
+186
-104
@@ -122,46 +122,65 @@ elf_auxv64_from_auxv32(ELF_Auxv32 auxv32)
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
elf_string_from_class(Arena *arena, ELF_Class v)
|
||||
{
|
||||
switch (v) {
|
||||
case ELF_Class_None: return str8_lit("None");
|
||||
case ELF_Class_32: return str8_lit("32Bit");
|
||||
case ELF_Class_64: return str8_lit("64Bit");
|
||||
}
|
||||
return push_str8f(arena, "%#x", v);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ELF -> Codebase enum Conversions
|
||||
|
||||
internal Arch
|
||||
arch_from_elf_machine(ELF_MachineKind e_machine)
|
||||
{
|
||||
Arch arch = Arch_Null;
|
||||
switch (e_machine) {
|
||||
case ELF_MachineKind_None: arch = Arch_Null; break;
|
||||
case ELF_MachineKind_AARCH64: arch = Arch_arm32; break;
|
||||
case ELF_MachineKind_ARM: arch = Arch_arm32; break;
|
||||
case ELF_MachineKind_386: arch = Arch_x86; break;
|
||||
case ELF_MachineKind_X86_64: arch = Arch_x64; break;
|
||||
default: NotImplemented; break;
|
||||
switch((ELF_MachineKindEnum)e_machine)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_MachineKind_None: {arch = Arch_Null;}break;
|
||||
case ELF_MachineKind_AARCH64: {arch = Arch_arm32;}break;
|
||||
case ELF_MachineKind_ARM: {arch = Arch_arm32;}break;
|
||||
case ELF_MachineKind_386: {arch = Arch_x86;}break;
|
||||
case ELF_MachineKind_X86_64: {arch = Arch_x64;}break;
|
||||
}
|
||||
return arch;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ELF Class -> Structure Size
|
||||
|
||||
internal U64
|
||||
elf_hdr_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Hdr32);} break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Hdr64);} break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
elf_phdr_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: break;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Phdr32);} break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Phdr64);} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
elf_shdr_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Shdr32);} break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Shdr64);} break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -170,124 +189,187 @@ internal U64
|
||||
elf_dyn_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: break;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Dyn32);}break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Dyn64);}break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
elf_sym_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Sym32);}break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Sym64);}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
elf_auxv_size_from_class(ELF_Class elf_class)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch((ELF_ClassEnum)elf_class)
|
||||
{
|
||||
case ELF_Class_COUNT:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:{result = sizeof(ELF_Auxv32);}break;
|
||||
case ELF_Class_64:{result = sizeof(ELF_Auxv64);}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Optional Class Conversion Readers
|
||||
|
||||
internal MachineOpResult
|
||||
elf_read_ehdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Hdr64 *ehdr_out)
|
||||
internal ELF_Hdr64
|
||||
elf_hdr64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
U8 e_ident[ELF_Identifier_Max] = {0};
|
||||
MachineOpResult result = mem_read(addr, &e_ident, sizeof(e_ident), mem_read_ud);
|
||||
if (result == MachineOpResult_Ok) {
|
||||
if (str8_match(str8_prefix(str8_array_fixed(e_ident), elf_magic_string.size), elf_magic_string, 0)) {
|
||||
switch (e_ident[ELF_Identifier_Class]) {
|
||||
default: { InvalidPath; }break;
|
||||
case ELF_Class_None: { }break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Hdr32 ehdr32 = {0};
|
||||
result = mem_read(addr, &ehdr32, sizeof(ehdr32), mem_read_ud);
|
||||
if (result == MachineOpResult_Ok) {
|
||||
*ehdr_out = elf_hdr64_from_hdr32(ehdr32);
|
||||
}
|
||||
ELF_Hdr64 result = {0};
|
||||
U64 needed_size = elf_hdr_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Hdr32 result32 = *(ELF_Hdr32 *)data.str;
|
||||
result = elf_hdr64_from_hdr32(result32);
|
||||
}break;
|
||||
case ELF_Class_64: {
|
||||
result = mem_read(addr, ehdr_out, sizeof(*ehdr_out), mem_read_ud);
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Hdr64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal MachineOpResult
|
||||
elf_read_phdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out)
|
||||
internal ELF_Phdr64
|
||||
elf_phdr64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
MachineOpResult result = MachineOpResult_Fail;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Phdr32 phdr32 = {0};
|
||||
result = mem_read(addr, &phdr32, sizeof(phdr32), mem_read_ud);
|
||||
if (result == MachineOpResult_Ok) {
|
||||
*phdr_out = elf_phdr64_from_phdr32(phdr32);
|
||||
ELF_Phdr64 result = {0};
|
||||
U64 needed_size = elf_phdr_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Phdr32 result32 = *(ELF_Phdr32 *)data.str;
|
||||
result = elf_phdr64_from_phdr32(result32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Phdr64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
} break;
|
||||
case ELF_Class_64: {
|
||||
result = mem_read(addr, phdr_out, sizeof(*phdr_out), mem_read_ud);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal MachineOpResult
|
||||
elf_read_shdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out)
|
||||
internal ELF_Shdr64
|
||||
elf_shdr64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
MachineOpResult result = MachineOpResult_Fail;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Shdr32 shdr32 = {0};
|
||||
result = mem_read(addr, &shdr32, sizeof(shdr32), mem_read_ud);
|
||||
if (result == MachineOpResult_Ok) {
|
||||
*shdr_out = elf_shdr64_from_shdr32(shdr32);
|
||||
ELF_Shdr64 result = {0};
|
||||
U64 needed_size = elf_shdr_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Shdr32 result32 = *(ELF_Shdr32 *)data.str;
|
||||
result = elf_shdr64_from_shdr32(result32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Shdr64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
} break;
|
||||
case ELF_Class_64: {
|
||||
result = mem_read(addr, shdr_out, sizeof(*shdr_out), mem_read_ud);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal MachineOpResult
|
||||
elf_read_dyn(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out)
|
||||
internal ELF_Dyn64
|
||||
elf_dyn64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
MachineOpResult result = MachineOpResult_Fail;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: {} break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Dyn32 dyn32 = {0};
|
||||
result = mem_read(addr, &dyn32, sizeof(dyn32), mem_read_ud);
|
||||
if (result == MachineOpResult_Fail) {
|
||||
*dyn_out = elf_dyn64_from_dyn32(dyn32);
|
||||
ELF_Dyn64 result = {0};
|
||||
U64 needed_size = elf_dyn_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Dyn32 result32 = *(ELF_Dyn32 *)data.str;
|
||||
result = elf_dyn64_from_dyn32(result32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Dyn64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
} break;
|
||||
case ELF_Class_64: {
|
||||
result = mem_read(addr, dyn_out, sizeof(*dyn_out), mem_read_ud);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal MachineOpResult
|
||||
elf_read_symbol(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out)
|
||||
internal ELF_Sym64
|
||||
elf_sym64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
MachineOpResult result = MachineOpResult_Fail;
|
||||
switch (elf_class) {
|
||||
case ELF_Class_None: {} break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Sym32 symbol32 = {0};
|
||||
result = mem_read(addr, &symbol32, sizeof(symbol32), mem_read_ud);
|
||||
if (result == MachineOpResult_Ok) {
|
||||
*symbol_out = elf_sym64_from_sym32(symbol32);
|
||||
ELF_Sym64 result = {0};
|
||||
U64 needed_size = elf_sym_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Sym32 result32 = *(ELF_Sym32 *)data.str;
|
||||
result = elf_sym64_from_sym32(result32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Sym64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
}break;
|
||||
case ELF_Class_64: {
|
||||
result = mem_read(addr, symbol_out, sizeof(*symbol_out), mem_read_ud);
|
||||
}break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal ELF_Auxv64
|
||||
elf_auxv64_from_class_data(ELF_Class elf_class, String8 data)
|
||||
{
|
||||
ELF_Auxv64 result = {0};
|
||||
U64 needed_size = elf_auxv_size_from_class(elf_class);
|
||||
if(data.size >= needed_size)
|
||||
{
|
||||
switch(elf_class)
|
||||
{
|
||||
default:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Auxv32 result32 = *(ELF_Auxv32 *)data.str;
|
||||
result = elf_auxv64_from_auxv32(result32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
result = *(ELF_Auxv64 *)data.str;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+133
-91
@@ -4,17 +4,21 @@
|
||||
#ifndef ELF_H
|
||||
#define ELF_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Primary ELF File enums/structures
|
||||
|
||||
typedef U8 ELF_Class;
|
||||
enum
|
||||
typedef enum ELF_ClassEnum
|
||||
{
|
||||
ELF_Class_None = 0,
|
||||
ELF_Class_32 = 1,
|
||||
ELF_Class_64 = 2,
|
||||
ELF_Class_Count = 3
|
||||
};
|
||||
ELF_Class_COUNT = 3
|
||||
}
|
||||
ELF_ClassEnum;
|
||||
|
||||
typedef U8 ELF_OsAbi;
|
||||
enum
|
||||
typedef enum ELF_OsAbiEnum
|
||||
{
|
||||
ELF_OsAbi_None,
|
||||
ELF_OsAbi_SYSV,
|
||||
@@ -28,17 +32,19 @@ enum
|
||||
ELF_OsAbi_TRU64,
|
||||
ELF_OsAbi_ARM = 97,
|
||||
ELF_OsAbi_STANDALONE = 255,
|
||||
};
|
||||
}
|
||||
ELF_OsAbiEnum;
|
||||
|
||||
typedef U8 ELF_Version;
|
||||
enum
|
||||
typedef enum ELF_VersionEnum
|
||||
{
|
||||
ELF_Version_None,
|
||||
ELF_Version_Current,
|
||||
};
|
||||
}
|
||||
ELF_VersionEnum;
|
||||
|
||||
typedef U16 ELF_MachineKind;
|
||||
enum
|
||||
typedef enum ELF_MachineKindEnum
|
||||
{
|
||||
ELF_MachineKind_None = 0,
|
||||
ELF_MachineKind_M32 = 1,
|
||||
@@ -96,18 +102,20 @@ enum
|
||||
ELF_MachineKind_K1OM = 181,
|
||||
ELF_MachineKind_RISCV = 243,
|
||||
ELF_MachineKind_S390_OLD = 0xA390,
|
||||
};
|
||||
}
|
||||
ELF_MachineKindEnum;
|
||||
|
||||
typedef U8 ELF_Data;
|
||||
enum
|
||||
typedef enum ELF_DataEnum
|
||||
{
|
||||
ELF_Data_None = 0,
|
||||
ELF_Data_2LSB = 1,
|
||||
ELF_Data_2MSB = 2,
|
||||
};
|
||||
}
|
||||
ELF_DataEnum;
|
||||
|
||||
typedef U16 ELF_Type;
|
||||
enum
|
||||
typedef enum ELF_TypeEnum
|
||||
{
|
||||
ELF_Type_None = 0,
|
||||
ELF_Type_Rel = 1,
|
||||
@@ -118,10 +126,11 @@ enum
|
||||
ELF_Type_HiOs = 0xff00,
|
||||
ELF_Type_LoProc = 0xff00,
|
||||
ELF_Type_HiProc = 0xffff
|
||||
};
|
||||
}
|
||||
ELF_TypeEnum;
|
||||
|
||||
typedef U32 ELF_PType;
|
||||
enum
|
||||
typedef enum ELF_PTypeEnum
|
||||
{
|
||||
ELF_PType_Null = 0,
|
||||
ELF_PType_Load = 1,
|
||||
@@ -141,18 +150,20 @@ enum
|
||||
ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e551, // frame unwind information
|
||||
ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e552, // stack flags
|
||||
ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e553, // read-only after relocations
|
||||
};
|
||||
}
|
||||
ELF_PTypeEnum;
|
||||
|
||||
typedef U32 ELF_PFlag;
|
||||
enum
|
||||
typedef enum ELF_PFlagEnum
|
||||
{
|
||||
ELF_PFlag_Exec = (1 << 0),
|
||||
ELF_PFlag_Write = (1 << 1),
|
||||
ELF_PFlag_Read = (1 << 2),
|
||||
};
|
||||
}
|
||||
ELF_PFlagEnum;
|
||||
|
||||
typedef U32 ELF_ShType;
|
||||
enum
|
||||
typedef enum ELF_ShTypeEnum
|
||||
{
|
||||
ELF_ShType_Null = 0,
|
||||
ELF_ShType_ProgBits = 1,
|
||||
@@ -187,10 +198,11 @@ enum
|
||||
ELF_ShType_GNU_versym = ELF_ShType_SUNW_versym,
|
||||
ELF_ShType_Proc,
|
||||
ELF_ShType_User,
|
||||
};
|
||||
}
|
||||
ELF_ShTypeEnum;
|
||||
|
||||
typedef U32 ELF_SectionIndex;
|
||||
enum
|
||||
typedef enum ELF_SectionIndexEnum
|
||||
{
|
||||
|
||||
ELF_SectionIndex_Undef = 0, // Symbol with section index is undefined and must be resolved by the link editor
|
||||
@@ -214,7 +226,8 @@ enum
|
||||
|
||||
ELF_SectionIndex_TIC6X_Common = ELF_SectionIndex_LoReserve,
|
||||
ELF_SectionIndex_MIPS_SUndefined = 0xff04,
|
||||
};
|
||||
}
|
||||
ELF_SectionIndexEnum;
|
||||
|
||||
typedef U32 ELF_SectionFlags;
|
||||
enum
|
||||
@@ -240,7 +253,7 @@ enum
|
||||
#define ELF_SectionFlag_Extract_MaskOs(f) (U8)(((f) >> ELF_SectionFlag_MaskOs_Shift) & ELF_SectionFlag_MaskOs_Mask)
|
||||
#define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask)
|
||||
typedef U32 ELF_AuxType;
|
||||
enum
|
||||
typedef enum ELF_AuxTypeEnum
|
||||
{
|
||||
ELF_AuxType_Null = 0,
|
||||
ELF_AuxType_Phdr = 3, // program headers
|
||||
@@ -276,10 +289,11 @@ enum
|
||||
ELF_AuxType_L2_CacheGeometry = 45,
|
||||
ELF_AuxType_L3_CacheSize = 46,
|
||||
ELF_AuxType_L3_CacheGeometry = 47,
|
||||
};
|
||||
}
|
||||
ELF_AuxTypeEnum;
|
||||
|
||||
typedef U32 ELF_DynTag;
|
||||
enum
|
||||
typedef enum ELF_DynTagEnum
|
||||
{
|
||||
ELF_DynTag_Null = 0,
|
||||
|
||||
@@ -358,7 +372,8 @@ enum
|
||||
ELF_DynTag_VerSym = 0x6ffffff0,
|
||||
ELF_DynTag_LoProc = 0x70000000,
|
||||
ELF_DynTag_HiProc = 0x7fffffff,
|
||||
};
|
||||
}
|
||||
ELF_DynTagEnum;
|
||||
|
||||
typedef U32 ELF_DynFlag;
|
||||
enum
|
||||
@@ -532,9 +547,6 @@ enum
|
||||
ELF_NoteType_STapSdt = 3, // System Tap probes
|
||||
};
|
||||
|
||||
#define ELF_HdrIs64Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_64)
|
||||
#define ELF_HdrIs32Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_32)
|
||||
|
||||
typedef enum ELF_Identifier
|
||||
{
|
||||
ELF_Identifier_Mag0 = 0,
|
||||
@@ -547,12 +559,14 @@ typedef enum ELF_Identifier
|
||||
ELF_Identifier_OsAbi = 7,
|
||||
ELF_Identfiier_AbiBersion = 8,
|
||||
ELF_Identifier_Max = 16,
|
||||
} ELF_Identifier;
|
||||
}
|
||||
ELF_Identifier;
|
||||
|
||||
read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'};
|
||||
read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)};
|
||||
|
||||
typedef struct ELF_Hdr64
|
||||
typedef struct ELF_Hdr64 ELF_Hdr64;
|
||||
struct ELF_Hdr64
|
||||
{
|
||||
U8 e_ident[ELF_Identifier_Max];
|
||||
ELF_Type e_type;
|
||||
@@ -568,9 +582,10 @@ typedef struct ELF_Hdr64
|
||||
U16 e_shentsize;
|
||||
U16 e_shnum;
|
||||
U16 e_shstrndx;
|
||||
} ELF_Hdr64;
|
||||
};
|
||||
|
||||
typedef struct ELF_Hdr32
|
||||
typedef struct ELF_Hdr32 ELF_Hdr32;
|
||||
struct ELF_Hdr32
|
||||
{
|
||||
U8 e_ident[ELF_Identifier_Max];
|
||||
ELF_Type e_type;
|
||||
@@ -586,9 +601,10 @@ typedef struct ELF_Hdr32
|
||||
U16 e_shentsize;
|
||||
U16 e_shnum;
|
||||
U16 e_shstrndx;
|
||||
} ELF_Hdr32;
|
||||
};
|
||||
|
||||
typedef struct ELF_Shdr64
|
||||
typedef struct ELF_Shdr64 ELF_Shdr64;
|
||||
struct ELF_Shdr64
|
||||
{
|
||||
U32 sh_name;
|
||||
ELF_ShType sh_type;
|
||||
@@ -600,9 +616,10 @@ typedef struct ELF_Shdr64
|
||||
U32 sh_info;
|
||||
U64 sh_addralign;
|
||||
U64 sh_entsize;
|
||||
} ELF_Shdr64;
|
||||
};
|
||||
|
||||
typedef struct ELF_Shdr32
|
||||
typedef struct ELF_Shdr32 ELF_Shdr32;
|
||||
struct ELF_Shdr32
|
||||
{
|
||||
U32 sh_name;
|
||||
ELF_ShType sh_type;
|
||||
@@ -614,9 +631,10 @@ typedef struct ELF_Shdr32
|
||||
U32 sh_info;
|
||||
U32 sh_addralign;
|
||||
U32 sh_entsize;
|
||||
} ELF_Shdr32;
|
||||
};
|
||||
|
||||
typedef struct ELF_Phdr64
|
||||
typedef struct ELF_Phdr64 ELF_Phdr64;
|
||||
struct ELF_Phdr64
|
||||
{
|
||||
U32 p_type;
|
||||
U32 p_flags;
|
||||
@@ -626,9 +644,10 @@ typedef struct ELF_Phdr64
|
||||
U64 p_filesz;
|
||||
U64 p_memsz;
|
||||
U64 p_align;
|
||||
} ELF_Phdr64;
|
||||
};
|
||||
|
||||
typedef struct ELF_Phdr32
|
||||
typedef struct ELF_Phdr32 ELF_Phdr32;
|
||||
struct ELF_Phdr32
|
||||
{
|
||||
U32 p_type;
|
||||
U32 p_offset;
|
||||
@@ -638,46 +657,53 @@ typedef struct ELF_Phdr32
|
||||
U32 p_memsz;
|
||||
U32 p_flags;
|
||||
U32 p_align;
|
||||
} ELF_Phdr32;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Auxiliary Vectors
|
||||
|
||||
//~ Auxiliary Vectors
|
||||
//
|
||||
// these appear in /proc/<pid>/auxv of a process, they are not in elf files
|
||||
//
|
||||
|
||||
typedef struct ELF_Auxv32
|
||||
typedef struct ELF_Auxv32 ELF_Auxv32;
|
||||
struct ELF_Auxv32
|
||||
{
|
||||
U32 a_type;
|
||||
U32 a_val;
|
||||
} ELF_Auxv32;
|
||||
};
|
||||
|
||||
typedef struct ELF_Auxv64
|
||||
typedef struct ELF_Auxv64 ELF_Auxv64;
|
||||
struct ELF_Auxv64
|
||||
{
|
||||
U64 a_type;
|
||||
U64 a_val;
|
||||
} ELF_Auxv64;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Dynamic Structures
|
||||
|
||||
//~ Dynamic Structures
|
||||
//
|
||||
// these appear in the virtual address space of a process, they are not in elf files
|
||||
//
|
||||
|
||||
typedef struct ELF_Dyn32
|
||||
typedef struct ELF_Dyn32 ELF_Dyn32;
|
||||
struct ELF_Dyn32
|
||||
{
|
||||
U32 tag;
|
||||
U32 val;
|
||||
} ELF_Dyn32;
|
||||
};
|
||||
|
||||
typedef struct ELF_Dyn64
|
||||
typedef struct ELF_Dyn64 ELF_Dyn64;
|
||||
struct ELF_Dyn64
|
||||
{
|
||||
U64 tag;
|
||||
U64 val;
|
||||
} ELF_Dyn64;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Imports and Exports
|
||||
//~ Imports and Exports
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Sym32 ELF_Sym32;
|
||||
struct ELF_Sym32
|
||||
{
|
||||
U32 st_name; // Holds index into files string table.
|
||||
U32 st_value; // Depending on the context, this may be address, size, etc.
|
||||
@@ -685,9 +711,10 @@ typedef struct
|
||||
U8 st_info; // Contains symbols type and binding.
|
||||
U8 st_other; // Reserved for future use, currenly zero.
|
||||
U16 st_shndx; // Section index to which symbol is relevant.
|
||||
} ELF_Sym32;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Sym64 ELF_Sym64;
|
||||
struct ELF_Sym64
|
||||
{
|
||||
U32 st_name;
|
||||
U8 st_info;
|
||||
@@ -695,38 +722,42 @@ typedef struct
|
||||
U16 st_shndx;
|
||||
U64 st_value;
|
||||
U64 st_size;
|
||||
} ELF_Sym64;
|
||||
};
|
||||
|
||||
#define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF))
|
||||
#define ELF_ST_BIND(x) ((x) >> 4)
|
||||
#define ELF_ST_TYPE(x) ((x) & 0xF)
|
||||
#define ELF_ST_VISIBILITY(v) ((v) & 0x3)
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Rel32 ELF_Rel32;
|
||||
struct ELF_Rel32
|
||||
{
|
||||
U32 r_offset;
|
||||
U32 r_info;
|
||||
} ELF_Rel32;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Rela32 ELF_Rela32;
|
||||
struct ELF_Rela32
|
||||
{
|
||||
U32 r_offset;
|
||||
U32 r_info;
|
||||
S32 r_addend;
|
||||
} ELF_Rela32;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Rel64 ELF_Rel64;
|
||||
struct ELF_Rel64
|
||||
{
|
||||
U64 r_offset;
|
||||
U64 r_info;
|
||||
} ELF_Rel64;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct ELF_Rela64 ELF_Rela64;
|
||||
struct ELF_Rela64
|
||||
{
|
||||
U64 r_offset;
|
||||
U64 r_info;
|
||||
S64 r_addend;
|
||||
} ELF_Rela64;
|
||||
};
|
||||
|
||||
#define ELF32_R_SYM(x) ((x) >> 8)
|
||||
#define ELF32_R_TYPE(x) ((x) & 0xFF)
|
||||
@@ -740,7 +771,8 @@ typedef struct
|
||||
#define ELF_EXTERNAL_VERSYM_MASK 0x7FFF
|
||||
|
||||
// Appears in .gnu.verdef (SHT_GNU_verdef)
|
||||
typedef struct
|
||||
typedef struct ELF_ExternalVerdef ELF_ExternalVerdef;
|
||||
struct ELF_ExternalVerdef
|
||||
{
|
||||
U16 vd_version;
|
||||
U16 vd_flags;
|
||||
@@ -749,43 +781,47 @@ typedef struct
|
||||
U32 vd_hash;
|
||||
U32 vd_aux;
|
||||
U32 vd_next;
|
||||
} ELF_ExternalVerdef;
|
||||
};
|
||||
|
||||
// Appears in .gnu.verdef (SHT_GNU_verdef)
|
||||
typedef struct
|
||||
typedef struct ELF_ExternalVerdaux ELF_ExternalVerdaux;
|
||||
struct ELF_ExternalVerdaux
|
||||
{
|
||||
U32 vda_name;
|
||||
U32 vda_next;
|
||||
} ELF_ExternalVerdaux;
|
||||
};
|
||||
|
||||
// Appears in .gnu.verneed (SHT_GNU_verneed)
|
||||
typedef struct
|
||||
typedef struct ELF_ExternalVerneed ELF_ExternalVerneed;
|
||||
struct ELF_ExternalVerneed
|
||||
{
|
||||
U16 vn_version;
|
||||
U16 vn_cnt;
|
||||
U32 vn_file;
|
||||
U32 vn_aux;
|
||||
U32 vn_next;
|
||||
} ELF_ExternalVerneed;
|
||||
};
|
||||
|
||||
// Appears in .gnu.verneed (SHT_GNU_verneed)
|
||||
typedef struct
|
||||
typedef struct ELF_ExternalVernaux ELF_ExternalVernaux;
|
||||
struct ELF_ExternalVernaux
|
||||
{
|
||||
U32 vna_hash;
|
||||
U16 vna_flags;
|
||||
U16 vna_other;
|
||||
U32 vna_name;
|
||||
U32 vna_next;
|
||||
} ELF_ExternalVernaux;
|
||||
};
|
||||
|
||||
// Appears in .gnu.version (SHT_GNU_versym)
|
||||
typedef struct
|
||||
typedef struct ELF_ExternalVersym ELF_ExternalVersym;
|
||||
struct ELF_ExternalVersym
|
||||
{
|
||||
U16 vs_vers;
|
||||
} ELF_ExternalVersym;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Extensions
|
||||
//~ Extensions
|
||||
|
||||
typedef U8 ELF_CompressType;
|
||||
enum ELF_CompressTypeEnum
|
||||
@@ -801,22 +837,25 @@ enum ELF_CompressTypeEnum
|
||||
ELF_CompressType_HiProc = 0x7fffffff,
|
||||
};
|
||||
|
||||
typedef struct ELF_Chdr32
|
||||
typedef struct ELF_Chdr32 ELF_Chdr32;
|
||||
struct ELF_Chdr32
|
||||
{
|
||||
U32 ch_type;
|
||||
U32 ch_size;
|
||||
U32 ch_addr_align;
|
||||
} ELF_Chdr32;
|
||||
};
|
||||
|
||||
typedef struct ELF_Chdr64
|
||||
typedef struct ELF_Chdr64 ELF_Chdr64;
|
||||
struct ELF_Chdr64
|
||||
{
|
||||
U32 ch_type;
|
||||
U32 ch_reserved;
|
||||
U64 ch_size;
|
||||
U64 ch_addr_align;
|
||||
} ELF_Chdr64;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: 32 => 64 bit conversions
|
||||
|
||||
internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32);
|
||||
internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32);
|
||||
@@ -829,25 +868,28 @@ internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32);
|
||||
internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8 elf_string_from_class(Arena *arena, ELF_Class v);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ELF -> Codebase enum Conversions
|
||||
|
||||
internal Arch arch_from_elf_machine(ELF_MachineKind machine);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ELF Class -> Structure Size
|
||||
|
||||
internal U64 elf_hdr_size_from_class(ELF_Class elf_class);
|
||||
internal U64 elf_phdr_size_from_class(ELF_Class elf_class);
|
||||
internal U64 elf_shdr_size_from_class(ELF_Class elf_class);
|
||||
internal U64 elf_dyn_size_from_class(ELF_Class elf_class);
|
||||
internal U64 elf_sym_size_from_class(ELF_Class elf_class);
|
||||
internal U64 elf_auxv_size_from_class(ELF_Class elf_class);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Compat Readers
|
||||
//~ rjf: Optional Class Conversion Readers
|
||||
|
||||
internal MachineOpResult elf_read_ehdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Hdr64 *ehdr_out);
|
||||
internal MachineOpResult elf_read_phdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out);
|
||||
internal MachineOpResult elf_read_shdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out);
|
||||
internal MachineOpResult elf_read_dyn (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out);
|
||||
internal MachineOpResult elf_read_symbol(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out);
|
||||
internal ELF_Hdr64 elf_hdr64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
internal ELF_Phdr64 elf_phdr64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
internal ELF_Shdr64 elf_shdr64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
internal ELF_Dyn64 elf_dyn64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
internal ELF_Sym64 elf_sym64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
internal ELF_Auxv64 elf_auxv64_from_class_data(ELF_Class elf_class, String8 data);
|
||||
|
||||
#endif // ELF_H
|
||||
+2
-5
@@ -172,8 +172,8 @@ internal ELF_NoteList
|
||||
elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine)
|
||||
{
|
||||
ELF_NoteList result = {0};
|
||||
|
||||
for (U64 cursor = 0; cursor < raw_note.size; ) {
|
||||
for(U64 cursor = 0; cursor < raw_note.size; )
|
||||
{
|
||||
U32 owner_size;
|
||||
U64 owner_size_size = str8_deserial_read_struct(raw_note, cursor, &owner_size);
|
||||
if (owner_size_size == 0) { goto exit; }
|
||||
@@ -206,9 +206,6 @@ elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineK
|
||||
SLLQueuePush(result.first, result.last, n);
|
||||
result.count += 1;
|
||||
}
|
||||
|
||||
exit:;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1251,11 +1251,11 @@ e_value_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
default:{}break;
|
||||
case E_TypeKind_Char8:
|
||||
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
|
||||
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u128.u8[0]);}break;
|
||||
case E_TypeKind_Char16:
|
||||
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
|
||||
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u128.u8[0]);}break;
|
||||
case E_TypeKind_Char32:
|
||||
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
|
||||
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u128.u8[0]);}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1278,7 +1278,7 @@ internal E_DbgInfo *e_dbg_info_from_type_key(E_TypeKey type_key);
|
||||
//
|
||||
// key
|
||||
// ________________________________________________
|
||||
// / / | \
|
||||
// _/ / | \_
|
||||
// text -> expression -> ir tree and type -> interpretation result
|
||||
//
|
||||
// Each one of these calls refers to one stage in this pipeline. The cache will
|
||||
|
||||
@@ -402,8 +402,10 @@ e_interpret(String8 bytecode)
|
||||
|
||||
case RDI_EvalOp_ConstString:
|
||||
{
|
||||
MemoryCopy(&nval, ptr, imm.u64);
|
||||
ptr += imm.u64;
|
||||
U64 src_size = imm.u64;
|
||||
U64 dst_size = Min(sizeof(nval), src_size);
|
||||
MemoryCopy(&nval, ptr, dst_size);
|
||||
ptr += src_size;
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Abs:
|
||||
|
||||
@@ -3110,15 +3110,29 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder)
|
||||
if(matches.count == matches.needle_part_count)
|
||||
{
|
||||
if(info.props.flags & FilePropertyFlag_IsFolder)
|
||||
{
|
||||
if(str8_match(info.name, local_filter, 0))
|
||||
{
|
||||
str8_list_push_front(scratch.arena, &folder_paths, str8_copy(arena, info.name));
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_push(scratch.arena, &folder_paths, str8_copy(arena, info.name));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(str8_match(info.name, local_filter, 0))
|
||||
{
|
||||
str8_list_push_front(scratch.arena, &file_paths, str8_copy(arena, info.name));
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_push(scratch.arena, &file_paths, str8_copy(arena, info.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file_iter_end(iter);
|
||||
}
|
||||
|
||||
|
||||
+48
-1
@@ -199,6 +199,22 @@ e2_msgf(Arena *arena, E2_MsgList *msgs, Rng1U64 src_range, char *fmt, ...)
|
||||
return msg;
|
||||
}
|
||||
|
||||
internal void
|
||||
e2_msg_list_concat_in_place(E2_MsgList *dst, E2_MsgList *src)
|
||||
{
|
||||
if(dst->last != 0 && src->first != 0)
|
||||
{
|
||||
dst->last->next = src->first;
|
||||
dst->last = src->last;
|
||||
dst->count += src->count;
|
||||
}
|
||||
else if(src->first != 0)
|
||||
{
|
||||
MemoryCopyStruct(dst, src);
|
||||
}
|
||||
MemoryZeroStruct(src);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Assets
|
||||
|
||||
@@ -2594,7 +2610,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
internal E2_Compile
|
||||
e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_result, E2_Val compile_time_eval_result, E2_Expr *expr)
|
||||
{
|
||||
E2_Compile compile = {E2_CompileStatus_Error};
|
||||
E2_Compile compile = {E2_CompileStatus_Error, .irtree = &e2_irnode_nil, .params_irtree = &e2_irnode_nil};
|
||||
{
|
||||
E2_IRNode *next_resolve_result = resolve_result;
|
||||
|
||||
@@ -3720,6 +3736,7 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
|
||||
{
|
||||
good = 0;
|
||||
interp.status = E2_InterpStatus_BadRegCode;
|
||||
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "Bad register code (%i).", base_reg_code);
|
||||
}
|
||||
}break;
|
||||
case RDI_EvalOp_FrameOff: {ctx_flags = E2_CtxFlag_HasFrameBase; ctx_base_addr = state->selected_ctx.frame_base_addr;}goto optional_base_off;
|
||||
@@ -3735,6 +3752,16 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
|
||||
else
|
||||
{
|
||||
good = 0;
|
||||
String8 missing_msg = {0};
|
||||
switch(ctx_flags)
|
||||
{
|
||||
default:{}break;
|
||||
case E2_CtxFlag_HasFrameBase: {missing_msg = s("Missing frame base address.");}break;
|
||||
case E2_CtxFlag_HasModuleBase:{missing_msg = s("Missing module base address.");}break;
|
||||
case E2_CtxFlag_HasTLSBase: {missing_msg = s("Missing thread-local-storage base address.");}break;
|
||||
case E2_CtxFlag_HasCFA: {missing_msg = s("Missing canonical frame address.");}break;
|
||||
}
|
||||
e2_msg(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), missing_msg);
|
||||
interp.status = E2_InterpStatus_MissingCtxFlag;
|
||||
interp.missing_ctx_flags |= ctx_flags;
|
||||
}
|
||||
@@ -3979,6 +4006,7 @@ BinOp(U, u64, u64, symbol);
|
||||
{
|
||||
good = 0;
|
||||
interp.status = E2_InterpStatus_BadOffset;
|
||||
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "Couldn't read range [0x%I64x, 0x%I64x) (end of range is 0x%I64x).", offset, offset+bytes_to_read, popped_vals[1].string.size);
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -4029,6 +4057,25 @@ BinOp(U, u64, u64, symbol);
|
||||
}break;
|
||||
}
|
||||
|
||||
//- rjf: push generalized failure messages
|
||||
switch(interp.status)
|
||||
{
|
||||
default:{}break;
|
||||
case E2_InterpStatus_DivideByZero:
|
||||
{
|
||||
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "Divide by zero.");
|
||||
}break;
|
||||
case E2_InterpStatus_UnsupportedOp:
|
||||
{
|
||||
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "Unsupported opcode (%i).", op);
|
||||
}break;
|
||||
case E2_InterpStatus_BadOpTypes:
|
||||
{
|
||||
String8 opcode_name = rdi_string_from_eval_op(scratch.arena, op);
|
||||
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "%S opcode cannot be applied to these types.", opcode_name);
|
||||
}break;
|
||||
}
|
||||
|
||||
//- rjf: if opcode successful -> do stack pops
|
||||
if(good) for EachIndex(pop_idx, pop_count)
|
||||
{
|
||||
|
||||
+1
-1
@@ -64,7 +64,6 @@ typedef enum E2_CompileStatus
|
||||
//- rjf: caller-provided info
|
||||
E2_CompileStatus_MissedIdentifierResolution,
|
||||
E2_CompileStatus_NewIdentifierDefinition,
|
||||
E2_CompileStatus_NewCtxID,
|
||||
E2_CompileStatus_MemberAccess,
|
||||
E2_CompileStatus_IndexAccess,
|
||||
E2_CompileStatus_Call,
|
||||
@@ -559,6 +558,7 @@ internal E2_IRNode *e2_irtree_from_identifier(E2_IdentifierMap *map, String8 nam
|
||||
|
||||
internal E2_Msg *e2_msg(Arena *arena, E2_MsgList *msgs, Rng1U64 src_range, String8 string);
|
||||
internal E2_Msg *e2_msgf(Arena *arena, E2_MsgList *msgs, Rng1U64 src_range, char *fmt, ...);
|
||||
internal void e2_msg_list_concat_in_place(E2_MsgList *dst, E2_MsgList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Assets
|
||||
|
||||
@@ -65,6 +65,12 @@ E2_ExprKindTable:
|
||||
COUNT,
|
||||
}
|
||||
|
||||
@data(String8) e2_expr_kind_string_table:
|
||||
{
|
||||
`{0}`
|
||||
@expand(E2_ExprKindTable a) `str8_lit_comp("$(a.name)")`
|
||||
}
|
||||
|
||||
@data(B8) e2_expr_kind_allow_type_operands_table:
|
||||
{
|
||||
0,
|
||||
|
||||
@@ -4,6 +4,58 @@
|
||||
//- GENERATED CODE
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
String8 e2_expr_kind_string_table[48] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("Identifier"),
|
||||
str8_lit_comp("MacroArg"),
|
||||
str8_lit_comp("TypeIdentifier"),
|
||||
str8_lit_comp("Numeric"),
|
||||
str8_lit_comp("StringLiteral"),
|
||||
str8_lit_comp("CharLiteral"),
|
||||
str8_lit_comp("Ptr"),
|
||||
str8_lit_comp("Array"),
|
||||
str8_lit_comp("Function"),
|
||||
str8_lit_comp("Const"),
|
||||
str8_lit_comp("Volatile"),
|
||||
str8_lit_comp("Unsigned"),
|
||||
str8_lit_comp("Signed"),
|
||||
str8_lit_comp("Dot"),
|
||||
str8_lit_comp("Index"),
|
||||
str8_lit_comp("Call"),
|
||||
str8_lit_comp("DerefAsm"),
|
||||
str8_lit_comp("SizeOf"),
|
||||
str8_lit_comp("TypeOf"),
|
||||
str8_lit_comp("Cast"),
|
||||
str8_lit_comp("Deref"),
|
||||
str8_lit_comp("Address"),
|
||||
str8_lit_comp("Pos"),
|
||||
str8_lit_comp("Neg"),
|
||||
str8_lit_comp("LogNot"),
|
||||
str8_lit_comp("BitNot"),
|
||||
str8_lit_comp("Mul"),
|
||||
str8_lit_comp("Div"),
|
||||
str8_lit_comp("Mod"),
|
||||
str8_lit_comp("Add"),
|
||||
str8_lit_comp("Sub"),
|
||||
str8_lit_comp("LShift"),
|
||||
str8_lit_comp("RShift"),
|
||||
str8_lit_comp("Less"),
|
||||
str8_lit_comp("LtEq"),
|
||||
str8_lit_comp("Grtr"),
|
||||
str8_lit_comp("GrEq"),
|
||||
str8_lit_comp("EqEq"),
|
||||
str8_lit_comp("NtEq"),
|
||||
str8_lit_comp("BitAnd"),
|
||||
str8_lit_comp("BitXor"),
|
||||
str8_lit_comp("BitOr"),
|
||||
str8_lit_comp("LogAnd"),
|
||||
str8_lit_comp("LogOr"),
|
||||
str8_lit_comp("Define"),
|
||||
str8_lit_comp("Macro"),
|
||||
str8_lit_comp("Cond"),
|
||||
};
|
||||
|
||||
B8 e2_expr_kind_allow_type_operands_table[48] =
|
||||
{
|
||||
0,
|
||||
|
||||
@@ -163,6 +163,7 @@ E2_ExprKindParseInfo *expr_kind_parse_infos;
|
||||
};
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 e2_expr_kind_string_table[48];
|
||||
extern B8 e2_expr_kind_allow_type_operands_table[48];
|
||||
extern B8 e2_expr_kind_is_type_expr_table[48];
|
||||
extern B8 e2_expr_kind_is_first_operand_type_maybe_table[48];
|
||||
|
||||
@@ -1766,7 +1766,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
|
||||
}
|
||||
else if(e_space_read(ptr_data->value_eval.space, &byte, &range_info, r1u64(ptr_data->value_eval.value.u64, ptr_data->value_eval.value.u64+1)))
|
||||
{
|
||||
ptr_data->addr_is_good = !(byte_bad_flags & 1);
|
||||
ptr_data->addr_is_good = (range_info.flags & E_SpaceRangeFlag_Stale) || !(byte_bad_flags & 1);
|
||||
}
|
||||
}
|
||||
if(ptr_data->did_redirect)
|
||||
|
||||
@@ -516,12 +516,12 @@ fnt_hash2style_from_tag_size_flags(FNT_Tag tag, F32 size, FNT_RasterFlags flags)
|
||||
//- rjf: tag * size -> style hash
|
||||
U64 style_hash = {0};
|
||||
{
|
||||
F64 size_f64 = size;
|
||||
union { F64 size_f64; U64 size_u64; } size_pun = {.size_f64 = (F64)size};
|
||||
U64 buffer[] =
|
||||
{
|
||||
tag.u64[0],
|
||||
tag.u64[1],
|
||||
*(U64 *)(&size_f64),
|
||||
size_pun.size_u64,
|
||||
(U64)flags,
|
||||
};
|
||||
style_hash = fnt_little_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer)));
|
||||
|
||||
@@ -67,7 +67,7 @@ typedef S32 RAD_S32;
|
||||
#if defined(_MSC_VER)
|
||||
# define RADFORCEINLINE __forceinline
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
# define RADFORCEINLINE __attribute__((always_inline))
|
||||
# define RADFORCEINLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# error need force inline for this compiler
|
||||
#endif
|
||||
|
||||
+34
-4
@@ -11,17 +11,37 @@
|
||||
//~ Usage Samples
|
||||
//
|
||||
#if 0
|
||||
// File Data Blob -> RDI
|
||||
{
|
||||
RDI_Parsed rdi = {0};
|
||||
RDI_ParseStatus status = rdi_parse(data, size, &rdi);
|
||||
}
|
||||
|
||||
// Compressed File Data Blob -> RDI
|
||||
{
|
||||
RDI_Parsed rdi = {0};
|
||||
RDI_ParseStatus status = RDI_ParseStatus_Good;
|
||||
{
|
||||
RDI_Parsed rdi_compressed = {0};
|
||||
RDI_ParseStatus rdi_compressed_status = rdi_parse(compressed_data, compressed_size, &rdi_compressed);
|
||||
RDI_U64 decompressed_size = rdi_decompressed_size_from_parsed(&rdi_compressed);
|
||||
RDI_U8 *decompressed_data = allocate(decompressed_size);
|
||||
rdi_decompress_parsed(decompressed_data, decompressed_size, &rdi_compressed);
|
||||
status = rdi_parse(decompressed_data, decompressed_size, &rdi);
|
||||
}
|
||||
}
|
||||
|
||||
// Procedure Name -> Line
|
||||
{
|
||||
RDI_Parsed *rdi = ...;
|
||||
char *name = "mule_main";
|
||||
RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure
|
||||
RDI_Symbol *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure
|
||||
RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset
|
||||
RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line
|
||||
RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file
|
||||
RDI_U64 file_path_size = 0; // 5. source file -> path
|
||||
RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size);
|
||||
printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num);
|
||||
printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num); // "<name> is at <file>:<line>"
|
||||
}
|
||||
|
||||
// Line -> Procedure Name
|
||||
@@ -31,10 +51,20 @@
|
||||
RDI_U32 line_num = 2557;
|
||||
RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file
|
||||
RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset
|
||||
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure
|
||||
RDI_Symbol *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure
|
||||
RDI_U64 name_size = 0; // 4. procedure -> name
|
||||
RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size);
|
||||
printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name);
|
||||
printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name); // "<file>:<line> is inside <name>"
|
||||
}
|
||||
|
||||
// Virtual Offset -> Procedure Name
|
||||
{
|
||||
RDI_Parsed *rdi = ...;
|
||||
RDI_U64 voff = ...;
|
||||
RDI_Symbol *procedure = rdi_procedure_from_voff(rdi, voff); // 1. voff -> procedure
|
||||
RDI_U64 name_size = 0; // 2. procedure -> name
|
||||
RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size);
|
||||
printf("0x%llx is inside %.*s\n", voff, (int)name_size, name); // "<voff> is inside <name>"
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -442,7 +442,8 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count)
|
||||
RDI_U64 j2_opl = range2->opl;
|
||||
for(;;)
|
||||
{
|
||||
if(src[j1].key <= src[j2].key)
|
||||
if(src[j1].key < src[j2].key ||
|
||||
(src[j1].key == src[j2].key && src[j1].val == 0 && src[j2].val != 0))
|
||||
{
|
||||
rdim_memcpy(dst + jd, src + j1, sizeof(*src));
|
||||
j1 += 1;
|
||||
|
||||
@@ -41,12 +41,12 @@ bit_array_get_bit32(U32Array bit_array, U64 idx)
|
||||
Assert(idx < bit_array.count*32);
|
||||
U64 word_idx = idx / 32;
|
||||
U64 bit_idx = idx % 32;
|
||||
U32 bit = (bit_array.v[word_idx] & (1 << bit_idx)) >> bit_idx;
|
||||
U32 bit = (bit_array.v[word_idx] & (1u << bit_idx)) >> bit_idx;
|
||||
return bit;
|
||||
}
|
||||
|
||||
internal B32
|
||||
bit_array_is_bit_set(U32Array bit_arr, U64 bit_pos)
|
||||
bit_array_is_set32(U32Array bit_arr, U64 bit_pos)
|
||||
{
|
||||
U64 word_idx = bit_pos / 32;
|
||||
Assert(word_idx < bit_arr.count);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
internal U32Array bit_array_init32 (Arena *arena, U64 word_count);
|
||||
internal U32Array bit_array_init32 (Arena *arena, U64 bit_count);
|
||||
internal U64 bit_array_scan_left_to_right32(U32Array bit_array, U64 lo, U64 hi, B32 state);
|
||||
internal U64 bit_array_scan_right_to_left32(U32Array bit_array, U64 lo, U64 hi, B32 state);
|
||||
internal void bit_array_set_bit32 (U32Array bit_array, U64 idx, B32 state);
|
||||
|
||||
@@ -1,103 +1,16 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmacro-redefined"
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning (push, 0)
|
||||
#endif
|
||||
|
||||
#include "third_party/blake3/c/blake3_portable.c"
|
||||
|
||||
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||
|
||||
#define round_fn sse2_round_fn
|
||||
#define compress_pre sse2_compress_pre
|
||||
|
||||
#include "third_party/blake3/c/blake3_sse2.c"
|
||||
|
||||
#define loadu sse41_loadu
|
||||
#define storeu sse41_storeu
|
||||
#define addv sse41_addv
|
||||
#define xorv sse41_xorv
|
||||
#define set1 sse41_set1
|
||||
#define set4 sse41_set4
|
||||
#define rot16 sse41_rot16
|
||||
#define rot12 sse41_rot12
|
||||
#define rot8 sse41_rot8
|
||||
#define rot7 sse41_rot7
|
||||
#define g1 sse41_g1
|
||||
#define g2 sse41_g2
|
||||
#define diagonalize sse41_diagonalize
|
||||
#define undiagonalize sse41_undiagonalize
|
||||
#define compress_pre sse41_compress_pre
|
||||
#define round_fn sse41_round_fn
|
||||
#define transpose_vecs sse41_transpose_vecs
|
||||
#define transpose_msg_vecs sse41_transpose_msg_vecs
|
||||
#define load_counters sse41_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("sse4.1"))), apply_to=function)
|
||||
#endif
|
||||
#include "third_party/blake3/c/blake3_sse41.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#define loadu avx2_loadu
|
||||
#define storeu avx2_storeu
|
||||
#define addv avx2_addv
|
||||
#define xorv avx2_xorv
|
||||
#define set1 avx2_set1
|
||||
#define rot7 avx2_rot7
|
||||
#define rot8 avx2_rot8
|
||||
#define rot12 avx2_rot12
|
||||
#define rot16 avx2_rot16
|
||||
#define round_fn avx2_round_fn
|
||||
#define transpose_vecs avx2_transpose_vecs
|
||||
#define transpose_msg_vecs avx2_transpose_msg_vecs
|
||||
#define load_counters avx2_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("avx2"))), apply_to=function)
|
||||
#endif
|
||||
#include "third_party/blake3/c/blake3_avx2.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#define set4 avx512_set4
|
||||
#define g1 avx512_g1
|
||||
#define g2 avx512_g2
|
||||
#define diagonalize avx512_diagonalize
|
||||
#define undiagonalize avx512_undiagonalize
|
||||
#define compress_pre avx512_compress_pre
|
||||
#define transpose_vecs avx512_transpose_vecs
|
||||
#define transpose_msg_vecs avx512_transpose_msg_vecs
|
||||
#define load_counters avx512_load_counters
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute push(__attribute__((target("avx512f,avx512vl"))), apply_to=function)
|
||||
#endif
|
||||
#include "third_party/blake3/c/blake3_avx512.c"
|
||||
#if defined(__clang__)
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#include "third_party/blake3/blake3_portable.c"
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
#include "third_party/blake3/c/blake3_neon.c"
|
||||
#include "third_party/blake3/blake3_neon.c"
|
||||
#endif
|
||||
|
||||
#include "third_party/blake3/c/blake3_dispatch.c"
|
||||
#include "third_party/blake3/c/blake3.c"
|
||||
#include "third_party/blake3/blake3_dispatch.c"
|
||||
#include "third_party/blake3/blake3.c"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning (pop, 0)
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#pragma comment (lib, "blake3")
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define BLAKE3_API static
|
||||
#define BLAKE3_PRIVATE static
|
||||
|
||||
#include "third_party/blake3/c/blake3.h"
|
||||
#include "third_party/blake3/blake3.h"
|
||||
|
||||
static void
|
||||
blake3(void* out, size_t outlen, void* in, size_t inlen)
|
||||
|
||||
@@ -23,7 +23,7 @@ make_version(U64 major, U64 minor)
|
||||
return version;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
version_compar(Version a, Version b)
|
||||
{
|
||||
int cmp = 0;
|
||||
@@ -48,7 +48,7 @@ isect_off(U32 isect, U32 off)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u16_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U16 a = *(U16*)raw_a;
|
||||
@@ -59,7 +59,7 @@ u16_compar(const void *raw_a, const void *raw_b)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u32_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U32 a = *(U32*)raw_a;
|
||||
@@ -70,7 +70,7 @@ u32_compar(const void *raw_a, const void *raw_b)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u64_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U64 a = *(const U64*)raw_a;
|
||||
@@ -79,7 +79,7 @@ u64_compar(const void *raw_a, const void *raw_b)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u64_compar_inv(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
U64 a = *(const U64*)raw_a;
|
||||
@@ -88,7 +88,7 @@ u64_compar_inv(const void *raw_a, const void *raw_b)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u16_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U16 *a = (U16 *)raw_a;
|
||||
@@ -97,7 +97,7 @@ u16_compar_is_before(void *raw_a, void *raw_b)
|
||||
return is_before;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u32_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U32 *a = (U32 *)raw_a;
|
||||
@@ -106,7 +106,7 @@ u32_compar_is_before(void *raw_a, void *raw_b)
|
||||
return is_before;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u64_compar_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U64 *a = (U64 *)raw_a;
|
||||
@@ -115,7 +115,7 @@ u64_compar_is_before(void *raw_a, void *raw_b)
|
||||
return is_before;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u8_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U8 *a = (U8 *) raw_a;
|
||||
@@ -123,7 +123,7 @@ u8_is_before(void *raw_a, void *raw_b)
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u16_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U16 *a = (U16 *) raw_a;
|
||||
@@ -131,7 +131,7 @@ u16_is_before(void *raw_a, void *raw_b)
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u32_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U32 *a = (U32 *) raw_a;
|
||||
@@ -139,7 +139,7 @@ u32_is_before(void *raw_a, void *raw_b)
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
u64_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
U64 *a = (U64 *) raw_a;
|
||||
@@ -147,7 +147,7 @@ u64_is_before(void *raw_a, void *raw_b)
|
||||
return *a < *b;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u32_is_before_v0(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU32 *a = raw_a;
|
||||
@@ -155,7 +155,7 @@ pair_u32_is_before_v0(void *raw_a, void *raw_b)
|
||||
return a->v0 < b->v0;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u32_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU32 *a = raw_a;
|
||||
@@ -163,7 +163,7 @@ pair_u32_is_before(void *raw_a, void *raw_b)
|
||||
return a->v1 < b->v1;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u64_is_before_v0(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU64 *a = raw_a;
|
||||
@@ -171,7 +171,7 @@ pair_u64_is_before_v0(void *raw_a, void *raw_b)
|
||||
return a->v0 < b->v0;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u64_is_before_v1(void *raw_a, void *raw_b)
|
||||
{
|
||||
PairU64 *a = raw_a;
|
||||
@@ -179,7 +179,7 @@ pair_u64_is_before_v1(void *raw_a, void *raw_b)
|
||||
return a->v1 < b->v1;
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u32_compar_v0(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU32 *a = raw_a;
|
||||
@@ -187,7 +187,7 @@ pair_u32_compar_v0(const void *raw_a, const void *raw_b)
|
||||
return u32_compar(&a->v0, &b->v0);
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u64_compar_v0(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU64 *a = raw_a;
|
||||
@@ -195,7 +195,7 @@ pair_u64_compar_v0(const void *raw_a, const void *raw_b)
|
||||
return u64_compar(&a->v0, &b->v0);
|
||||
}
|
||||
|
||||
internal int
|
||||
internal force_inline int
|
||||
pair_u64_compar_v1(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const PairU64 *a = raw_a;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define U64_RADIX_BITS 8
|
||||
#define U64_RADIX_SIZE (1 << U64_RADIX_BITS)
|
||||
#define U64_RADIX_PARALLEL_MIN 140000
|
||||
|
||||
typedef struct U64RadixTask
|
||||
{
|
||||
Rng1U64 *ranges;
|
||||
U64 *src;
|
||||
U64 *dst;
|
||||
U64 *offsets;
|
||||
U32 shift;
|
||||
} U64RadixTask;
|
||||
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(u64_radix_hist_task)
|
||||
{
|
||||
U64RadixTask *task = raw_task;
|
||||
U64 *counts = task->offsets + task_id * U64_RADIX_SIZE;
|
||||
MemoryZeroTyped(counts, U64_RADIX_SIZE);
|
||||
for EachInRange(i, task->ranges[task_id]) {
|
||||
U64 digit = (task->src[i] >> task->shift) & (U64_RADIX_SIZE - 1);
|
||||
counts[digit] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(u64_radix_scatter_task)
|
||||
{
|
||||
U64RadixTask *task = raw_task;
|
||||
U64 *offsets = task->offsets + task_id * U64_RADIX_SIZE;
|
||||
for EachInRange(i, task->ranges[task_id]) {
|
||||
U64 value = task->src[i];
|
||||
U64 digit = (value >> task->shift) & (U64_RADIX_SIZE - 1);
|
||||
task->dst[offsets[digit]++] = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
u64_array_sort_radix_parallel(TP_Context *tp, U64 count, U64 *v)
|
||||
{
|
||||
if (count < U64_RADIX_PARALLEL_MIN) {
|
||||
u64_array_sort(count, v);
|
||||
return;
|
||||
}
|
||||
|
||||
U64 max_value = u64_array_max(count, v);
|
||||
if (max_value == 0) { return; }
|
||||
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
U64 task_count = tp->worker_count;
|
||||
U64 *buffer = push_array_no_zero(scratch.arena, U64, count);
|
||||
U64 *offsets = push_array_no_zero(scratch.arena, U64, task_count * U64_RADIX_SIZE);
|
||||
U64RadixTask task = {
|
||||
.ranges = tp_divide_work(scratch.arena, count, task_count),
|
||||
.src = v,
|
||||
.dst = buffer,
|
||||
.offsets = offsets,
|
||||
};
|
||||
|
||||
U64 pass_count = (64 - clz64(max_value) + U64_RADIX_BITS - 1) / U64_RADIX_BITS;
|
||||
for EachIndex(pass_idx, pass_count) {
|
||||
task.shift = safe_cast_u32(pass_idx * U64_RADIX_BITS);
|
||||
tp_for_parallel(tp, 0, task_count, u64_radix_hist_task, &task);
|
||||
|
||||
U64 cursor = 0;
|
||||
for EachIndex(digit, U64_RADIX_SIZE) {
|
||||
for EachIndex(task_idx, task_count) {
|
||||
U64 *slot = &offsets[task_idx * U64_RADIX_SIZE + digit];
|
||||
U64 slot_count = *slot;
|
||||
*slot = cursor;
|
||||
cursor += slot_count;
|
||||
}
|
||||
}
|
||||
Assert(cursor == count);
|
||||
|
||||
tp_for_parallel(tp, 0, task_count, u64_radix_scatter_task, &task);
|
||||
Swap(U64 *, task.src, task.dst);
|
||||
}
|
||||
|
||||
if (task.src != v) {
|
||||
MemoryCopyTyped(v, task.src, count);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#undef U64_RADIX_BITS
|
||||
#undef U64_RADIX_SIZE
|
||||
#undef U64_RADIX_PARALLEL_MIN
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
internal void u64_array_sort_radix_parallel(TP_Context *tp, U64 count, U64 *v);
|
||||
@@ -1147,8 +1147,23 @@ cv_debug_t_from_data(Arena *arena, String8 data, U64 align)
|
||||
{
|
||||
CV_DebugT debug_t = { .data = data };
|
||||
|
||||
U64 parse_start_offset = 0;
|
||||
|
||||
// strip LF_PRECOMP from .debug$T to exclude it from leaf arrays
|
||||
B8 has_pch = 0;
|
||||
CV_PrecompInfo precomp = {0};
|
||||
{
|
||||
CV_Leaf leaf = {0};
|
||||
U64 leaf_size = cv_read_leaf(data, 0, CV_LeafAlign, &leaf);
|
||||
if (leaf.kind == CV_LeafKind_PRECOMP) {
|
||||
debug_t.has_pch = 1;
|
||||
debug_t.precomp = cv_precomp_info_from_leaf(leaf);
|
||||
parse_start_offset = leaf_size;
|
||||
}
|
||||
}
|
||||
|
||||
ProfBegin("Upfront parse for counts");
|
||||
for (U64 cursor = 0, prev_cursor = 0, ti = CV_MinComplexTypeIndex; cursor < data.size; ti += 1) {
|
||||
for (U64 cursor = parse_start_offset, prev_cursor = parse_start_offset, ti = CV_MinComplexTypeIndex; cursor < data.size; ti += 1) {
|
||||
CV_Leaf leaf = {0};
|
||||
TryRead(cv_read_leaf(data, cursor, align, &leaf), cursor, count_stop);
|
||||
debug_t.source_counts[cv_type_index_source_from_leaf_kind(leaf.kind)] += 1;
|
||||
@@ -1160,20 +1175,15 @@ count_stop:
|
||||
|
||||
ProfBegin("store leaf offsets");
|
||||
debug_t.offsets = push_array_no_zero(arena, U32, debug_t.count);
|
||||
for (U64 cursor = 0, idx = 0; cursor < data.size && idx < debug_t.count; idx += 1) {
|
||||
for (U64 cursor = parse_start_offset, idx = 0; cursor < data.size && idx < debug_t.count; idx += 1) {
|
||||
debug_t.offsets[idx] = cursor;
|
||||
TryRead(cv_read_leaf(data, cursor, align, &(CV_Leaf){0}), cursor, store_stop);
|
||||
}
|
||||
store_stop:
|
||||
|
||||
for EachElement(i, debug_t.ti_ranges) { debug_t.ti_ranges[i] = r1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + debug_t.count); }
|
||||
for EachElement(i, debug_t.ti_ranges) { debug_t.ti_ranges[i] = r1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + debug_t.count + debug_t.precomp.leaf_count); }
|
||||
|
||||
// shift upper type index bound to include precompiled types
|
||||
CV_Leaf leaf = cv_debug_t_get_leaf(&debug_t, 0);
|
||||
if (leaf.kind == CV_LeafKind_PRECOMP) {
|
||||
CV_PrecompInfo precomp_info = cv_precomp_info_from_leaf(leaf);
|
||||
for EachElement(i, debug_t.ti_ranges) { debug_t.ti_ranges[i].max += precomp_info.leaf_count; }
|
||||
}
|
||||
for (U64 i = 1; i < CV_TypeIndexSource_COUNT; i += 1) { debug_t.pch_ti_range[i] = r1u64s(debug_t.precomp.start_index, debug_t.precomp.leaf_count); }
|
||||
|
||||
ProfEnd();
|
||||
return debug_t;
|
||||
@@ -1452,6 +1462,7 @@ cv_c13_lines_from_sub_sections(Arena *arena, String8 c13_data, Rng1U64 ss_range)
|
||||
String8 sub_sect_data = str8_substr(c13_data, ss_range);
|
||||
|
||||
for (U64 cursor = 0; cursor + sizeof(CV_C13SubSecLinesHeader) <= sub_sect_data.size; ) {
|
||||
U64 header_off = cursor;
|
||||
CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader *)(sub_sect_data.str + cursor);
|
||||
cursor += sizeof(*hdr);
|
||||
|
||||
@@ -1486,6 +1497,7 @@ cv_c13_lines_from_sub_sections(Arena *arena, String8 c13_data, Rng1U64 ss_range)
|
||||
lines_parsed_node->next = 0;
|
||||
|
||||
CV_C13LinesHeader *lines_parsed = &lines_parsed_node->v;
|
||||
lines_parsed->header_off = ss_range.min + header_off;
|
||||
lines_parsed->sec_idx = hdr->sec;
|
||||
lines_parsed->sec_off_lo = hdr->sec_off;
|
||||
lines_parsed->sec_off_hi = hdr->sec_off + hdr->len;
|
||||
@@ -1633,6 +1645,12 @@ cv_c13_voff_map_compar(const void *raw_a, const void *raw_b)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal force_inline int
|
||||
cv_c13_voff_map_is_before(void *raw_a, void *raw_b)
|
||||
{
|
||||
return cv_c13_voff_map_compar(raw_a, raw_b) < 0;
|
||||
}
|
||||
|
||||
internal CV_LinesAccel *
|
||||
cv_c13_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines)
|
||||
{
|
||||
@@ -1676,56 +1694,22 @@ cv_c13_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines)
|
||||
return accel;
|
||||
}
|
||||
|
||||
internal CV_LinesAccel *
|
||||
cv_lines_accel_from_debug_s(Arena *arena, CV_DebugS debug_s)
|
||||
{
|
||||
// parse $$LINES
|
||||
U64 c13_lines_count = 0;
|
||||
CV_LineArray *c13_lines = 0;
|
||||
{
|
||||
String8List raw_lines_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines);
|
||||
|
||||
for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) {
|
||||
Temp temp = temp_begin(arena);
|
||||
CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(temp.arena, raw_lines_node->string, rng_1u64(0, raw_lines_node->string.size));
|
||||
c13_lines_count += parsed_list.count;
|
||||
temp_end(temp);
|
||||
}
|
||||
|
||||
c13_lines = push_array_no_zero(arena, CV_LineArray, c13_lines_count);
|
||||
|
||||
U64 c13_lines_idx = 0;
|
||||
for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) {
|
||||
String8 raw_lines = raw_lines_node->string;
|
||||
CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(arena, raw_lines, rng_1u64(0, raw_lines.size));
|
||||
|
||||
for(CV_C13LinesHeaderNode *header_node = parsed_list.first; header_node != 0; header_node = header_node->next) {
|
||||
c13_lines[c13_lines_idx++] = cv_c13_line_array_from_data(arena, raw_lines, 0, header_node->v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cv_c13_make_lines_accel(arena, c13_lines_count, c13_lines);
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_nearest_line(CV_Line *arr, U64 count, U64 value)
|
||||
{
|
||||
if(count > 1 && arr[0].voff <= value && value < arr[count-1].voff)
|
||||
{
|
||||
U64 l = 0;
|
||||
U64 r = count - 1;
|
||||
for (; l <= r; ) {
|
||||
U64 r = count;
|
||||
for (; l < r; ) {
|
||||
U64 m = l + (r - l) / 2;
|
||||
if (arr[m].voff == value) {
|
||||
return m;
|
||||
} else if (arr[m].voff < value) {
|
||||
if (arr[m].voff <= value) {
|
||||
l = m + 1;
|
||||
} else {
|
||||
r = m - 1;
|
||||
r = m;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
return l - 1;
|
||||
}
|
||||
else if (count == 1 && arr[0].voff == value)
|
||||
{
|
||||
@@ -1754,7 +1738,7 @@ cv_line_from_voff(CV_LinesAccel *accel, U64 voff, U64 *out_line_count)
|
||||
|
||||
lines = accel->map + map_idx;
|
||||
|
||||
for(; map_idx < (accel->map_count-1); map_idx += 1) {
|
||||
for(; map_idx < accel->map_count; map_idx += 1) {
|
||||
if(accel->map[map_idx].voff != near_voff) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ typedef struct CV_File
|
||||
|
||||
typedef struct CV_C13LinesHeader
|
||||
{
|
||||
U64 header_off;
|
||||
U64 sec_idx;
|
||||
U64 sec_off_lo;
|
||||
U64 sec_off_hi;
|
||||
@@ -239,6 +240,8 @@ typedef struct CV_DebugT
|
||||
Rng1U64 ti_ranges [CV_TypeIndexSource_COUNT];
|
||||
|
||||
// PCH
|
||||
B8 has_pch;
|
||||
CV_PrecompInfo precomp;
|
||||
Rng1U64 pch_ti_range[CV_TypeIndexSource_COUNT];
|
||||
U32 pch_obj_idx;
|
||||
} CV_DebugT;
|
||||
|
||||
+22
-14
@@ -334,6 +334,7 @@ hash_table_purge_item(HashTable *ht, U64 hash, BucketNode *node)
|
||||
{
|
||||
U64 bucket_idx = hash % ht->cap;
|
||||
DLLRemove(ht->buckets[bucket_idx].first, ht->buckets[bucket_idx].last, node);
|
||||
SLLQueuePush(ht->free_buckets.first, ht->free_buckets.last, node);
|
||||
ht->count -= 1;
|
||||
}
|
||||
|
||||
@@ -654,11 +655,11 @@ hash_map_purge(HashMap *hm)
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
force_inline HASH_MAP_KEY_MATCH(hash_map_match_u32) { return a->key_u32 == b->key_u32; }
|
||||
force_inline HASH_MAP_KEY_MATCH(hash_map_match_u64) { return a->key_u64 == b->key_u64; }
|
||||
force_inline HASH_MAP_KEY_MATCH(hash_map_match_raw) { return a->key_raw == b->key_raw; }
|
||||
force_inline HASH_MAP_KEY_MATCH(hash_map_match_string) { return str8_match(a->key_string, b->key_string, 0); }
|
||||
force_inline HASH_MAP_KEY_MATCH(hash_map_match_path) { return str8_match(a->key_string, b->key_string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); }
|
||||
internal force_inline HASH_MAP_KEY_MATCH(hash_map_match_u32) { return a->key_u32 == b->key_u32; }
|
||||
internal force_inline HASH_MAP_KEY_MATCH(hash_map_match_u64) { return a->key_u64 == b->key_u64; }
|
||||
internal force_inline HASH_MAP_KEY_MATCH(hash_map_match_raw) { return a->key_raw == b->key_raw; }
|
||||
internal force_inline HASH_MAP_KEY_MATCH(hash_map_match_string) { return str8_match(a->key_string, b->key_string, 0); }
|
||||
internal force_inline HASH_MAP_KEY_MATCH(hash_map_match_path) { return str8_match(a->key_string, b->key_string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); }
|
||||
|
||||
internal U64
|
||||
hash_map_hash_from_path(String8 path)
|
||||
@@ -841,6 +842,13 @@ hash_map_search_u64_u64(HashMap *hm, U64 key)
|
||||
return n ? &n->v.value.value_u64 : 0;
|
||||
}
|
||||
|
||||
internal String8 *
|
||||
hash_map_search_u64_string(HashMap *hm, U64 key)
|
||||
{
|
||||
HashMapNode *n = hash_map_search(hm, hash_map_hasher(str8_struct(&key)), (HashMapKey){ .key_u64 = key }, hash_map_match_u64);
|
||||
return n ? &n->v.value.value_string : 0;
|
||||
}
|
||||
|
||||
internal void *
|
||||
hash_map_search_raw_raw(HashMap *hm, void *key)
|
||||
{
|
||||
@@ -941,29 +949,29 @@ hash_map_extract(Arena *arena,
|
||||
}
|
||||
|
||||
// { keys, value }
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_value) { MemoryCopy(buffer, kv, sizeof(*kv)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_value) { MemoryCopy(buffer, kv, sizeof(*kv)); }
|
||||
internal HashMapKeyValue * key_value_from_hash_map ( Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, hash_map_extract_key_value, sizeof(HashMapKeyValue), 0, 0).keys; }
|
||||
|
||||
// keys
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_u32) { MemoryCopy(buffer, &kv->key.key_u32, sizeof(kv->key.key_u32)); }
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_u64) { MemoryCopy(buffer, &kv->key.key_u64, sizeof(kv->key.key_u64)); }
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_string) { MemoryCopy(buffer, &kv->key.key_string, sizeof(kv->key.key_string)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_u32) { MemoryCopy(buffer, &kv->key.key_u32, sizeof(kv->key.key_u32)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_u64) { MemoryCopy(buffer, &kv->key.key_u64, sizeof(kv->key.key_u64)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_key_string) { MemoryCopy(buffer, &kv->key.key_string, sizeof(kv->key.key_string)); }
|
||||
internal U32 * keys_from_hash_map_u32 ( Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, hash_map_extract_key_u32, sizeof(U32), 0, 0).keys; }
|
||||
internal U64 * keys_from_hash_map_u64 ( Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, hash_map_extract_key_u64, sizeof(U64), 0, 0).keys; }
|
||||
internal String8 * keys_from_hash_map_string( Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, hash_map_extract_key_string, sizeof(String8), 0, 0).keys; }
|
||||
internal void * keys_from_hash_map_raw ( Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, hash_map_extract_key_string, sizeof(void *), 0, 0).keys; }
|
||||
|
||||
// values
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_raw) { MemoryCopy(buffer, &kv->value.value_raw, sizeof(kv->value.value_raw)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
|
||||
internal force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_raw) { MemoryCopy(buffer, &kv->value.value_raw, sizeof(kv->value.value_raw)); }
|
||||
internal U64 * values_from_hash_map_u64(Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_u64, sizeof(U64)).values; }
|
||||
internal void * values_from_hash_map_raw(Arena *arena, HashMap *hm) {return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_raw, sizeof(void *)).values; }
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
force_inline int hash_map_key_is_before_u32(void *a, void *b) { return ((HashMapKeyValue*)a)->key.key_u32 < ((HashMapKeyValue*)b)->key.key_u32; }
|
||||
force_inline int hash_map_key_is_before_u64(void *a, void *b) { return ((HashMapKeyValue*)a)->key.key_u64 < ((HashMapKeyValue*)b)->key.key_u64; }
|
||||
force_inline int hash_map_key_is_before_string(void *a, void *b) { return str8_is_before_case_sensitive(a, b); }
|
||||
internal force_inline int hash_map_key_is_before_u32(void *a, void *b) { return ((HashMapKeyValue*)a)->key.key_u32 < ((HashMapKeyValue*)b)->key.key_u32; }
|
||||
internal force_inline int hash_map_key_is_before_u64(void *a, void *b) { return ((HashMapKeyValue*)a)->key.key_u64 < ((HashMapKeyValue*)b)->key.key_u64; }
|
||||
internal force_inline int hash_map_key_is_before_string(void *a, void *b) { return str8_is_before_case_sensitive(a, b); }
|
||||
|
||||
internal void sort_hash_map_key_value_u32(HashMapKeyValue *pairs, U64 count) { radsort(pairs, count, hash_map_key_is_before_u32); }
|
||||
internal void sort_hash_map_key_value_u64(HashMapKeyValue *pairs, U64 count) { radsort(pairs, count, hash_map_key_is_before_u64); }
|
||||
|
||||
@@ -185,6 +185,7 @@ internal String8 * hash_map_search_path_string (HashMap *hm, String8 key);
|
||||
internal void * hash_map_search_path_raw (HashMap *hm, String8 key);
|
||||
internal void * hash_map_search_u64_raw (HashMap *hm, U64 key);
|
||||
internal U64 * hash_map_search_u64_u64 (HashMap *hm, U64 key);
|
||||
internal String8 * hash_map_search_u64_string (HashMap *hm, U64 key);
|
||||
internal void * hash_map_search_raw_raw (HashMap *hm, void *key);
|
||||
internal U64 * hash_map_search_raw_u64 (HashMap *hm, void *key);
|
||||
|
||||
|
||||
@@ -240,5 +240,32 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="HashMap">
|
||||
<DisplayString>{{ count={count} tombstones={tombstone_count} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[count]">count</Item>
|
||||
<Item Name="[tombstone count]">tombstone_count</Item>
|
||||
<Item Name="[root]">root</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="HashMapNode">
|
||||
<DisplayString Condition="is_live">live</DisplayString>
|
||||
<DisplayString>tombstone</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[key]" Condition="is_live">v.key</Item>
|
||||
<Item Name="[value]" Condition="is_live">v.value</Item>
|
||||
<Synthetic Name="[children]">
|
||||
<DisplayString>radix children</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[0]" Condition="children[0] != 0">children[0]</Item>
|
||||
<Item Name="[1]" Condition="children[1] != 0">children[1]</Item>
|
||||
<Item Name="[2]" Condition="children[2] != 0">children[2]</Item>
|
||||
<Item Name="[3]" Condition="children[3] != 0">children[3]</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
||||
+1031
-969
File diff suppressed because it is too large.
Load diff
+8
-10
@@ -64,6 +64,7 @@ typedef struct LNK_Inputer
|
||||
LNK_InputList new_objs;
|
||||
|
||||
HashTable *libs_ht;
|
||||
HashTable *cmd_lib_names_ht;
|
||||
HashTable *missing_lib_ht;
|
||||
LNK_InputList libs;
|
||||
LNK_InputList new_libs[LNK_InputSource_Count];
|
||||
@@ -98,6 +99,7 @@ typedef struct LNK_Link
|
||||
LNK_LibList libs;
|
||||
LNK_ObjNode **last_symbol_input;
|
||||
LNK_IncludeSymbolNode **last_include;
|
||||
LNK_AltNameNode **last_func_override_alt_name;
|
||||
String8Node **last_cmd_lib;
|
||||
String8Node **last_default_lib;
|
||||
String8Node **last_obj_lib;
|
||||
@@ -115,8 +117,9 @@ typedef struct LNK_LinkResult
|
||||
|
||||
// -- Image Layout ------------------------------------------------------------
|
||||
|
||||
#define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3
|
||||
#define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3
|
||||
#define LNK_REMOVED_ASSOCIATIVE_SYMBOL_VALUE ((U32)-4)
|
||||
#define LNK_REMOVED_SECTION_NUMBER_32 ((U32)-3)
|
||||
#define LNK_REMOVED_SECTION_NUMBER_16 ((U16)-3)
|
||||
|
||||
typedef struct LNK_ImageContext
|
||||
{
|
||||
@@ -130,7 +133,7 @@ typedef struct LNK_SectionDefinition
|
||||
COFF_SectionFlags flags;
|
||||
U64 contribs_count;
|
||||
struct LNK_Obj *obj;
|
||||
U64 obj_sect_idx;
|
||||
U64 obj_section_number;
|
||||
} LNK_SectionDefinition;
|
||||
|
||||
typedef struct LNK_CommonBlockContrib
|
||||
@@ -206,7 +209,6 @@ typedef struct LNK_BaseRelocPageArray
|
||||
typedef struct
|
||||
{
|
||||
B32 search_anti_deps;
|
||||
B32 reset_search_cursor;
|
||||
LNK_Link *link;
|
||||
HashMap *imports_hm;
|
||||
LNK_SymbolTable *symtab;
|
||||
@@ -332,10 +334,6 @@ typedef struct
|
||||
String8 image_data;
|
||||
} LNK_P2R;
|
||||
|
||||
// --- Config -----------------------------------------------------------------
|
||||
|
||||
internal LNK_Config * lnk_config_from_cmdline(CmdLine *cmdline);
|
||||
|
||||
// --- Entry Point -------------------------------------------------------------
|
||||
|
||||
internal void lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config);
|
||||
@@ -358,7 +356,7 @@ internal String8 lnk_manifest_from_inputs(Arena *arena, LNK_IO_Flags io_flags, S
|
||||
|
||||
internal String8 lnk_make_null_obj(Arena *arena);
|
||||
internal String8 lnk_make_res_obj(Arena *arena, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name);
|
||||
internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config);
|
||||
internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config, MSCRT_FeatFlags feat_flags);
|
||||
|
||||
// --- Inputer -----------------------------------------------------------------
|
||||
|
||||
@@ -380,7 +378,7 @@ internal LNK_Input * lnk_inputer_push_lib(LNK_Inputer *inputer, LNK_InputSourceT
|
||||
internal LNK_Input * lnk_inputer_push_lib_linkgen(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data);
|
||||
internal LNK_Input * lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSourceType input_source, String8 lib_path);
|
||||
|
||||
internal B32 lnk_inputer_has_items(LNK_Inputer *inputer);
|
||||
internal B32 lnk_has_pending_input_work(LNK_Inputer *inputer, LNK_Link *link);
|
||||
internal LNK_InputPtrArray lnk_inputer_flush(Arena *arena, TP_Context *tp, LNK_Inputer *inputer, LNK_IO_Flags io_flags, LNK_InputList *all_inputs, LNK_InputList *new_inputs);
|
||||
internal void lnk_inputer_release_file_maps(TP_Context *tp, LNK_Inputer *inputer);
|
||||
|
||||
|
||||
+17
-54
@@ -15,7 +15,7 @@ lnk_arg_list_parse_windows_rules(Arena *arena, String8 string)
|
||||
while(ptr < opl) {
|
||||
U64 size = (U64)(opl - ptr);
|
||||
UnicodeDecode uni = utf8_decode(ptr, size);
|
||||
if (uni.codepoint != ' ' && uni.codepoint != '\n' && uni.codepoint != '\r') {
|
||||
if (uni.codepoint != ' ' && uni.codepoint != '\t' && uni.codepoint != '\n' && uni.codepoint != '\r') {
|
||||
break;
|
||||
}
|
||||
ptr += uni.inc;
|
||||
@@ -31,7 +31,7 @@ lnk_arg_list_parse_windows_rules(Arena *arena, String8 string)
|
||||
UnicodeDecode uni;
|
||||
|
||||
uni = utf8_decode(ptr, (U64)(opl-ptr));
|
||||
if (uni.codepoint == '\0' || uni.codepoint == '\n' || uni.codepoint == '\r' || uni.codepoint == ' ') {
|
||||
if (uni.codepoint == '\0' || uni.codepoint == '\t' || uni.codepoint == '\n' || uni.codepoint == '\r' || uni.codepoint == ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -89,12 +89,12 @@ lnk_cmd_line_push_option_node(LNK_CmdLine *cmd_line, LNK_CmdOption *opt)
|
||||
}
|
||||
|
||||
internal LNK_CmdOption *
|
||||
lnk_cmd_line_push_option_list(Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8List value_strings)
|
||||
lnk_cmd_line_push_option_string(Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8 value)
|
||||
{
|
||||
// fill out node
|
||||
LNK_CmdOption *opt = push_array(arena, LNK_CmdOption, 1);
|
||||
opt->string = string;
|
||||
opt->value_strings = value_strings;
|
||||
opt->value = value;
|
||||
|
||||
// push node
|
||||
lnk_cmd_line_push_option_node(cmd_line, opt);
|
||||
@@ -102,14 +102,6 @@ lnk_cmd_line_push_option_list(Arena *arena, LNK_CmdLine *cmd_line, String8 strin
|
||||
return opt;
|
||||
}
|
||||
|
||||
internal LNK_CmdOption *
|
||||
lnk_cmd_line_push_option_string(Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8 value)
|
||||
{
|
||||
String8List value_list = str8_split_by_string_chars(arena, value, str8_lit(","), StringSplitFlag_KeepEmpties);
|
||||
LNK_CmdOption *opt = lnk_cmd_line_push_option_list(arena, cmd_line, string, value_list);
|
||||
return opt;
|
||||
}
|
||||
|
||||
internal LNK_CmdOption *
|
||||
lnk_cmd_line_push_option(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value)
|
||||
{
|
||||
@@ -129,9 +121,11 @@ internal void
|
||||
lnk_cmd_line_concat_in_place(LNK_CmdLine *list, LNK_CmdLine *to_concat)
|
||||
{
|
||||
if (list->option_count > 0) {
|
||||
if (to_concat->option_count > 0) {
|
||||
list->option_count += to_concat->option_count;
|
||||
list->last_option->next = to_concat->first_option;
|
||||
list->last_option = to_concat->last_option;
|
||||
}
|
||||
str8_list_concat_in_place(&list->input_list, &to_concat->input_list);
|
||||
str8_list_concat_in_place(&list->raw_cmd_line, &to_concat->raw_cmd_line);
|
||||
} else {
|
||||
@@ -147,11 +141,9 @@ lnk_cmd_line_parse_windows_rules(Arena *arena, String8List arg_list)
|
||||
LNK_CmdLine cmd_line = {0};
|
||||
cmd_line.raw_cmd_line = str8_list_copy(arena, &arg_list);
|
||||
|
||||
for (String8Node *arg_node = arg_list.first; arg_node != 0; arg_node = arg_node->next) {
|
||||
for EachNode(arg_node, String8Node, arg_list.first) {
|
||||
String8 arg = arg_node->string;
|
||||
B32 is_option = str8_match_lit("/", arg, StringMatchFlag_RightSideSloppy) ||
|
||||
str8_match_lit("-", arg, StringMatchFlag_RightSideSloppy);
|
||||
if (is_option) {
|
||||
if (str8_starts_with(arg, str8_lit("/")) || str8_starts_with(arg, str8_lit("-"))) {
|
||||
U64 param_start_pos = str8_find_needle(arg, 0, str8_lit(":"), 0);
|
||||
String8 option_name = str8_chop(arg, arg.size - param_start_pos);
|
||||
|
||||
@@ -161,13 +153,12 @@ lnk_cmd_line_parse_windows_rules(Arena *arena, String8List arg_list)
|
||||
// skip ':'
|
||||
String8 value_string = str8_skip(arg, param_start_pos + 1);
|
||||
|
||||
// make value list
|
||||
String8List value_list_unowned = str8_split_by_string_chars(scratch.arena, value_string, str8_lit(","), 0);
|
||||
String8List value_list = str8_list_copy(arena, &value_list_unowned);
|
||||
|
||||
// push command
|
||||
option_name = push_str8_copy(arena, option_name);
|
||||
lnk_cmd_line_push_option_list(arena, &cmd_line, option_name, value_list);
|
||||
value_string = push_str8_copy(arena, value_string);
|
||||
lnk_cmd_line_push_option_string(arena, &cmd_line, option_name, value_string);
|
||||
} else if (str8_starts_with(arg, str8_lit("@"))) {
|
||||
lnk_cmd_line_push_option_string(arena, &cmd_line, push_str8_copy(arena, arg), str8_zero());
|
||||
} else {
|
||||
str8_list_push(arena, &cmd_line.input_list, push_str8_copy(arena, arg));
|
||||
}
|
||||
@@ -202,7 +193,7 @@ lnk_cmd_line_option_from_string(LNK_CmdLine cmd_line, String8 string)
|
||||
{
|
||||
LNK_CmdOption *opt;
|
||||
for (opt = cmd_line.first_option; opt != NULL; opt = opt->next) {
|
||||
if (str8_match(string, opt->string, StringMatchFlag_CaseInsensitive)) {
|
||||
if (str8_matchi(string, opt->string)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -228,42 +219,14 @@ lnk_data_from_cmd_line(Arena *arena, LNK_CmdLine cmd_line)
|
||||
{
|
||||
String8List result = {0};
|
||||
|
||||
for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) {
|
||||
// separate directives
|
||||
for EachNode(opt, LNK_CmdOption, cmd_line.first_option) {
|
||||
// separate commands
|
||||
if (opt != cmd_line.first_option) {
|
||||
str8_list_pushf(arena, &result, " ");
|
||||
}
|
||||
|
||||
// push new directive
|
||||
str8_list_pushf(arena, &result, "/%.*s", str8_varg(opt->string));
|
||||
|
||||
// do we have arguments?
|
||||
if (opt->value_strings.node_count > 0) {
|
||||
str8_list_pushf(arena, &result, ":");
|
||||
|
||||
for (String8Node *value_node = opt->value_strings.first; value_node != 0; value_node = value_node->next) {
|
||||
// separate arguments
|
||||
if (value_node != opt->value_strings.first) {
|
||||
str8_list_pushf(arena, &result, ",");
|
||||
}
|
||||
|
||||
// push argument
|
||||
B32 has_spaces = str8_find_needle(value_node->string, 0, str8_lit(" "), StringMatchFlag_CaseInsensitive) < value_node->string.size;
|
||||
if (has_spaces) {
|
||||
str8_list_pushf(arena, &result, "\"%.*s\"", str8_varg(value_node->string));
|
||||
} else {
|
||||
str8_list_pushf(arena, &result, "%.*s", str8_varg(value_node->string));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append inputs
|
||||
for (String8Node *input_node = cmd_line.input_list.first; input_node != 0; input_node = input_node->next) {
|
||||
if (input_node != cmd_line.input_list.first) {
|
||||
str8_list_pushf(arena, &result, " ");
|
||||
}
|
||||
str8_list_pushf(arena, &result, "\"%.*s\"", str8_varg(input_node->string));
|
||||
// push command line option
|
||||
str8_list_pushf(arena, &result, "/%S%s%S", opt->string, opt->value.size ? ":" : "", opt->value);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -7,7 +7,7 @@ typedef struct LNK_CmdOption
|
||||
{
|
||||
struct LNK_CmdOption *next;
|
||||
String8 string;
|
||||
String8List value_strings;
|
||||
String8 value;
|
||||
} LNK_CmdOption;
|
||||
|
||||
typedef struct LNK_CmdLine
|
||||
@@ -50,7 +50,7 @@ internal String8List lnk_arg_list_parse_windows_rules (Arena *arena,
|
||||
internal LNK_CmdLine lnk_cmd_line_parse_windows_rules (Arena *arena, String8List arg_list);
|
||||
internal LNK_CmdLine lnk_cmd_line_from_stringfv_windows_rules(Arena *arena, char *fmt, va_list args);
|
||||
internal LNK_CmdLine lnk_cmd_line_from_stringf_windows_rules (Arena *arena, char *fmt, ...);
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_option_list (Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8List value_strings);
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_option_string (Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8 value);
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_option (Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value);
|
||||
internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_present (Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value);
|
||||
internal String8List lnk_data_from_cmd_line (Arena *arena, LNK_CmdLine cmd_line);
|
||||
|
||||
Loaded 100 of 266 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user