Merge remote-tracking branch 'EpicGamesExt/master'

This commit is contained in:
ed committed 2026-10-19 14:25:47 -04:00
commit 8066378fd3
267 files changed
+25193 -17386

No files matched your search

+86 -19
View File
@@ -12,7 +12,7 @@ env:
TORTURE_FLAGS: "--gen_crash_dump" TORTURE_FLAGS: "--gen_crash_dump"
jobs: jobs:
build-ubuntu-24-04: build-ubuntu-24:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
strategy: strategy:
fail-fast: false fail-fast: false
@@ -24,30 +24,58 @@ jobs:
- radbin - radbin
- torture - torture
compiler: compiler:
- clang-17
- clang-22 - clang-22
# TODO: - gcc - gcc
mode:
- debug name: ${{ matrix.target }}-${{ matrix.compiler }}-ubuntu24
- release
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
lfs: true 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 shell: bash
run: | run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 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-add-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main"
sudo apt-get update 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
sudo ln -s /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer sudo ln -sf /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer
- name: build echo CC="${{ matrix.compiler }}" >> "${GITHUB_ENV}"
echo AR=llvm-ar-22 >> "${GITHUB_ENV}"
- name: Build (debug)
shell: bash shell: bash
run: | 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 runs-on: windows-2022
strategy: strategy:
fail-fast: false fail-fast: false
@@ -60,23 +88,60 @@ jobs:
compiler: compiler:
- msvc - msvc
- clang - clang
mode:
- debug name: ${{ matrix.target }}-${{ matrix.compiler }}-vs2022
- release
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
lfs: true lfs: true
- name: build (vs 2022) - name: Build (debug)
shell: cmd shell: cmd
run: | 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 "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 || exit /b 1
call "%VS_INSTALL%\VC\Auxiliary\Build\vcvarsall.bat" x64 call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" debug || exit /b 1
call build meta "${{ matrix.target }}" "${{ matrix.compiler }}" "${{ matrix.mode }}" || 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: run-ubuntu-24-04:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
if: false
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -97,12 +162,13 @@ jobs:
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 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-add-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main"
sudo apt-get update 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 # crash callstack symbolizer depends on LLVM
sudo ln -s /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer sudo ln -s /usr/bin/llvm-symbolizer-22 /usr/bin/llvm-symbolizer
- name: Run - name: Run
shell: bash shell: bash
run: | run: |
[[ "${{ matrix.compiler }}" == "clang-22" ]] && export AR=llvm-ar-22
CC="${{ matrix.compiler }}" ./run_tests.sh clang "${{ matrix.mode }}" -- \* $TORTURE_FLAGS CC="${{ matrix.compiler }}" ./run_tests.sh clang "${{ matrix.mode }}" -- \* $TORTURE_FLAGS
- name: Upload Artifacts - name: Upload Artifacts
if: failure() if: failure()
@@ -118,6 +184,7 @@ jobs:
run-windows-2022: run-windows-2022:
runs-on: windows-2022 runs-on: windows-2022
if: false
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
+99 -2
View File
@@ -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 # 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 ## Linker Changes
- Implemented `/OPT:ICF` identical COMDAT folding. - Implemented `/OPT:ICF` identical COMDAT folding.
- Added DEF, and SECTION configuration support. - Added DEF, and SECTION configuration support.
- Improved COMDAT handling for weak symbols, ICF, and zero-sized COMDAT - Improved COMDAT handling for weak symbols, ICF, and zero-sized COMDAT
anchors, and stopped emitting empty marker sections that could produce invalid anchors, and stopped emitting empty marker sections that could produce
PE images. invalid PE images.
- Fixed import/export edge cases, including import data-directory bounds and - Fixed import/export edge cases, including import data-directory bounds and
archive member handling for `__imp_*` symbols. archive member handling for `__imp_*` symbols.
- Accepted duplicate identical weak search aliases without reporting multiply - Accepted duplicate identical weak search aliases without reporting multiply
@@ -14,6 +105,12 @@
- Fixed DBI section-contribution image-section range mapping. - Fixed DBI section-contribution image-section range mapping.
- Improved debug logging for `/OPT:REF` liveness stats and unresolved symbols - Improved debug logging for `/OPT:REF` liveness stats and unresolved symbols
referenced by `.llvm_addrsig`. 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 # v0.9.27-alpha
+136 -65
View File
@@ -8,9 +8,9 @@ local copy has been built. You can find pre-built release binaries
[here](https://github.com/EpicGames/raddebugger/releases)._ [here](https://github.com/EpicGames/raddebugger/releases)._
The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It
currently only supports local-machine Windows x64 debugging with PDBs, with currently only supports local-machine x64 debugging on both Windows and Linux
plans to expand and port in the future. In the future we'll expand to also (although Linux support is still very early). We plan to expand support to
support native Linux debugging and DWARF debug info. other architectures, and to implement remote and multi-machine debugging.
The debugger is currently in *ALPHA*. In order to get the debugger 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 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 RAD Debug Info (RDI) format is our custom debug information format, which
the debugger parses and uses, rather than the debug information natively the debugger parses and uses, rather than the debug information natively
produced by toolchains, like PDB or DWARF. To work with these existing produced by toolchains, like PDB or DWARF. To work with these existing
toolchains, we convert PDB (and eventually PE/ELF files with embedded DWARF) toolchains, we convert PDB and DWARF to the RDI format on-demand.
into the RDI format on-demand.
The RDI format is currently specified in code, in the files within the 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 `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 ### 1. Installing the Required Tools (MSVC & Windows SDK)
v15 (2017) or later](https://aka.ms/vs/17/release/vs_BuildTools.exe), for both
the Windows SDK and the MSVC compiler and linker. 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++ 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/). 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 Building the codebase can be done in a terminal which is equipped with the
ability to call either MSVC or Clang from command line. ability to call either MSVC or Clang from command line.
@@ -169,73 +171,142 @@ build radlink release
build radbin 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 #### GCC on Ubuntu / Debian / Mint
are functioning extremely reliably for local, x64, Windows development. ```
For the debugger, this would include parts like debug info conversion, debug sudo apt update && sudo apt install build-essential
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.
We feel that we've already come a long way in all of these respects, but given #### Clang on Ubuntu / Debian / Mint
the massive set of possible combinations of languages, build settings, ```
toolchains, used language features, and patterns of generated code, we still sudo apt update && sudo apt install clang llvm
expect some issues, and are prioritizing these issues being resolved first. ```
We also hope to continue to improve performance in this phase. For the debugger, #### GCC on Arch / Manjaro
this primarily includes frontend performance, introducing caches when economical ```
to do so, and tightening existing systems up. For the linker, it has been mostly sudo pacman -S base-devel
tuned thus far for giant projects, and so we'd like to improve linking speed for ```
small-to-mid sized projects as well.
For the linker, there are also a number of features to come, like #### Clang on Arch / Manjaro
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). 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 clang --version && llvm-ar --version
Linux debugging also. ```
The debugger has been written to abstract over the parts that need to differ on You should see output similar to the following:
either Linux or Windows, and this is mainly going to be a task in building out
different backends for those abstraction layers.
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 If you've installed the GCC tooling required, you can run:
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).
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 gcc --version && gcc-ar --version
available natively on Linux machines. ```
### 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 gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
the debugger's features (like improving the visualization engine), and so on. Copyright (C) 2023 Free Software Foundation, Inc.
But for now, we're mostly focused on those first two phases. 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
```
--- ---
+64 -4
View File
@@ -27,10 +27,12 @@ cd /D "%~dp0"
:: - `ubsan`: enable undefined-behavior sanitizer :: - `ubsan`: enable undefined-behavior sanitizer
:: - `telemetry`: enable RAD telemetry profiling support :: - `telemetry`: enable RAD telemetry profiling support
:: - `spall`: enable spall profiling support :: - `spall`: enable spall profiling support
:: - `oodle`: enable Oodle from local\oodle2*\win or an explicit OODLE_SDK_DIR
:: --- Unpack Arguments ------------------------------------------------------- :: --- Unpack Arguments -------------------------------------------------------
for %%a in (%*) do set "%%~a=1" for %%a in (%*) do set "%%~a=1"
if not "%msvc%"=="1" if not "%clang%"=="1" set msvc=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 not "%release%"=="1" set debug=1
if "%debug%"=="1" set release=0 && echo [debug mode] if "%debug%"=="1" set release=0 && echo [debug mode]
if "%release%"=="1" set debug=0 && echo [release 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 ------------------------------------------ :: --- Compile/Link Line Definitions ------------------------------------------
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 /Zc:preprocessor 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% 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 "%clang%"=="1" set rc=call llvm-rc
if "%msvc%"=="1" set link_dll=/link /DLL if "%msvc%"=="1" set link_dll=/link /DLL
if "%clang%"=="1" set link_dll=-Xlinker -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 ---------------------------------------------- :: --- Choose Compile/Link Lines ----------------------------------------------
if "%msvc%"=="1" set compile_debug=%cl_debug% 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 %rc% /nologo /fo logo.res ..\data\logo.rc || exit /b 1
popd 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 ------------------------------------------------ :: --- Build & Run Metaprogram ------------------------------------------------
pushd build pushd build
if not exist metagen.exe set meta=1
if "%meta%"=="1" ( if "%meta%"=="1" (
echo [building metagen] echo [building metagen]
%compile_debug% ..\src\metagen\metagen_main.c %compile_link% %out%metagen.exe || exit /b 1 %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 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) -------------------------------------- :: --- Build Everything (@build_targets) --------------------------------------
pushd build 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%"=="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 "%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 "%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 "%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 "%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 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 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.
)
+86 -24
View File
@@ -3,23 +3,24 @@ set -eu
cd "$(dirname "$0")" cd "$(dirname "$0")"
# --- Unpack Arguments -------------------------------------------------------- # --- Unpack Arguments --------------------------------------------------------
auto_compile_flags=""
for arg in "$@"; do declare $arg='1'; done for arg in "$@"; do declare $arg='1'; done
if [[ "$#" == "0" ]]; then raddbg='1'; fi if [[ "$#" == "0" ]]; then raddbg='1'; fi
if [[ "$#" == "1" && "${release:-0}" == "1" ]]; then raddbg='1'; fi
cc_sanitize=""
if [[ "${asan:-0}" == "1" ]]; then if [[ "${asan:-0}" == "1" ]]; then
echo "[asan enabled]" echo "[asan enabled]"
cc_sanitize="-fsanitize=address" auto_compile_flags="$auto_compile_flags -fsanitize=address"
fi fi
# --- Get Current Git Commit Id ----------------------------------------------- # --- Mix Git Commit ID -------------------------------------------------------
git_hash=$(git describe --always --dirty) if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git_hash_full=$(git rev-parse HEAD) 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 ------------------------------------------- # --- Compile/Link Line Definitions -------------------------------------------
cc_cflags_gcc="" 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_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="-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_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_debug="-g -O0 -DBUILD_DEBUG=1 ${cc_common}"
cc_release="-g -O2 -DBUILD_DEBUG=0 ${cc_common}" cc_release="-g -O2 -DBUILD_DEBUG=0 ${cc_common}"
cc_link="-lpthread -lm -lrt -ldl" cc_link="-lpthread -lm -lrt -ldl"
@@ -28,50 +29,111 @@ cc_link="-lpthread -lm -lrt -ldl"
cc_link_dll="-fPIC" cc_link_dll="-fPIC"
# --- External Libraries ------------------------------------------------------ # --- 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 if [[ -x "$(command -v pkg-config)" ]]; then
cc_font_provider="$(pkg-config --cflags --libs freetype2)" 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)" cc_render="$(pkg-config --cflags --libs gl egl)"
else else
cc_font_provider="-I/usr/include/freetype2 -lfreetype" cc_font_provider="-I/usr/include/freetype2 -lfreetype"
cc_os_gfx="-lX11 -lXext" cc_os_gfx="-lX11 -lXext -lXfixes -lXrandr"
cc_render="-lGL -lEGL" cc_render="-lGL -lEGL"
fi fi
# --- Icons -------------------------------------------------------------------
cc_icon="-DLNX_WM_ICON=1"
# --- Choose Compile/Link Lines ----------------------------------------------- # --- Choose Compile/Link Lines -----------------------------------------------
if [[ "${gcc:-0}" == "1" ]]; then compiler="${CC:-gcc} $cc_cflags_gcc"; echo "[gcc 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"; echo "[clang compile]"; elif [[ "${clang:-1}" == "1" ]]; then compiler="${CC:-clang} $cc_cflags_clang"; ar="${AR:-llvm-ar}"; echo "[clang compile]";
fi fi
if [[ "${release:-0}" == "1" ]]; then echo "[release mode]"; compile="$compiler $cc_release"; if [[ "${release:-0}" == "1" ]]; then echo "[release mode]"; compile="$compiler $cc_release";
elif [[ "${debug:-1}" == "1" ]]; then echo "[debug mode]"; compile="$compiler $cc_debug"; elif [[ "${debug:-1}" == "1" ]]; then echo "[debug mode]"; compile="$compiler $cc_debug";
fi fi
oodle_flags=()
compile() {
$compile "${oodle_flags[@]}" -Wl,--start-group "$@" blake3.a -latomic -Wl,--end-group
}
# --- Prep Directories -------------------------------------------------------- # --- Prep Directories --------------------------------------------------------
mkdir -p build local mkdir -p build local
# --- Build & Run Metaprogram ------------------------------------------------- # --- Build & Run Metaprogram -------------------------------------------------
if [[ "${no_meta:-0}" == "0" ]] cd build
then if [[ ! -f metagen ]]; then meta='1'; fi
if [[ "${meta:-0}" == "1" ]]; then
echo "[building metagen]" echo "[building metagen]"
cd build
$compiler $cc_debug ../src/metagen/metagen_main.c $cc_link -o metagen $compiler $cc_debug ../src/metagen/metagen_main.c $cc_link -o metagen
fi
if [[ ! -v no_meta ]]; then
./metagen ./metagen
cd .. 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 fi
# --- Build Everything (@build_targets) --------------------------------------- # --- Build Everything (@build_targets) ---------------------------------------
cd build 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:-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 [[ "${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 [[ "${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 [[ "${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 [[ "${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 .. cd ..
# --- Warn On No Builds ------------------------------------------------------- # --- Warn On No Builds -------------------------------------------------------
if [[ "${didbuild:-0}" == "0" ]] if [[ "${didbuild:-0}" == "0" ]]; then
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\`." 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 exit 1
fi 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
BIN
View File
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
View File
@@ -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", .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 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 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] //- rjf: [raddbg wsl]
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .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, }, // .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 //- 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 = "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 = "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, }, // .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
View File
@@ -1,75 +1,56 @@
// raddbg 0.9.28 project file // raddbg 0.9.30 project file
name: "The RAD Debugger" name: "The RAD Debugger"
target: target:
{ {
executable: "build/raddbg.exe" executable: "build/raddbg.exe"
working_directory: "../raddebugger" working_directory: build
arguments: "--user:C:/devel/raddebugger/build/raddbg_test.user" arguments: "--user:raddbg_test.user"
debug_subprocesses: 0 debug_subprocesses: 0
} }
target: target:
{ {
executable: "build/raddbg.exe" executable: "build/raddbg_server.exe"
working_directory: "../raddebugger"
arguments: "--user:test123"
debug_subprocesses: 0
}
target:
{
executable: "build/mule_main.exe"
working_directory: build working_directory: build
output_label: output_a debug_subprocesses: 1
}
target:
{
executable: "build/torture.exe"
working_directory: build
arguments: "eval2/*"
} }
target: target:
{ {
executable: "build/metagen.exe" executable: "build/metagen.exe"
working_directory: build working_directory: build
enabled: 1
} }
target: target:
{ {
executable: "build/radbin.exe" executable: "build/mule_main.exe"
working_directory: build working_directory: build
arguments: "--rdi raddbg"
} }
target: target:
{ {
executable: "build/release_version/raddbg.exe" executable: "build/torture.exe"
working_directory: "build/release_version"
}
target:
{
executable: "build/radbin.exe"
working_directory: build working_directory: build
arguments: "--rdi fat.so --capture" arguments: *
}
target:
{
executable: "build/radbin.exe"
working_directory: build
arguments: "--rdi fat.debug --capture"
}
target:
{
executable: "build/radbin.exe"
working_directory: build
arguments: "--rdi raddbg"
} }
watch_pin: expression: tag_hash_slots watch_pin: expression: tag_hash_slots
target: target:
{ {
executable: "build/ryan_scratch.exe" executable: "build/ryan_scratch.exe"
working_directory: build working_directory: build
enabled: 1
} }
target: target:
{ {
executable: "../../Program Files/SuperTux/bin/supertux2.exe" executable: "build/raddbg"
working_directory: "../../Program Files/SuperTux/bin" 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
+1
View File
@@ -681,6 +681,7 @@ ac_async_tick(void)
internal void internal void
ac_cancel_thread_entry_point(void *p) ac_cancel_thread_entry_point(void *p)
{ {
ThreadNameF("ac_cancel_thread");
for(;;) for(;;)
{ {
sleep_ms(50); sleep_ms(50);
+14 -14
View File
@@ -29,7 +29,7 @@ internal Arena *
arena_alloc_(ArenaParams *params) arena_alloc_(ArenaParams *params)
{ {
ProfBeginFunction(); ProfBeginFunction();
U64 reserve_size = params->reserve_size; U64 reserve_size = params->reserve_size;
U64 commit_size = params->commit_size; U64 commit_size = params->commit_size;
@@ -69,13 +69,13 @@ arena_alloc_(ArenaParams *params)
} }
// rjf: panic on arena creation failure // rjf: panic on arena creation failure
#if OS_FEATURE_GRAPHICAL
if(Unlikely(base == 0)) 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); abort_self(1);
} }
#endif
// rjf: extract arena header & fill // rjf: extract arena header & fill
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE); AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
@@ -143,7 +143,7 @@ internal void
arena_release(Arena *arena) arena_release(Arena *arena)
{ {
ProfBeginFunction(); ProfBeginFunction();
#if PROFILE_TELEMETRY #if PROFILE_TELEMETRY
{ {
Arena *base_arena = arena; Arena *base_arena = arena;
@@ -176,7 +176,7 @@ arena_release(Arena *arena)
AsanUnpoisonMemoryRegion(n, n->cmt); AsanUnpoisonMemoryRegion(n, n->cmt);
release_memory(n, n->res); release_memory(n, n->res);
} }
ProfEnd(); ProfEnd();
} }
@@ -227,8 +227,8 @@ arena_push(Arena *arena, U64 size, U64 align, B32 zero)
if(new_block == 0) if(new_block == 0)
{ {
U64 res_size = current->res_size; U64 res_size = arena->res_size;
U64 cmt_size = current->cmt_size; U64 cmt_size = arena->cmt_size;
if(size + ARENA_HEADER_SIZE > res_size) if(size + ARENA_HEADER_SIZE > res_size)
{ {
res_size = AlignPow2(size + ARENA_HEADER_SIZE, align); 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, new_block = arena_alloc(.reserve_size = res_size,
.commit_size = cmt_size, .commit_size = cmt_size,
.flags = current->flags, .flags = arena->flags,
.allocation_site_file = current->allocation_site_file, .allocation_site_file = arena->allocation_site_file,
.allocation_site_line = current->allocation_site_line); .allocation_site_line = arena->allocation_site_line);
size_to_zero = 0; size_to_zero = 0;
} }
@@ -295,13 +295,13 @@ arena_push(Arena *arena, U64 size, U64 align, B32 zero)
#endif #endif
// rjf: panic on failure // rjf: panic on failure
#if OS_FEATURE_GRAPHICAL
if(Unlikely(result == 0)) 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); abort_self(1);
} }
#endif
return result; return result;
} }
+1 -1
View File
@@ -163,7 +163,7 @@
#endif #endif
#if !defined(BUILD_VERSION_PATCH) #if !defined(BUILD_VERSION_PATCH)
# define BUILD_VERSION_PATCH 28 # define BUILD_VERSION_PATCH 30
#endif #endif
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
-33
View File
@@ -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 internal U32
idx_of_zero_byte64(U8 *ptr, U64 size) idx_of_zero_byte64(U8 *ptr, U64 size)
{ {
+6 -8
View File
@@ -21,6 +21,7 @@
#define STB_SPRINTF_DECORATE(name) raddbg_##name #define STB_SPRINTF_DECORATE(name) raddbg_##name
#define STB_SPRINTF_STATIC #define STB_SPRINTF_STATIC
#include "third_party/stb/stb_sprintf.h" #include "third_party/stb/stb_sprintf.h"
#include "third_party/radsort/radsort.h"
//////////////////////////////// ////////////////////////////////
//~ rjf: Codebase Keywords //~ rjf: Codebase Keywords
@@ -54,7 +55,7 @@
#if COMPILER_MSVC #if COMPILER_MSVC
# define force_inline __forceinline # define force_inline __forceinline
#elif COMPILER_CLANG || COMPILER_GCC #elif COMPILER_CLANG || COMPILER_GCC
# define force_inline __attribute__((always_inline)) # define force_inline inline __attribute__((always_inline))
#else #else
# error force_inline not defined for this compiler. # error force_inline not defined for this compiler.
#endif #endif
@@ -199,7 +200,7 @@
#define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) #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 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 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 //~ rjf: Memory Operation Macros
@@ -241,8 +242,8 @@
#else #else
# define Assert(x) (void)(x) # define Assert(x) (void)(x)
#endif #endif
#define InvalidPath Assert(!"Invalid Path!") #define InvalidPath AssertAlways(!"Invalid Path!")
#define NotImplemented Assert(!"Not Implemented!") #define NotImplemented AssertAlways(!"Not Implemented!")
#define NoOp ((void)0) #define NoOp ((void)0)
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1] #define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
@@ -695,6 +696,7 @@ enum
AccessFlag_ShareRead = (1<<4), AccessFlag_ShareRead = (1<<4),
AccessFlag_ShareWrite = (1<<5), AccessFlag_ShareWrite = (1<<5),
AccessFlag_Inherited = (1<<6), 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 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_u32(U32 *ptr, U64 count);
internal U64 index_of_zero_u64(U64 *ptr, U64 count); internal U64 index_of_zero_u64(U64 *ptr, U64 count);
+7 -1
View File
@@ -58,6 +58,9 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
} }
//- rjf: initialize all included layers //- rjf: initialize all included layers
#if defined(SOCKET_H) && !defined(SOCKET_INIT_MANUAL)
sock_init();
#endif
#if defined(HTTP_H) && !defined(HTTP_INIT_MANUAL) #if defined(HTTP_H) && !defined(HTTP_INIT_MANUAL)
http_init(); http_init();
#endif #endif
@@ -79,7 +82,7 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
#if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL) #if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL)
di_init(&cmdline); di_init(&cmdline);
#endif #endif
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) #if defined(DEMON_H) && !defined(DMN_INIT_MANUAL)
dmn_init(); dmn_init();
#endif #endif
#if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL) #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) #if defined(FILE_STREAM_H)
fs_async_tick(); fs_async_tick();
#endif #endif
#if defined(SOCKET_H)
sock_async_tick();
#endif
#if defined(HTTP_H) #if defined(HTTP_H)
http_async_tick(); http_async_tick();
#endif #endif
+16
View File
@@ -40,6 +40,13 @@ struct File
U64 u64[1]; U64 u64[1];
}; };
typedef struct FilePair FilePair;
struct FilePair
{
File read;
File write;
};
typedef struct FileMap FileMap; typedef struct FileMap FileMap;
struct FileMap struct FileMap
{ {
@@ -70,6 +77,11 @@ internal String8 file_read_cstring(Arena *arena, File file, U64 off);
//- rjf: files //- rjf: files
internal File file_open(AccessFlags flags, String8 path); internal File file_open(AccessFlags flags, String8 path);
internal void file_close(File file); 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); 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)) #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); 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 FileProperties properties_from_file(File file);
internal FileID id_from_file(File file); internal FileID id_from_file(File file);
internal B32 file_reserve_size(File file, U64 size); 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 delete_file_at_path(String8 path);
internal B32 copy_file_path(String8 dst, String8 src); internal B32 copy_file_path(String8 dst, String8 src);
internal B32 move_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 String8 full_path_from_path(Arena *arena, String8 path);
internal B32 file_path_exists(String8 path); internal B32 file_path_exists(String8 path);
internal B32 folder_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 FileMap file_map_open(AccessFlags flags, File file);
internal void file_map_close(FileMap map); internal void file_map_close(FileMap map);
internal void * file_map_view_open(FileMap map, AccessFlags flags, Rng1U64 range); 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); internal void file_map_view_close(FileMap map, void *ptr, Rng1U64 range);
//- rjf: directory iteration //- rjf: directory iteration
+1 -5
View File
@@ -4,11 +4,7 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals/Thread-Locals //~ rjf: Globals/Thread-Locals
C_LINKAGE thread_static Log *log_active; thread_static Log *log_active;
#if !BUILD_SUPPLEMENTARY_UNIT
C_LINKAGE thread_static Log *log_active = 0;
#endif
String8 g_logs_folder; String8 g_logs_folder;
//////////////////////////////// ////////////////////////////////
+1
View File
@@ -40,6 +40,7 @@ struct Log
// Globals // Globals
extern String8 g_logs_folder; extern String8 g_logs_folder;
extern thread_static Log *log_active;
//////////////////////////////// ////////////////////////////////
//~ rjf: Log Creation/Selection //~ rjf: Log Creation/Selection
+14
View File
@@ -13,6 +13,20 @@ internal B32 commit_memory(void *ptr, U64 size);
internal void decommit_memory(void *ptr, U64 size); internal void decommit_memory(void *ptr, U64 size);
internal void release_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 //- rjf: large pages
internal void *reserve_memory_large(U64 size); internal void *reserve_memory_large(U64 size);
internal B32 commit_memory_large(void *ptr, U64 size); internal B32 commit_memory_large(void *ptr, U64 size);
+1 -1
View File
@@ -10,7 +10,7 @@ memory_map_push(Arena *arena, MemoryMap *map, Rng1U64 vaddr_range, void *data)
MemoryMapRangeNode *n = push_array(arena, MemoryMapRangeNode, 1); MemoryMapRangeNode *n = push_array(arena, MemoryMapRangeNode, 1);
n->v.vaddr_range = vaddr_range; n->v.vaddr_range = vaddr_range;
n->v.base = data; n->v.base = data;
SLLQueuePush(map->first_range, map->last_range, n); SLLQueuePushFront(map->first_range, map->last_range, n);
} }
internal U64 internal U64
+15
View File
@@ -25,6 +25,12 @@ struct Process
U64 u64[1]; U64 u64[1];
}; };
typedef struct ProcessGroup ProcessGroup;
struct ProcessGroup
{
U64 u64[1];
};
typedef struct ProcessNode ProcessNode; typedef struct ProcessNode ProcessNode;
struct ProcessNode struct ProcessNode
{ {
@@ -49,6 +55,8 @@ struct ProcessLaunchParams
B32 inherit_env; B32 inherit_env;
B32 debug_subprocesses; B32 debug_subprocesses;
B32 consoleless; B32 consoleless;
B32 new_console;
ProcessGroup process_group;
File stdout_file; File stdout_file;
File stderr_file; File stderr_file;
File stdin_file; File stdin_file;
@@ -84,8 +92,15 @@ internal U32 get_process_start_time_unix(void);
internal Process process_launch(ProcessLaunchParams *params); internal Process process_launch(ProcessLaunchParams *params);
internal U64 pid_from_process(Process process); 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 B32 process_join(Process process, U64 endt_us, U64 *exit_code_out);
internal void process_detach(Process process); internal void process_detach(Process process);
internal B32 process_kill(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 #endif // BASE_PROCESSES_H
+5 -5
View File
@@ -8,22 +8,22 @@ spall_begin(char *fmt, ...)
if(spall_buffer.data == 0) if(spall_buffer.data == 0)
{ {
spall_buffer.length = MB(1); spall_buffer.length = MB(1);
spall_buffer.data = os_reserve(spall_buffer.length); spall_buffer.data = reserve_memory(spall_buffer.length);
os_commit(spall_buffer.data, spall_buffer.length); commit_memory(spall_buffer.data, spall_buffer.length);
spall_buffer_init(&spall_profile, &spall_buffer); spall_buffer_init(&spall_profile, &spall_buffer);
} }
if(spall_pid == 0) if(spall_pid == 0)
{ {
spall_pid = os_get_process_info()->pid; spall_pid = get_process_info()->pid;
} }
if(spall_tid == 0) if(spall_tid == 0)
{ {
spall_tid = os_tid(); spall_tid = tid();
} }
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
va_list args; va_list args;
va_start(args, fmt); 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); spall_buffer_begin_ex(&spall_profile, &spall_buffer, string.str, string.size, now_time_us(), spall_tid, spall_pid);
va_end(args); va_end(args);
scratch_end(scratch); scratch_end(scratch);
-4
View File
@@ -46,22 +46,18 @@ ring_try_read(Ring *ring, U64 size, void *ptr)
internal GuardedRing * internal GuardedRing *
guarded_ring_alloc(Arena *arena, U64 size) guarded_ring_alloc(Arena *arena, U64 size)
{ {
ProfBeginFunction();
GuardedRing *gr = push_array(arena, GuardedRing, 1); GuardedRing *gr = push_array(arena, GuardedRing, 1);
gr->ring = make_ring(arena, size); gr->ring = make_ring(arena, size);
gr->mutex = mutex_alloc(); gr->mutex = mutex_alloc();
gr->cv = cond_var_alloc(); gr->cv = cond_var_alloc();
ProfEnd();
return gr; return gr;
} }
internal void internal void
guarded_ring_release(GuardedRing *ring) guarded_ring_release(GuardedRing *ring)
{ {
ProfBeginFunction();
mutex_release(ring->mutex); mutex_release(ring->mutex);
cond_var_release(ring->cv); cond_var_release(ring->cv);
ProfEnd();
} }
internal RingGuard internal RingGuard
+1
View File
@@ -18,5 +18,6 @@ internal SharedMemory shared_memory_open(String8 name);
internal void shared_memory_close(SharedMemory handle); internal void shared_memory_close(SharedMemory handle);
internal void * shared_memory_view_open(SharedMemory handle, Rng1U64 range); 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_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 #endif // BASE_SHARED_MEMORY_H
+10 -10
View File
@@ -196,7 +196,7 @@ str32_zero(void)
} }
internal String8 internal String8
str8_cstring(char *c) str8_cstring(const char *c)
{ {
String8 result = {(U8*)c, cstring8_length((U8*)c)}; String8 result = {(U8*)c, cstring8_length((U8*)c)};
return result; 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) if(dst.size != 0 && dst_style == PathStyle_Relative)
{ {
Temp scratch = scratch_begin(&arena, 1); 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); 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); 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); 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->data1 = (U32)data1;
guid_out->data2 = (U16)data2; guid_out->data2 = (U16)data2;
guid_out->data3 = (U16)data3; 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)); MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4));
is_parsed = 1; is_parsed = 1;
} }
@@ -3076,38 +3076,38 @@ 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) str8_compar(String8 a, String8 b, B32 ignore_case)
{ {
U64 size = Min(a.size, b.size); U64 size = Min(a.size, b.size);
int cmp = ignore_case ? MemCompareI(a.str, b.str, size) : MemCompare(a.str, b.str, size); int cmp = ignore_case ? MemCompareI(a.str, b.str, size) : MemCompare(a.str, b.str, size);
// normalize compar result // normalize compar result
cmp = cmp > 0 ? 1 : cmp < 0 ? -1 : 0; cmp = cmp > 0 ? 1 : cmp < 0 ? -1 : 0;
// shorter prefix must precede longer prefixes // shorter prefix must precede longer prefixes
if (cmp == 0) if (cmp == 0)
{ {
cmp = a.size < b.size ? -1 : cmp = a.size < b.size ? -1 :
a.size > b.size ? +1 : 0; a.size > b.size ? +1 : 0;
} }
return cmp; return cmp;
} }
force_inline int internal force_inline int
str8_compar_ignore_case(const void *a, const void *b) str8_compar_ignore_case(const void *a, const void *b)
{ {
return str8_compar(*(String8*)a, *(String8*)b, 1); 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) str8_compar_case_sensitive(const void *a, const void *b)
{ {
return str8_compar(*(String8*)a, *(String8*)b, 0); 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) str8_is_before_case_sensitive(const void *a, const void *b)
{ {
int cmp = str8_compar_case_sensitive(a, b); int cmp = str8_compar_case_sensitive(a, b);
+3 -1
View File
@@ -180,7 +180,7 @@ internal String16 str16_zero(void);
internal String32 str32(U32 *str, U64 size); internal String32 str32(U32 *str, U64 size);
internal String32 str32_range(U32 *first, U32 *one_past_last); internal String32 str32_range(U32 *first, U32 *one_past_last);
internal String32 str32_zero(void); 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 String16 str16_cstring(U16 *c);
internal String32 str32_cstring(U32 *c); internal String32 str32_cstring(U32 *c);
internal String8 str8_cstring_capped(void *cstr, void *cap); 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__) #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. 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 //~ rjf: String <=> Integer Conversions
+1
View File
@@ -11,6 +11,7 @@ struct SystemInfo
U64 page_size; U64 page_size;
U64 large_page_size; U64 large_page_size;
U64 allocation_granularity; U64 allocation_granularity;
U64 physical_memory_size;
String8 machine_name; String8 machine_name;
}; };
+13 -6
View File
@@ -32,16 +32,23 @@ test_exemplar_path(Arena *arena, TestCtx *ctx, String8 name)
return path; 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 internal void
base_register_test(char *func_name_cstr, TestFunctionType *fn, char *file_path_cstr, int line, int skip) 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); 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++]; 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->label = str8_cstring(func_name_cstr);
t->decl_line = line; t->decl_line = line;
t->skip = skip; t->skip = skip;
+3
View File
@@ -30,6 +30,7 @@ struct TestCtx
String8 exemplars_path; String8 exemplars_path;
String8 artifacts_path; String8 artifacts_path;
String8 input_data_path; String8 input_data_path;
String8 user_data;
TestResult *result_out; TestResult *result_out;
String8List *test_out; String8List *test_out;
}; };
@@ -46,6 +47,7 @@ struct TestInfo
S64 decl_line; S64 decl_line;
B32 skip; B32 skip;
TestFunctionType *test_fn; TestFunctionType *test_fn;
String8 user_data;
}; };
#if BUILD_TESTS #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_path(Arena *arena, TestCtx *ctx, String8 name);
internal String8 test_input_exe_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_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); internal void base_register_test(char *func_name, TestFunctionType *fn, char *file_path, int line, int skip);
#define AddTest(name, file_path, line, skip_, ...) \ #define AddTest(name, file_path, line, skip_, ...) \
+1 -4
View File
@@ -4,10 +4,7 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals //~ rjf: Globals
C_LINKAGE thread_static TCTX *tctx_thread_local; thread_static TCTX *tctx_thread_local;
#if !BUILD_SUPPLEMENTARY_UNIT
C_LINKAGE thread_static TCTX *tctx_thread_local = 0;
#endif
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Context Functions //~ rjf: Thread Context Functions
+5
View File
@@ -79,6 +79,11 @@ struct TCTX
U64 *progress_target_ptr; U64 *progress_target_ptr;
}; };
////////////////////////////////
// Globals
extern thread_static TCTX *tctx_thread_local;
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Context Functions //~ rjf: Thread Context Functions
+11
View File
@@ -102,6 +102,17 @@ TEST(count_digits)
T_Ok(count_digits_u64(999999, 10) == 6); 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) TEST(match_wildcard)
{ {
// empty strings // empty strings
-1
View File
@@ -131,7 +131,6 @@ cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg)
return r; return r;
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Enum -> String //~ rjf: Enum -> String
+1 -1
View File
@@ -1161,7 +1161,7 @@ struct CV_SymPub32
//- (SymKind: LPROC32, GPROC32) //- (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; typedef struct CV_SymProc32 CV_SymProc32;
struct CV_SymProc32 struct CV_SymProc32
+4 -1
View File
@@ -291,7 +291,9 @@ cv_c13_inline_site_decoder_step(CV_C13InlineSiteDecoder *decoder, String8 binary
} break; } break;
case CV_InlineBinaryAnnotation_CodeOffset: { case CV_InlineBinaryAnnotation_CodeOffset: {
decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_offset); decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_offset);
decoder->code_offset_changed = 1; decoder->code_offset_lo = decoder->code_offset;
decoder->code_offset_lo_changed = 1;
decoder->code_offset_changed = 1;
} break; } break;
case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: { case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: {
AssertAlways(!"TODO: test case"); AssertAlways(!"TODO: test case");
@@ -948,6 +950,7 @@ cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data
case CV_LeafKind_NESTTYPEEX: { case CV_LeafKind_NESTTYPEEX: {
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestTypeEx, itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestTypeEx, itype));
} break; } break;
case CV_LeafKind_ENDPRECOMP: {} break;
default: { default: {
NotImplemented; NotImplemented;
} break; } break;
+35 -5
View File
@@ -55,11 +55,41 @@ internal String8
coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header) coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header)
{ {
String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name)); String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name));
if (name.str[0] == '/') {
String8 name_off_str = str8_skip(name, 1); if (name.size > 0 && name.str[0] == '/') {
U64 name_off = u64_from_str8(name_off_str, 10); U64 name_off = max_U64;
name = str8_cstring_capped(string_table.str + name_off, string_table.str+string_table.size);
// 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; 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)); reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5));
} break; } break;
case COFF_Reloc_X64_Section: { case COFF_Reloc_X64_Section: {
reloc_value_size = 4; reloc_value_size = 2;
reloc_value = symbol_section_number; reloc_value = symbol_section_number;
} break; } break;
case COFF_Reloc_X64_SecRel: { case COFF_Reloc_X64_SecRel: {
+2 -2
View File
@@ -149,13 +149,13 @@ coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine
imp_symbol.member_idx = member_idx; imp_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol); coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
} break; } break;
case COFF_ImportHeader_Data: { case COFF_ImportHeader_Data:
case COFF_ImportHeader_Const: {
COFF_LibWriterSymbol imp_symbol = {0}; COFF_LibWriterSymbol imp_symbol = {0};
imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name); imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name);
imp_symbol.member_idx = member_idx; imp_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol); coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
} break; } break;
case COFF_ImportHeader_Const: { NotImplemented; } break;
default: { InvalidPath; } break; default: { InvalidPath; } break;
} }
} }
+71 -42
View File
@@ -26,28 +26,32 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
String8List srl = {0}; String8List srl = {0};
String8List string_table = {0}; String8List string_table = {0};
U32 *string_table_size = push_array(scratch.arena, U32, 1); U32 *string_table_size = push_array(scratch.arena, U32, 1);
*string_table_size = sizeof(*string_table_size); *string_table_size = sizeof(*string_table_size);
str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size)); str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size));
// //
// assing section numbers // assign section numbers
// //
U64 obj_sections_count; U64 obj_sections_count;
COFF_ObjSection **obj_sections; COFF_ObjSection **obj_sections;
{ {
obj_sections_count = obj_writer->sect_count; 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); obj_sections = push_array(scratch.arena, COFF_ObjSection *, obj_writer->sect_count);
U64 sect_idx = 0; 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 = &sect_n->v; COFF_ObjSection *sect = &sect_n->v;
sect->section_number = sect_idx+1; sect->section_number = sect_idx+1;
obj_sections[sect_idx] = sect; 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 // serialize symbol table
@@ -56,7 +60,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
{ {
{ {
U64 symbol_idx = 0; 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_ObjSymbol *s = &symbol_n->v;
// assign symbol index // assign symbol index
@@ -66,12 +70,9 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
} }
U64 symbol_idx = 0; 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_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}; COFF_SymbolName name = {0};
// long name // long name
if (s->name.size > sizeof(name.short_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 // symbol header
AssertAlways(s->aux_symbols.node_count <= max_U8); AssertAlways(s->aux_symbols.node_count <= max_U8);
d->name = name; U32 section_number = 0;
d->value = s->value;
switch (s->loc.type) { switch (s->loc.type) {
case COFF_SymbolLocation_Null: break; 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_Section: section_number = s->loc.u.section->section_number; break;
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break; case COFF_SymbolLocation_Abs: section_number = is_big_obj ? COFF_Symbol_AbsSection32 : COFF_Symbol_AbsSection16; break;
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break; case COFF_SymbolLocation_Undef: section_number = COFF_Symbol_UndefinedSection; break;
case COFF_SymbolLocation_Common: d->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 = (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));
} }
d->type = s->type;
d->storage_class = s->storage_class;
d->aux_symbol_count = 0;
U64 start_symbol_idx = symbol_idx; U64 start_symbol_idx = symbol_idx;
if (s->storage_class == COFF_SymStorageClass_WeakExternal) { if (s->storage_class == COFF_SymStorageClass_WeakExternal) {
if (s->aux_symbols.node_count > 0) { if (s->aux_symbols.node_count > 0) {
COFF_ObjSymbolWeak *s_weak = (COFF_ObjSymbolWeak *)s->aux_symbols.first->string.str; 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->tag_index = s_weak->tag ? s_weak->tag->idx : max_U32;
d_weak->characteristics = s_weak->characteristics; 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; symbol_idx += 1;
} }
} else if (s->storage_class == COFF_SymStorageClass_Static) { } 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_ObjSection *sect = s->loc.u.section;
COFF_ObjSymbolSecDef *s_sd = (COFF_ObjSymbolSecDef *)s->aux_symbols.first->string.str; 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->length = safe_cast_u32(sect->data.total_size);
d_sd->number_of_relocations = (U16)sect->reloc_count; d_sd->number_of_relocations = (U16)sect->reloc_count;
d_sd->check_sum = 0; 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; 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; 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); 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) { 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); U8 *a = push_array(scratch.arena, U8, symbol_size);
str8_list_push(scratch.arena, &symbol_table, str8_struct(a)); str8_list_push(scratch.arena, &symbol_table, str8(a, symbol_size));
} }
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
} }
} }
// //
// file header // file header
// //
COFF_FileHeader *file_header = push_array(scratch.arena, COFF_FileHeader, 1); U32 *symbol_table_foff;
file_header->machine = obj_writer->machine; if (is_big_obj) {
file_header->section_count = obj_sections_count; COFF_BigObjHeader *header = push_array(scratch.arena, COFF_BigObjHeader, 1);
file_header->time_stamp = obj_writer->time_stamp; header->sig1 = COFF_MachineType_Unknown;
file_header->symbol_table_foff = 0; header->sig2 = max_U16;
file_header->symbol_count = safe_cast_u32(symbol_table.node_count); header->version = 2;
file_header->optional_header_size = 0; header->machine = obj_writer->machine;
file_header->flags = 0; header->time_stamp = obj_writer->time_stamp;
str8_list_push(scratch.arena, &srl, str8_struct(file_header)); 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 // 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); COFF_SectionHeader *sectab = push_array(scratch.arena, COFF_SectionHeader, obj_sections_count);
str8_list_push(scratch.arena, &srl, str8_array(sectab, 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_ObjSection *s = obj_sections[sect_idx];
COFF_SectionHeader *d = &sectab[sect_idx]; COFF_SectionHeader *d = &sectab[sect_idx];
@@ -179,7 +208,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
} }
// alloc zero nodes // 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) { 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); 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); AssertAlways(s->reloc_count <= max_U16);
COFF_Reloc *relocs = push_array(scratch.arena, COFF_Reloc, s->reloc_count); COFF_Reloc *relocs = push_array(scratch.arena, COFF_Reloc, s->reloc_count);
U64 reloc_idx = 0; 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_ObjReloc *rs = &reloc_n->v;
COFF_Reloc *rd = &relocs[reloc_idx]; COFF_Reloc *rd = &relocs[reloc_idx++];
rd->apply_off = rs->apply_off; rd->apply_off = rs->apply_off;
rd->isymbol = rs->symbol->idx; rd->isymbol = rs->symbol->idx;
rd->type = rs->type; rd->type = rs->type;
@@ -230,7 +259,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
// symbol table // symbol table
// //
if (symbol_table.total_size || string_table.total_size > sizeof(*string_table_size)) { 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); str8_list_concat_in_place(&srl, &symbol_table);
} }
+43 -43
View File
@@ -166,20 +166,20 @@ coff_section_header_array_from_name(Arena *arena, String8 string_table, COFF_Sec
} }
internal COFF_ParsedSymbol internal COFF_ParsedSymbol
coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32) coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
{ {
COFF_ParsedSymbol result = coff_parse_symbol32_no_name(sym32); COFF_ParsedSymbol result = coff_parse_symbol32_no_name(sym32);
result.name = coff_read_symbol_name(string_table, &sym32->name); result.name = coff_read_symbol_name(string_table, &sym32->name);
return result; return result;
} }
internal force_inline COFF_ParsedSymbol internal force_inline COFF_ParsedSymbol
coff_parse_symbol32_no_name(COFF_Symbol32 *sym32) coff_parse_symbol32_no_name(COFF_Symbol32 *sym32)
{ {
COFF_ParsedSymbol result = {0}; COFF_ParsedSymbol result = {0};
result.value = sym32->value; result.value = sym32->value;
result.section_number = sym32->section_number; result.section_number = sym32->section_number;
result.type = sym32->type; result.type = sym32->type;
result.storage_class = sym32->storage_class; result.storage_class = sym32->storage_class;
result.aux_symbol_count = sym32->aux_symbol_count; result.aux_symbol_count = sym32->aux_symbol_count;
@@ -187,19 +187,19 @@ coff_parse_symbol32_no_name(COFF_Symbol32 *sym32)
return result; return result;
} }
internal COFF_ParsedSymbol internal COFF_ParsedSymbol
coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16) coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16)
{ {
COFF_ParsedSymbol result = coff_parse_symbol16_no_name(sym16); COFF_ParsedSymbol result = coff_parse_symbol16_no_name(sym16);
result.name = coff_read_symbol_name(string_table, &sym16->name); result.name = coff_read_symbol_name(string_table, &sym16->name);
return result; return result;
} }
internal force_inline COFF_ParsedSymbol internal force_inline COFF_ParsedSymbol
coff_parse_symbol16_no_name(COFF_Symbol16 *sym16) coff_parse_symbol16_no_name(COFF_Symbol16 *sym16)
{ {
COFF_ParsedSymbol result = {0}; COFF_ParsedSymbol result = {0};
result.value = sym16->value; result.value = sym16->value;
if (sym16->section_number == COFF_Symbol_DebugSection16) { if (sym16->section_number == COFF_Symbol_DebugSection16) {
result.section_number = COFF_Symbol_DebugSection32; result.section_number = COFF_Symbol_DebugSection32;
} else if (sym16->section_number == COFF_Symbol_AbsSection16) { } else if (sym16->section_number == COFF_Symbol_AbsSection16) {
@@ -214,8 +214,8 @@ coff_parse_symbol16_no_name(COFF_Symbol16 *sym16)
return result; return result;
} }
internal COFF_ParsedSymbol internal COFF_ParsedSymbol
coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx) coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx)
{ {
COFF_ParsedSymbol symbol; COFF_ParsedSymbol symbol;
if (header.is_big_obj) { if (header.is_big_obj) {
@@ -223,20 +223,20 @@ coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symb
} else { } else {
symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx); symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx);
} }
return symbol; return symbol;
} }
internal force_inline COFF_ParsedSymbol internal force_inline COFF_ParsedSymbol
coff_parse_symbol_no_name(COFF_FileHeaderInfo header, String8 symbol_table, U32 symbol_idx) coff_parse_symbol_no_name(COFF_FileHeaderInfo header, String8 symbol_table, U32 symbol_idx)
{ {
COFF_ParsedSymbol symbol; COFF_ParsedSymbol symbol;
if (header.is_big_obj) { if (header.is_big_obj) {
symbol = coff_parse_symbol32_no_name((COFF_Symbol32 *)symbol_table.str + symbol_idx); symbol = coff_parse_symbol32_no_name((COFF_Symbol32 *)symbol_table.str + symbol_idx);
} else { } else {
symbol = coff_parse_symbol16_no_name((COFF_Symbol16 *)symbol_table.str + symbol_idx); symbol = coff_parse_symbol16_no_name((COFF_Symbol16 *)symbol_table.str + symbol_idx);
} }
return symbol; return symbol;
} }
internal COFF_Symbol32Array internal COFF_Symbol32Array
coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count) coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count)
+1 -1
View File
@@ -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, exe_name);
str8_list_push(scratch.arena, &command_parts, s("--cli")); 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]); String8 arg = str8_cstring(cmd_line->argv[idx]);
str8_list_push(scratch.arena, &command_parts, arg); str8_list_push(scratch.arena, &command_parts, arg);
+23 -10
View File
@@ -184,19 +184,19 @@ cfg_node_from_id(CFG_ID id)
} }
else else
{ {
U64 hash = u64_hash_from_str8(str8_struct(&id)); U64 hash = id;
U64 slot_idx = hash%cfg_ctx->id_slots_count; 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) for(CFG_NodePtrNode *n = cfg_ctx->id_slots[slot_idx].first; n != 0; n = n->next)
{ {
if(n->v->id == id) if(n->v->id == id)
{ {
result = n->v; result = n->v;
cfg_ctx->last_accessed_id = id;
cfg_ctx->last_accessed = result;
break; break;
} }
} }
} }
cfg_ctx->last_accessed_id = id;
cfg_ctx->last_accessed = result;
return result; return result;
} }
@@ -619,7 +619,7 @@ cfg_node_alloc(CFG_State *state)
{ {
cfg_id_node = push_array(state->arena, CFG_NodePtrNode, 1); 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; 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); DLLPushBack(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, cfg_id_node);
cfg_id_node->v = result; cfg_id_node->v = result;
@@ -632,7 +632,6 @@ internal void
cfg_node_release(CFG_State *state, CFG_Node *node) cfg_node_release(CFG_State *state, CFG_Node *node)
{ {
state->ctx.change_gen += 1; state->ctx.change_gen += 1;
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
// rjf: unhook from context // rjf: unhook from context
@@ -648,23 +647,37 @@ cfg_node_release(CFG_State *state, CFG_Node *node)
// rjf: release all nodes // rjf: release all nodes
for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next) for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next)
{ {
// rjf: unpack node
CFG_Node *c = n->v; 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; U64 slot_idx = hash%state->ctx.id_slots_count;
// rjf: release string, recycle node
cfg_string_release(state, c->string); cfg_string_release(state, c->string);
SLLStackPush(state->free, c); SLLStackPush(state->free, c);
// rjf: zero node's contents
c->first = c->last = c->prev = c->parent = 0; c->first = c->last = c->prev = c->parent = 0;
c->id = 0; c->id = 0;
c->string = str8_zero(); 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); DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, id_n);
SLLStackPush(state->free_id_node, n); SLLStackPush(state->free_id_node, id_n);
break; 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); scratch_end(scratch);
+52 -39
View File
@@ -7,7 +7,7 @@ cfg_window_from_cfg(CFG_Node *cfg)
CFG_Node *result = &cfg_nil_node; CFG_Node *result = &cfg_nil_node;
for(CFG_Node *c = cfg; c != &cfg_nil_node; c = c->parent) 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; result = c;
break; break;
@@ -21,56 +21,69 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
CFG_Node *wcfg = cfg_window_from_cfg(cfg_root); 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_root = &cfg_nil_panel_node;
CFG_PanelNode *dst_focused = &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_NodeRec rec = {0};
CFG_PanelNode *dst_active_parent = &cfg_nil_panel_node; CFG_PanelNode *dst_active_parent = &cfg_nil_panel_node;
for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next) for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next)
{ {
// rjf: build a panel node // rjf: unpack this config string
CFG_PanelNode *dst = push_array(arena, CFG_PanelNode, 1); MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src->string);
MemoryCopyStruct(dst, &cfg_nil_panel_node);
dst->parent = dst_active_parent;
if(dst_active_parent != &cfg_nil_panel_node)
{
DLLPushBack_NPZ(&cfg_nil_panel_node, dst_active_parent->first, dst_active_parent->last, dst, next, prev);
dst_active_parent->child_count += 1;
}
if(dst_root == &cfg_nil_panel_node)
{
dst_root = dst;
}
// rjf: extract cfg info // rjf: build a panel node if this is a child panel
CFG_PanelNode *dst = &cfg_nil_panel_node;
B32 panel_has_children = 0; B32 panel_has_children = 0;
dst->cfg = src; if(src == src_root || (tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric))
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->split_axis = active_split_axis;
for(CFG_Node *src_child = src->first; src_child != &cfg_nil_node; src_child = src_child->next)
{ {
MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_child->string); // rjf: allocate
if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric) 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)
{ {
panel_has_children = 1; DLLPushBack_NPZ(&cfg_nil_panel_node, dst_active_parent->first, dst_active_parent->last, dst, next, prev);
dst_active_parent->child_count += 1;
} }
else if(str8_match(src_child->string, str8_lit("tabs_on_bottom"), 0)) if(dst_root == &cfg_nil_panel_node)
{ {
// NOTE(rjf): skip - this is a panel option. dst_root = dst;
} }
else if(str8_match(src_child->string, str8_lit("selected"), 0))
// rjf: extract cfg info
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, 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)
{ {
dst_focused = dst; MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_child->string);
} if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric)
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)
{ {
dst->selected_tab = src_child; panel_has_children = 1;
}
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, 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, s("selected")) != &cfg_nil_node)
{
dst->selected_tab = src_child;
}
} }
} }
} }
@@ -103,7 +116,7 @@ cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root)
} }
} }
scratch_end(scratch); scratch_end(scratch);
CFG_PanelTree tree = {dst_root, dst_focused}; CFG_PanelTree tree = {dst_root, dst_focused, dst_zoom_root};
return tree; return tree;
} }
@@ -179,7 +192,7 @@ cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_Pane
// rjf: count ancestors // rjf: count ancestors
U64 ancestor_count = 0; 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; 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); CFG_PanelNode **ancestors = push_array(scratch.arena, CFG_PanelNode *, ancestor_count);
{ {
U64 ancestor_idx = 0; 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; ancestors[ancestor_idx] = p;
ancestor_idx += 1; 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 *ancestor = ancestors[ancestor_idx];
CFG_PanelNode *parent = ancestor->parent; 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); parent_rect = cfg_target_rect_from_panel_node_child(parent_rect, parent, ancestor);
} }
+1
View File
@@ -33,6 +33,7 @@ struct CFG_PanelTree
{ {
CFG_PanelNode *root; CFG_PanelNode *root;
CFG_PanelNode *focused; CFG_PanelNode *focused;
CFG_PanelNode *zoom_root;
}; };
typedef struct CFG_PanelNodeRec CFG_PanelNodeRec; typedef struct CFG_PanelNodeRec CFG_PanelNodeRec;
+1 -1
View File
@@ -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 // rjf: key is new -> add this key to the associated root
if(key_is_new) 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_slot_idx = root_hash%c_shared->root_slots_count;
U64 root_stripe_idx = root_slot_idx%c_shared->root_stripes_count; U64 root_stripe_idx = root_slot_idx%c_shared->root_stripes_count;
C_RootSlot *root_slot = &c_shared->root_slots[root_slot_idx]; C_RootSlot *root_slot = &c_shared->root_slots[root_slot_idx];
+27 -129
View File
@@ -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." "" "" } {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." "" "" } {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." "" "" } {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." "" "" } {FreezeServer 0 1 "query:servers" Server 0 0 0 0 0 1 1 Locked "freeze_server " "Freeze Server " "Freezes the passed server." "" "" }
{ThawMachine 0 1 "query:machines" Machine 0 0 0 0 0 1 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" "" } {ThawServer 0 1 "query:servers" Server 0 0 0 0 0 1 1 Unlocked "thaw_server" "Thaw Server" "Thaws the passed server." "" "" }
{FreezeLocalMachine 1 1 "" Null 0 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" "" } {FreezeLocalServer 1 1 "" Null 0 0 0 0 0 0 0 Machine "freeze_local_server" "Freeze Local Server" "Freezes the local server." "" "" }
{ThawLocalMachine 1 1 "" Null 0 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" "" } {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." "" "" } {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." "" "" } {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." "" "" } {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 //- 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: @enum D_CmdKind:
@@ -104,7 +108,7 @@ D_DevToggleTable:
D_EntityKindTable: D_EntityKindTable:
{ {
{Root root "Root" } {Root root "Root" }
{Machine machine "Machine" } {Server server "Server" }
{Process process "Process" } {Process process "Process" }
{Thread thread "Thread" } {Thread thread "Thread" }
{Module module "Module" } {Module module "Module" }
@@ -139,151 +143,45 @@ D_EntityKindTable:
//////////////////////////////// ////////////////////////////////
//~ rjf: Exception Codes //~ 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: @enum D_ExceptionCodeKind:
{ {
Null, Null,
@expand(D_ExceptionCodeKindTable a) `$(a.name)`, @expand(W32_ExceptionCodeKindTable a) `Win32$(a.name)`,
@expand(LNX_SignalCodeTable a) `Linux$(a.name)`,
COUNT, COUNT,
} }
@data(U32) d_exception_code_kind_code_table: @data(U32) d_exception_code_kind_code_table:
{ {
`0`; `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: @data(String8) d_exception_code_kind_display_string_table:
{ {
`{0}`; `{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: @data(String8) d_exception_code_kind_lowercase_code_string_table:
{ {
`{0}`; `{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: @data(B8) d_exception_code_kind_default_enable_table:
{ {
`0`; `0`;
@expand(D_ExceptionCodeKindTable a) `$(a.default)`; @expand(W32_ExceptionCodeKindTable a) `$(a.default)`;
} @expand(LNX_SignalCodeTable a) `$(a.break_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 }
} }
+101 -1
View File
@@ -6,6 +6,93 @@
#include "generated/dbg_engine.meta.c" #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 //~ rjf: Layer Initialization
@@ -17,6 +104,7 @@ d_init(void)
Arena *arena = arena_alloc(); Arena *arena = arena_alloc();
d_ctrl_state = push_array(arena, D_CtrlState, 1); d_ctrl_state = push_array(arena, D_CtrlState, 1);
d_ctrl_state->arena = arena; d_ctrl_state->arena = arena;
d_ctrl_state->sock_session = sock_session_open(0, d_ctrl_sock_wakeup);
for EachEnumVal(Arch, arch) for EachEnumVal(Arch, arch)
{ {
ARCH_Info *arch_info = arch_info_from_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_entity_store = d_entity_ctx_rw_store_alloc();
d_ctrl_state->ctrl_thread_eval_cache = e_cache_alloc(); d_ctrl_state->ctrl_thread_eval_cache = e_cache_alloc();
d_ctrl_state->ctrl_thread_msg_process_arena = arena_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(); d_ctrl_state->dmn_event_arena = arena_alloc();
#endif
d_ctrl_state->user_entry_point_arena = arena_alloc(); 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)) 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]) if(d_exception_code_kind_default_enable_table[k])
+28 -6
View File
@@ -4,11 +4,25 @@
#ifndef DBG_ENGINE_CORE_H #ifndef DBG_ENGINE_CORE_H
#define 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 //~ rjf: ID Types
typedef U64 D_MsgID; typedef U64 D_MsgID;
typedef U32 D_MachineID; typedef U32 D_ServerID;
typedef U32 D_ControllerKind; typedef U32 D_ControllerKind;
typedef enum D_ControllerKindEnum typedef enum D_ControllerKindEnum
{ {
@@ -17,7 +31,7 @@ typedef enum D_ControllerKindEnum
} }
D_ControllerKindEnum; D_ControllerKindEnum;
#define D_MachineID_Local (1) #define D_ServerID_LocalHost (1)
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Handle Types //~ rjf: Entity Handle Types
@@ -25,7 +39,7 @@ D_ControllerKindEnum;
typedef struct D_Handle D_Handle; typedef struct D_Handle D_Handle;
struct D_Handle struct D_Handle
{ {
D_MachineID machine_id; D_ServerID server_id;
D_ControllerKind controller_kind; D_ControllerKind controller_kind;
U64 entity_id; U64 entity_id;
}; };
@@ -63,9 +77,10 @@ struct D_HandleArray
typedef U32 D_BreakpointFlags; typedef U32 D_BreakpointFlags;
enum enum
{ {
D_BreakpointFlag_BreakOnWrite = (1<<0), D_BreakpointFlag_BreakOnWrite = (1<<0),
D_BreakpointFlag_BreakOnRead = (1<<1), D_BreakpointFlag_BreakOnRead = (1<<1),
D_BreakpointFlag_BreakOnExecute = (1<<2), D_BreakpointFlag_BreakOnExecute = (1<<2),
D_BreakpointFlag_BreakSelectedThreadOnly = (1<<3),
}; };
typedef struct D_Breakpoint D_Breakpoint; typedef struct D_Breakpoint D_Breakpoint;
@@ -236,8 +251,10 @@ struct D_Target
String8 stdout_path; String8 stdout_path;
String8 stderr_path; String8 stderr_path;
String8 stdin_path; String8 stdin_path;
String8 remote_address;
D_MsgID msg_id; D_MsgID msg_id;
B32 debug_subprocesses; B32 debug_subprocesses;
B32 deploy;
String8List env; String8List env;
}; };
@@ -318,6 +335,11 @@ struct D_TrapNet
B32 good_read; B32 good_read;
}; };
////////////////////////////////
//~ rjf: @eval2 Bundled Evaluation Path
internal D_Eval d_eval_from_string(Arena *arena, String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Layer Initialization //~ rjf: Layer Initialization
File diff suppressed because it is too large. Load diff
+68 -10
View File
@@ -218,6 +218,7 @@ struct D_DumpThread
D_Handle thread_handle; D_Handle thread_handle;
U32 id; U32 id;
U64 context_foff; U64 context_foff;
String8 name;
}; };
typedef struct D_DumpModule D_DumpModule; typedef struct D_DumpModule D_DumpModule;
@@ -312,6 +313,45 @@ struct D_ModuleReqCacheNode
#define D_WAKEUP_FUNCTION_DEF(name) void name(void) #define D_WAKEUP_FUNCTION_DEF(name) void name(void)
typedef D_WAKEUP_FUNCTION_DEF(D_WakeupFunctionType); 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 //~ rjf: Main State Types
@@ -320,11 +360,12 @@ struct D_CtrlState
{ {
Arena *arena; Arena *arena;
D_WakeupFunctionType *wakeup_hook; D_WakeupFunctionType *wakeup_hook;
SOCK_Session sock_session;
// rjf: name -> register hash tables for eval // rjf: name -> register hash tables for eval
E_String2NumMap arch_string2reg_tables[Arch_COUNT]; E_String2NumMap arch_string2reg_tables[Arch_COUNT];
// rjf: caches // rjf: shared caches
D_ThreadRegCache thread_reg_cache; D_ThreadRegCache thread_reg_cache;
D_ModuleInfoCache module_info_cache; D_ModuleInfoCache module_info_cache;
D_DumpCache dump_cache; D_DumpCache dump_cache;
@@ -361,17 +402,24 @@ struct D_CtrlState
D_EntityCtxRWStore *ctrl_thread_entity_store; D_EntityCtxRWStore *ctrl_thread_entity_store;
E_Cache *ctrl_thread_eval_cache; E_Cache *ctrl_thread_eval_cache;
Arena *ctrl_thread_msg_process_arena; 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; Arena *dmn_event_arena;
DMN_EventNode *first_dmn_event_node; DMN_EventNode *first_dmn_event_node;
DMN_EventNode *last_dmn_event_node; DMN_EventNode *last_dmn_event_node;
DMN_EventNode *free_dmn_event_node; DMN_EventNode *free_dmn_event_node;
#endif
Arena *user_entry_point_arena; Arena *user_entry_point_arena;
String8List user_entry_points; String8List user_entry_points;
U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64]; U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64];
B32 auto_download_debug_info; B32 auto_download_debug_info;
U64 process_counter; D_ServerID server_id_gen;
Arena *dbg_dir_arena;
D_DbgDirNode *dbg_dir_root;
U64 module_req_cache_slots_count; U64 module_req_cache_slots_count;
D_ModuleReqCacheNode **module_req_cache_slots; D_ModuleReqCacheNode **module_req_cache_slots;
String8List msg_user_bp_touched_files; 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 String8 d_string_from_handle(Arena *arena, D_Handle handle);
internal D_Handle d_handle_from_string(String8 string); internal D_Handle d_handle_from_string(String8 string);
internal DMN_Handle d_dmn_from_handle(D_Handle handle); 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_handle_from_dmn(D_ServerID server_id, DMN_Handle handle);
internal D_Handle d_dump_handle_make(D_MachineID machine_id, U64 id); internal D_Handle d_dump_handle_make(D_ServerID server_id, U64 id);
//////////////////////////////// ////////////////////////////////
//~ rjf: Trap Type Functions //~ 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_process_from_entity(D_Entity *entity);
internal D_Entity *d_module_from_process_vaddr(D_Entity *process, U64 vaddr); 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_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 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_vaddr_from_voff(D_Entity *module, U64 voff);
internal U64 d_voff_from_vaddr(D_Entity *module, U64 vaddr); 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 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 //- rjf: cache lookups
internal D_ModuleInfo *d_info_from_module(Access *access, D_Handle module); 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_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); 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_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); 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 //- rjf: dump process closing work
internal void d_ctrl_thread__close_dump_process(D_MsgID msg_id, D_Handle process); 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 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); 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 //- rjf: log flusher
internal void d_ctrl_thread__end_and_flush_log(void); internal void d_ctrl_thread__end_and_flush_log(void);
//- rjf: msg kind implementations //- 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__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__attach(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
internal void d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg); internal void d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg);
+100 -63
View File
@@ -53,7 +53,7 @@ d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src)
//~ rjf: Path Map Application //~ rjf: Path Map Application
internal String8List 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 // 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 // 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; PathStyle pth_style = PathStyle_Relative;
String8List pth_parts = path_normalized_list_from_string(scratch.arena, file_path, &pth_style); 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 //- rjf: push possible overrides based on path map rules
{ {
for(U64 idx = 0; idx < path_maps->count; idx += 1) 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); U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr); 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("ip_vaddr: 0x%I64x\n", ip_vaddr);
log_infof("dbgi_key: {0x%I64x, 0x%I64x}\n", dbgi_key.u64[0], dbgi_key.u64[1]); 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}; Rng1U64 line_vaddr_rng = {0};
{ {
U64 ip_voff = d_voff_from_vaddr(module, ip_vaddr); 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}; Rng1U64 line_voff_rng = {0};
if(lines.first != 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. // is enabled. This is enabled by default normally.
{ {
U64 opl_line_voff_rng = d_voff_from_vaddr(module, line_vaddr_rng.max); 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)) 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); 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); U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr); 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 // rjf: ip => line info
String8 file_path = {0}; 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}; Rng1U64 line_vaddr_rng = {0};
{ {
U64 ip_voff = d_voff_from_vaddr(module, ip_vaddr); 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}; Rng1U64 line_voff_rng = {0};
if(lines.first != 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. // is enabled. This is enabled by default normally.
{ {
U64 opl_line_voff_rng = d_voff_from_vaddr(module, line_vaddr_rng.max); 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)) 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); 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; U64 jump_dest_vaddr = point->jump_dest_vaddr;
D_Entity *jump_dest_module = d_module_from_process_vaddr(process, 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); 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_Entity *jump_dest_dbg_path = d_entity_child_from_kind(jump_dest_module, D_EntityKind_DebugInfoPath);
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, jump_dest_dbgi_key, jump_dest_voff); 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) if(lines.count == 0)
{ {
add = 0; add = 0;
@@ -996,7 +988,7 @@ d_trap_net_from_thread__step_to_exit(Arena *arena, D_Entity *thread)
//- rjf: voff -> line info //- rjf: voff -> line info
internal D_LineList 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); Temp scratch = scratch_begin(&arena, 1);
Access *access = access_open(); 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}; StringJoin join = {0};
join.sep = str8_lit("/"); join.sep = str8_lit("/");
String8 file_normalized_full_path = str8_list_join(arena, &path_parts, &join); 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); D_LineNode *n = push_array(arena, D_LineNode, 1);
SLLQueuePush(result.first, result.last, n); SLLQueuePush(result.first, result.last, n);
result.count += 1; 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.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]); 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 // 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") 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_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_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx);
RDI_ParsedSourceLineMap line_map = {0}; 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]); 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; S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num;
D_LineNode *n = push_array(arena, D_LineNode, 1); D_LineNode *n = push_array(arena, D_LineNode, 1);
n->v.file_path = match_file_path;
n->v.voff_range = range; n->v.voff_range = range;
n->v.pt.line = (S64)actual_line; n->v.pt.line = (S64)actual_line;
n->v.pt.column = 1; n->v.pt.column = 1;
@@ -1569,7 +1569,7 @@ d_next_cmd(D_Cmd **cmd)
//~ rjf: Main Layer Top-Level Calls //~ rjf: Main Layer Top-Level Calls
internal D_EventList 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(); ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1); 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 // rjf: build data strings of all param data
String8List strings = {0}; String8List strings = {0};
{ {
str8_list_push(scratch.arena, &strings, str8_struct(&selected_thread));
D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread);
for EachIndex(idx, threads.count) 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) for(U64 idx = 0; idx < breakpoints->count; idx += 1)
{ {
D_Breakpoint *bp = &breakpoints->v[idx]; 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, bp->file_path);
str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt)); str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt));
str8_list_push(scratch.arena, &strings, bp->vaddr_expr); 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 stdout_path = str8_skip_chop_whitespace(target->stdout_path);
String8 stderr_path = str8_skip_chop_whitespace(target->stderr_path); String8 stderr_path = str8_skip_chop_whitespace(target->stderr_path);
String8 stdin_path = str8_skip_chop_whitespace(target->stdin_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; String8List env = target->env;
if(working_directory.size == 0) 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); D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
msg->msg_id = target->msg_id; msg->msg_id = target->msg_id;
msg->kind = D_MsgKind_Launch; msg->kind = D_MsgKind_Launch;
msg->address = str8_copy(scratch.arena, remote_address);
msg->path = str8_copy(scratch.arena, working_directory); msg->path = str8_copy(scratch.arena, working_directory);
msg->cmd_line_string_list = str8_list_copy(scratch.arena, &cmdln_strings); msg->cmd_line_string_list = str8_list_copy(scratch.arena, &cmdln_strings);
msg->stdout_path = str8_copy(scratch.arena, stdout_path); msg->stdout_path = str8_copy(scratch.arena, stdout_path);
msg->stderr_path = str8_copy(scratch.arena, stderr_path); msg->stderr_path = str8_copy(scratch.arena, stderr_path);
msg->stdin_path = str8_copy(scratch.arena, stdin_path); msg->stdin_path = str8_copy(scratch.arena, stdin_path);
msg->debug_subprocesses = target->debug_subprocesses; msg->debug_subprocesses = target->debug_subprocesses;
msg->deploy = target->deploy;
msg->env_inherit = 1; msg->env_inherit = 1;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters); MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
msg->auto_download_debug_info = auto_download_debug_info; 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 // rjf: no targets -> error
if(targets_to_launch->count == 0) 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; }break;
case D_CmdKind_Kill: 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); D_Entity *process = d_entity_from_handle(params->process);
if(process == &d_entity_nil) 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 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); D_Entity *process = d_entity_from_handle(params->process);
if(process == &d_entity_nil) 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 else
{ {
@@ -1882,19 +1887,28 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case D_CmdKind_Continue: case D_CmdKind_Continue:
{ {
B32 good_to_run = 0; B32 good_to_run = 0;
B32 any_non_dump_threads = 0;
D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread);
if(threads.count > 0) if(threads.count > 0)
{ {
for EachIndex(idx, threads.count) for EachIndex(idx, threads.count)
{ {
D_Entity *thread = threads.v[idx]; 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) if(!thread->is_frozen)
{ {
good_to_run = 1; good_to_run = 1;
break; 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; need_run = 1;
run_kind = D_RunKind_Run; run_kind = D_RunKind_Run;
@@ -1902,7 +1916,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
} }
else else
{ {
log_user_error(str8_lit("Cannot run with all threads frozen.")); log_user_error(s("Cannot run with all threads frozen."));
} }
} }
}break; }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); D_Entity *thread = d_entity_from_handle(params->thread);
if(thread == &d_entity_nil) 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()) else if(d_ctrl_targets_running())
{ {
if(d_ctrl_last_run_kind() == D_RunKind_Run) 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) 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 else
{ {
@@ -1967,7 +1985,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
} }
else if(!good_trap_net) else if(!good_trap_net)
{ {
log_user_error(str8_lit("Could not successfully step.")); log_user_error(s("Could not successfully step."));
} }
} }
}break; }break;
@@ -1981,19 +1999,26 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{ {
need_run = 1; need_run = 1;
run_kind = d_user_state->ctrl_last_run_kind; 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_flags = d_user_state->ctrl_last_run_flags;
run_traps = d_user_state->ctrl_last_run_traps; run_traps = d_user_state->ctrl_last_run_traps;
}break; }break;
case D_CmdKind_SetThreadIP: case D_CmdKind_SetThreadIP:
{ {
D_Entity *thread = d_entity_from_handle(params->thread); D_Entity *thread = d_entity_from_handle(params->thread);
ARCH_Info *arch_info = arch_info_from_arch(thread->arch); if(thread->handle.controller_kind == D_ControllerKind_Dump)
U64 vaddr = params->vaddr; {
void *block = d_cached_reg_block_from_thread(scratch.arena, thread->handle); log_user_error(s("Cannot write register values to dump file threads."));
arch_reg_block_write_ip(arch_info, block, vaddr); }
B32 result = d_thread_write_reg_block(thread->handle, block); else
(void)result; {
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; }break;
//- rjf: high-level composite target control operations //- 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].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr);
} }
run_extra_bps.v[0].flags |= D_BreakpointFlag_BreakSelectedThreadOnly;
d_cmd(D_CmdKind_Run); d_cmd(D_CmdKind_Run);
}break; }break;
case D_CmdKind_RunToName: 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); D_EntityArray processes = d_entity_array_from_kind(D_EntityKind_Process);
if(processes.count != 0) 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()) 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_ThawThread:
case D_CmdKind_FreezeProcess: case D_CmdKind_FreezeProcess:
case D_CmdKind_ThawProcess: case D_CmdKind_ThawProcess:
case D_CmdKind_FreezeMachine: case D_CmdKind_FreezeServer:
case D_CmdKind_ThawMachine: case D_CmdKind_ThawServer:
{ {
D_CmdKind disptch_kind = ((cmd->kind == D_CmdKind_FreezeThread || D_CmdKind disptch_kind = ((cmd->kind == D_CmdKind_FreezeThread ||
cmd->kind == D_CmdKind_FreezeProcess || cmd->kind == D_CmdKind_FreezeProcess ||
cmd->kind == D_CmdKind_FreezeMachine) cmd->kind == D_CmdKind_FreezeServer)
? D_CmdKind_FreezeEntity ? D_CmdKind_FreezeEntity
: D_CmdKind_ThawEntity); : D_CmdKind_ThawEntity);
d_push_cmd(disptch_kind, params); d_push_cmd(disptch_kind, params);
}break; }break;
case D_CmdKind_FreezeLocalMachine: case D_CmdKind_FreezeLocalServer:
{ {
D_MachineID machine_id = D_MachineID_Local; D_ServerID server_id = D_ServerID_LocalHost;
d_cmd(D_CmdKind_FreezeMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero())); d_cmd(D_CmdKind_FreezeServer, .entity = d_handle_from_dmn(server_id, dmn_handle_zero()));
}break; }break;
case D_CmdKind_ThawLocalMachine: case D_CmdKind_ThawLocalServer:
{ {
D_MachineID machine_id = D_MachineID_Local; D_ServerID server_id = D_ServerID_LocalHost;
d_cmd(D_CmdKind_ThawMachine, .entity = d_handle_from_dmn(machine_id, dmn_handle_zero())); d_cmd(D_CmdKind_ThawServer, .entity = d_handle_from_dmn(server_id, dmn_handle_zero()));
}break; }break;
case D_CmdKind_FreezeEntity: case D_CmdKind_FreezeEntity:
case D_CmdKind_ThawEntity: case D_CmdKind_ThawEntity:
@@ -2110,7 +2136,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{ {
need_run = 1; need_run = 1;
run_kind = d_user_state->ctrl_last_run_kind; 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_flags = d_user_state->ctrl_last_run_flags;
run_traps = d_user_state->ctrl_last_run_traps; 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(); Access *access = access_open();
D_ModuleInfo *info = d_info_from_module(access, params->entity); 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); smsv_fill_local_path(symbol_server_local_cache_path);
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs); D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs);
msg->kind = D_MsgKind_SetModuleDebugInfoPath; 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); MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
msg->auto_download_debug_info = auto_download_debug_info; msg->auto_download_debug_info = auto_download_debug_info;
}break; }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 // 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; 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 // rjf: push & fill run message
D_Msg *msg = d_msg_list_push(scratch.arena, &ctrl_msgs); 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 // rjf: textual location -> add breakpoints for all possible override locations
if(bp->file_path.size != 0 && bp->pt.line != 0) 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) for(String8Node *n = overrides.first; n != 0; n = n->next)
{ {
D_Breakpoint dst_bp = {0}; 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); arena_clear(d_user_state->ctrl_last_run_arena);
d_user_state->ctrl_last_run_kind = run_kind; 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_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_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_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); d_user_state->ctrl_last_run_extra_bps = d_breakpoint_array_copy(d_user_state->ctrl_last_run_arena, &run_extra_bps_copy);
+16 -5
View File
@@ -59,7 +59,7 @@ D_RunKind;
typedef struct D_CmdParams D_CmdParams; typedef struct D_CmdParams D_CmdParams;
struct D_CmdParams struct D_CmdParams
{ {
D_Handle machine; D_Handle server;
D_Handle process; D_Handle process;
D_Handle thread; D_Handle thread;
D_Handle entity; D_Handle entity;
@@ -160,6 +160,8 @@ struct D_RunLocalsCache
typedef enum D_MsgKind typedef enum D_MsgKind
{ {
D_MsgKind_Null, D_MsgKind_Null,
D_MsgKind_OpenRemoteServer,
D_MsgKind_CloseRemoteServer,
D_MsgKind_Launch, D_MsgKind_Launch,
D_MsgKind_Attach, D_MsgKind_Attach,
D_MsgKind_OpenCrashDump, D_MsgKind_OpenCrashDump,
@@ -195,7 +197,9 @@ struct D_Msg
B32 env_inherit; B32 env_inherit;
B32 debug_subprocesses; B32 debug_subprocesses;
B32 auto_download_debug_info; B32 auto_download_debug_info;
B32 deploy;
U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64]; U64 exception_code_filters[(D_ExceptionCodeKind_COUNT+63)/64];
String8 address;
String8 path; String8 path;
String8List entry_points; String8List entry_points;
String8List cmd_line_string_list; String8List cmd_line_string_list;
@@ -263,6 +267,14 @@ typedef enum D_EventKind
D_EventKind_MemDecommit, D_EventKind_MemDecommit,
D_EventKind_MemRelease, 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_COUNT
} }
D_EventKind; D_EventKind;
@@ -366,7 +378,6 @@ struct D_UserState
Arena *ctrl_last_run_arena; Arena *ctrl_last_run_arena;
D_RunKind ctrl_last_run_kind; D_RunKind ctrl_last_run_kind;
U64 ctrl_last_run_frame_idx; U64 ctrl_last_run_frame_idx;
D_Handle ctrl_last_run_thread_handle;
D_RunFlags ctrl_last_run_flags; D_RunFlags ctrl_last_run_flags;
D_TrapList ctrl_last_run_traps; D_TrapList ctrl_last_run_traps;
D_BreakpointArray ctrl_last_run_extra_bps; 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 //~ 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 //~ 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: Debug Info Lookups
//- rjf: voff -> line info //- 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 //- rjf: file:line -> line info
// TODO(rjf): this depends on file path maps, needs to move // 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 //~ 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 #endif // DBG_ENGINE_USER_H
+240 -43
View File
@@ -8,7 +8,7 @@ String8 d_entity_kind_code_name_table[13] =
{ {
{0}, {0},
str8_lit_comp("root"), str8_lit_comp("root"),
str8_lit_comp("machine"), str8_lit_comp("server"),
str8_lit_comp("process"), str8_lit_comp("process"),
str8_lit_comp("thread"), str8_lit_comp("thread"),
str8_lit_comp("module"), str8_lit_comp("module"),
@@ -25,7 +25,7 @@ String8 d_entity_kind_display_string_table[13] =
{ {
{0}, {0},
str8_lit_comp("Root"), str8_lit_comp("Root"),
str8_lit_comp("Machine"), str8_lit_comp("Server"),
str8_lit_comp("Process"), str8_lit_comp("Process"),
str8_lit_comp("Thread"), str8_lit_comp("Thread"),
str8_lit_comp("Module"), str8_lit_comp("Module"),
@@ -38,7 +38,7 @@ str8_lit_comp("Breakpoint"),
str8_lit_comp("AddressRangeAnnotation"), str8_lit_comp("AddressRangeAnnotation"),
}; };
U32 d_exception_code_kind_code_table[38] = U32 d_exception_code_kind_code_table[69] =
{ {
0, 0,
0x40010005, 0x40010005,
@@ -78,51 +78,186 @@ U32 d_exception_code_kind_code_table[38] =
0xe073616e, 0xe073616e,
0xe0736171, 0xe0736171,
0x0000087a, 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}, {0},
str8_lit_comp("(Win32) Control-C"), str8_lit_comp("Control-C"),
str8_lit_comp("(Win32) Control-Break"), str8_lit_comp("Control-Break"),
str8_lit_comp("(Win32) WinRT Originate Error"), str8_lit_comp("WinRT Originate Error"),
str8_lit_comp("(Win32) WinRT Transform Error"), str8_lit_comp("WinRT Transform Error"),
str8_lit_comp("(Win32) RPC Call Cancelled"), str8_lit_comp("RPC Call Cancelled"),
str8_lit_comp("(Win32) Data Type Misalignment"), str8_lit_comp("Data Type Misalignment"),
str8_lit_comp("(Win32) Access Violation"), str8_lit_comp("Access Violation"),
str8_lit_comp("(Win32) In Page Error"), str8_lit_comp("In Page Error"),
str8_lit_comp("(Win32) Invalid Handle Specified"), str8_lit_comp("Invalid Handle Specified"),
str8_lit_comp("(Win32) Not Enough Quota"), str8_lit_comp("Not Enough Quota"),
str8_lit_comp("(Win32) Illegal Instruction"), str8_lit_comp("Illegal Instruction"),
str8_lit_comp("(Win32) Cannot Continue From Exception"), str8_lit_comp("Cannot Continue From Exception"),
str8_lit_comp("(Win32) Invalid Exception Disposition Returned By Handler"), str8_lit_comp("Invalid Exception Disposition Returned By Handler"),
str8_lit_comp("(Win32) Array Bounds Exceeded"), str8_lit_comp("Array Bounds Exceeded"),
str8_lit_comp("(Win32) Floating-Point Denormal Operand"), str8_lit_comp("Floating-Point Denormal Operand"),
str8_lit_comp("(Win32) Floating-Point Division By Zero"), str8_lit_comp("Floating-Point Division By Zero"),
str8_lit_comp("(Win32) Floating-Point Inexact Result"), str8_lit_comp("Floating-Point Inexact Result"),
str8_lit_comp("(Win32) Floating-Point Invalid Operation"), str8_lit_comp("Floating-Point Invalid Operation"),
str8_lit_comp("(Win32) Floating-Point Overflow"), str8_lit_comp("Floating-Point Overflow"),
str8_lit_comp("(Win32) Floating-Point Stack Check"), str8_lit_comp("Floating-Point Stack Check"),
str8_lit_comp("(Win32) Floating-Point Underflow"), str8_lit_comp("Floating-Point Underflow"),
str8_lit_comp("(Win32) Integer Division By Zero"), str8_lit_comp("Integer Division By Zero"),
str8_lit_comp("(Win32) Integer Overflow"), str8_lit_comp("Integer Overflow"),
str8_lit_comp("(Win32) Privileged Instruction"), str8_lit_comp("Privileged Instruction"),
str8_lit_comp("(Win32) Stack Overflow"), str8_lit_comp("Stack Overflow"),
str8_lit_comp("(Win32) Unable To Locate DLL"), str8_lit_comp("Unable To Locate DLL"),
str8_lit_comp("(Win32) Ordinal Not Found"), str8_lit_comp("Ordinal Not Found"),
str8_lit_comp("(Win32) Entry Point Not Found"), str8_lit_comp("Entry Point Not Found"),
str8_lit_comp("(Win32) DLL Initialization Failed"), str8_lit_comp("DLL Initialization Failed"),
str8_lit_comp("(Win32) Floating Point SSE Multiple Faults"), str8_lit_comp("Floating Point SSE Multiple Faults"),
str8_lit_comp("(Win32) Floating Point SSE Multiple Traps"), str8_lit_comp("Floating Point SSE Multiple Traps"),
str8_lit_comp("(Win32) Assertion Failed"), str8_lit_comp("Assertion Failed"),
str8_lit_comp("(Win32) Module Not Found"), str8_lit_comp("Module Not Found"),
str8_lit_comp("(Win32) Procedure Not Found"), str8_lit_comp("Procedure Not Found"),
str8_lit_comp("(Win32) Sanitizer Error Detected"), str8_lit_comp("Sanitizer Error Detected"),
str8_lit_comp("(Win32) Sanitizer Raw Access Violation"), str8_lit_comp("Sanitizer Raw Access Violation"),
str8_lit_comp("(Win32) DirectX Debug Layer"), 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}, {0},
str8_lit_comp("win32_ctrl_c"), 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_error_detected"),
str8_lit_comp("win32_sanitizer_raw_access_violation"), str8_lit_comp("win32_sanitizer_raw_access_violation"),
str8_lit_comp("win32_directx_debug_layer"), 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, 0,
1, 1,
@@ -204,6 +370,37 @@ B8 d_exception_code_kind_default_enable_table[38] =
1, 1,
0, 0,
1, 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 C_LINKAGE_END
+43 -9
View File
@@ -34,10 +34,10 @@ D_CmdKind_FreezeThread,
D_CmdKind_ThawThread, D_CmdKind_ThawThread,
D_CmdKind_FreezeProcess, D_CmdKind_FreezeProcess,
D_CmdKind_ThawProcess, D_CmdKind_ThawProcess,
D_CmdKind_FreezeMachine, D_CmdKind_FreezeServer,
D_CmdKind_ThawMachine, D_CmdKind_ThawServer,
D_CmdKind_FreezeLocalMachine, D_CmdKind_FreezeLocalServer,
D_CmdKind_ThawLocalMachine, D_CmdKind_ThawLocalServer,
D_CmdKind_FreezeEntity, D_CmdKind_FreezeEntity,
D_CmdKind_ThawEntity, D_CmdKind_ThawEntity,
D_CmdKind_SetEntityColor, D_CmdKind_SetEntityColor,
@@ -45,6 +45,8 @@ D_CmdKind_SetEntityName,
D_CmdKind_DownloadModuleDebugInfo, D_CmdKind_DownloadModuleDebugInfo,
D_CmdKind_Attach, D_CmdKind_Attach,
D_CmdKind_OpenCrashDump, D_CmdKind_OpenCrashDump,
D_CmdKind_OpenRemoteServer,
D_CmdKind_CloseRemoteServer,
D_CmdKind_COUNT, D_CmdKind_COUNT,
} D_CmdKind; } D_CmdKind;
@@ -52,7 +54,7 @@ typedef enum D_EntityKind
{ {
D_EntityKind_Null, D_EntityKind_Null,
D_EntityKind_Root, D_EntityKind_Root,
D_EntityKind_Machine, D_EntityKind_Server,
D_EntityKind_Process, D_EntityKind_Process,
D_EntityKind_Thread, D_EntityKind_Thread,
D_EntityKind_Module, D_EntityKind_Module,
@@ -106,6 +108,37 @@ D_ExceptionCodeKind_Win32ProcedureNotFound,
D_ExceptionCodeKind_Win32SanitizerErrorDetected, D_ExceptionCodeKind_Win32SanitizerErrorDetected,
D_ExceptionCodeKind_Win32SanitizerRawAccessViolation, D_ExceptionCodeKind_Win32SanitizerRawAccessViolation,
D_ExceptionCodeKind_Win32DirectXDebugLayer, 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_COUNT,
} D_ExceptionCodeKind; } D_ExceptionCodeKind;
@@ -133,10 +166,11 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
C_LINKAGE_BEGIN C_LINKAGE_BEGIN
extern String8 d_entity_kind_code_name_table[13]; extern String8 d_entity_kind_code_name_table[13];
extern String8 d_entity_kind_display_string_table[13]; extern String8 d_entity_kind_display_string_table[13];
extern U32 d_exception_code_kind_code_table[38]; extern U32 d_exception_code_kind_code_table[69];
extern String8 d_exception_code_kind_display_string_table[38]; extern OperatingSystem d_exception_code_kind_os_table[69];
extern String8 d_exception_code_kind_lowercase_code_string_table[38]; extern String8 d_exception_code_kind_display_string_table[69];
extern B8 d_exception_code_kind_default_enable_table[38]; extern String8 d_exception_code_kind_lowercase_code_string_table[69];
extern B8 d_exception_code_kind_default_enable_table[69];
C_LINKAGE_END C_LINKAGE_END
+19 -14
View File
@@ -483,6 +483,10 @@ di_rdi_from_key(Access *access, DI_Key key, B32 high_priority, U64 endt_us)
rdi = &n->rdi; rdi = &n->rdi;
access_touch(access, &n->access_pt, stripe->cv); access_touch(access, &n->access_pt, stripe->cv);
} }
if(ins_atomic_u64_eval(&n->working_count) != 0)
{
rdi = &di_rdi_parsed_nil_waiting;
}
break; break;
} }
} }
@@ -748,7 +752,7 @@ di_async_tick(void)
} }
else 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(cache_folder);
make_directory(raddbg_folder); make_directory(raddbg_folder);
make_directory(rdis_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 //- rjf: determine if RDI is stale
@@ -1699,20 +1703,21 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out,
RDI_SectionKind_Procedures, RDI_SectionKind_Procedures,
RDI_SectionKind_TypeNodes, RDI_SectionKind_TypeNodes,
}; };
Rng1U64 range = lane_range(dbgi_keys.count); for EachElement(name_map_kind_idx, name_map_kinds)
for EachInRange(dbgi_idx, range)
{ {
DI_Key dbgi_key = dbgi_keys.v[dbgi_idx]; Rng1U64 range = lane_range(dbgi_keys.count);
if(!allow_other_dbgis && !di_key_match(preferred_key, dbgi_key)) for EachInRange(dbgi_idx, range)
{ {
continue; DI_Key dbgi_key = dbgi_keys.v[dbgi_idx];
} if(!allow_other_dbgis && !di_key_match(preferred_key, dbgi_key))
Access *access = access_open();
{
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)
{ {
continue;
}
Access *access = access_open();
{
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx);
// rjf: unpack name map // rjf: unpack name map
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]); RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
RDI_ParsedNameMap parsed_name_map = {0}; RDI_ParsedNameMap parsed_name_map = {0};
@@ -1817,8 +1822,8 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, AC_Status *status_out,
lane_matches[lane_idx()].count = filtered_matches_count; lane_matches[lane_idx()].count = filtered_matches_count;
} }
} }
access_close(access);
} }
access_close(access);
} }
} }
} }
+1
View File
@@ -305,6 +305,7 @@ struct DI_Shared
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals //~ rjf: Globals
global read_only RDI_Parsed di_rdi_parsed_nil_waiting = {0};
global DI_Shared *di_shared = 0; global DI_Shared *di_shared = 0;
//////////////////////////////// ////////////////////////////////
+522
View File
@@ -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;
}
+154
View File
@@ -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; result->module_info = &dmn_module_info_nil;
return result; 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);
}
}
+4 -22
View File
@@ -1,8 +1,8 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DEMON_CORE_H #ifndef DEMON_H
#define DEMON_CORE_H #define DEMON_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Control-Thread-Only Context //~ rjf: Control-Thread-Only Context
@@ -18,17 +18,6 @@ struct DMN_CtrlCtx
U64 u64[1]; U64 u64[1];
}; };
////////////////////////////////
//~ Dynamic Linker Types
typedef U32 DMN_TlsModel;
enum
{
DMN_TlsModel_Null,
DMN_TlsModel_WinodwsNt,
DMN_TlsModel_Gnu
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Handle Types //~ rjf: Handle Types
@@ -129,9 +118,6 @@ struct DMN_Event
U64 user_data; U64 user_data;
B32 exception_repeated; B32 exception_repeated;
// rjf: process info
DMN_TlsModel tls_model;
// rjf: module info // rjf: module info
DMN_ModuleInfo *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 //- rjf: event list building
internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list); internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list);
internal void dmn_event_deep_copy(Arena *arena, DMN_Event *dst, DMN_Event *src);
////////////////////////////////
//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once)
internal String8 dmn_data_from_process_vaddr_range(Arena *arena, DMN_Handle process, Rng1U64 vrange);
//////////////////////////////// ////////////////////////////////
//~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) //~ 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 B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out);
internal void dmn_process_iter_end(DMN_ProcessIter *iter); 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 //~ rjf: Event Kind Tables
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#include "demon/demon_core.c" #include "demon/demon.c"
#if OS_WINDOWS #if OS_WINDOWS
# include "win32/demon/win32_demon.c" # include "win32/demon/win32_demon.c"
+1 -1
View File
@@ -4,7 +4,7 @@
#ifndef DEMON_INC_H #ifndef DEMON_INC_H
#define DEMON_INC_H #define DEMON_INC_H
#include "demon/demon_core.h" #include "demon/demon.h"
#if OS_WINDOWS #if OS_WINDOWS
# include "win32/demon/win32_demon.h" # include "win32/demon/win32_demon.h"
-3
View File
@@ -437,13 +437,10 @@ dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_ge
U64 buffer[] = U64 buffer[] =
{ {
mesh_vertices.u64[0], mesh_vertices.u64[0],
mesh_vertices.u64[1],
mesh_indices.u64[0], mesh_indices.u64[0],
mesh_indices.u64[1],
(U64)mesh_geo_topology, (U64)mesh_geo_topology,
(U64)mesh_geo_vertex_flags, (U64)mesh_geo_vertex_flags,
albedo_tex.u64[0], albedo_tex.u64[0],
albedo_tex.u64[1],
(U64)dr_top_tex2d_sample_kind(), (U64)dr_top_tex2d_sample_kind(),
}; };
hash = dr_hash_from_string(str8((U8 *)buffer, sizeof(buffer))); hash = dr_hash_from_string(str8((U8 *)buffer, sizeof(buffer)));
+52 -17
View File
@@ -676,6 +676,7 @@ internal void
dw2_parse_ctx_equip_unit_root_tag(DW2_ParseCtx *ctx_out, DW2_Tag *tag, DW2_OffsetTableSet *offset_tables) dw2_parse_ctx_equip_unit_root_tag(DW2_ParseCtx *ctx_out, DW2_Tag *tag, DW2_OffsetTableSet *offset_tables)
{ {
// rjf: unpack attributes // rjf: unpack attributes
DW2_Attrib *name_attrib = &dw2_attrib_nil;
DW2_Attrib *low_pc_attrib = &dw2_attrib_nil; DW2_Attrib *low_pc_attrib = &dw2_attrib_nil;
DW2_Attrib *lang_attrib = &dw2_attrib_nil; DW2_Attrib *lang_attrib = &dw2_attrib_nil;
DW2_Attrib *rnglists_base_off_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; default:{}break;
#define Case(name, name_upper) case DW_AttribKind_##name_upper:{name##_attrib = &n->v;}break #define Case(name, name_upper) case DW_AttribKind_##name_upper:{name##_attrib = &n->v;}break
Case(name, Name);
Case(low_pc, LowPc); Case(low_pc, LowPc);
Case(lang, Language); Case(lang, Language);
Case(rnglists_base_off, RngListsBase); 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->unit_base_addr = low_pc_attrib->val.addr;
ctx_out->language = lang_attrib->val.u128.u64[0]; ctx_out->language = lang_attrib->val.u128.u64[0];
ctx_out->unit_dir = comp_dir_attrib->val.string; ctx_out->unit_dir = comp_dir_attrib->val.string;
ctx_out->unit_file = name_attrib->val.string;
// rjf: find offset tables // rjf: find offset tables
Rng1U64Array rnglists_tables_ranges_array = {offset_tables->rnglists_tables_ranges, offset_tables->rnglists_tables_count}; 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); off += dw2_read_fmt_u64(data, off, format, &header_length);
opl_header_length_off = off; opl_header_length_off = off;
off += str8_deserial_read_struct(data, off, &min_inst_length); off += str8_deserial_read_struct(data, off, &min_inst_length);
off += str8_deserial_read_struct(data, off, &max_ops_per_inst); 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, &default_is_stmt);
off += str8_deserial_read_struct(data, off, &line_base); off += str8_deserial_read_struct(data, off, &line_base);
off += str8_deserial_read_struct(data, off, &line_range); off += str8_deserial_read_struct(data, off, &line_range);
@@ -1115,7 +1121,7 @@ dw2_read_line_table_header(Arena *arena, DW_Raw *raw, DW2_ParseCtx *ctx, String8
DW2_LineTableFile *entry_out = &table.v[idx]; DW2_LineTableFile *entry_out = &table.v[idx];
for(U64 entry_format_idx = 0; entry_format_idx < entry_formats_count; entry_format_idx += 1) for(U64 entry_format_idx = 0; entry_format_idx < entry_formats_count; entry_format_idx += 1)
{ {
DW_LNCT lnct = (DW_LNCT)entry_formats[entry_format_idx*2 + 0]; DW_LNCT lnct = (DW_LNCT)entry_formats[entry_format_idx*2 + 0];
DW_FormKind form_kind = (DW_FormKind)entry_formats[entry_format_idx*2 + 1]; DW_FormKind form_kind = (DW_FormKind)entry_formats[entry_format_idx*2 + 1];
DW2_FormVal form_val = {0}; DW2_FormVal form_val = {0};
off += dw2_read_form_val(raw, ctx, data, off, form_kind, 0, &form_val); off += dw2_read_form_val(raw, ctx, data, off, form_kind, 0, &form_val);
@@ -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) //~ rjf: String Offset Table Parsing (.debug_str_offsets)
internal U64 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; 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, &addr_size);
off += str8_deserial_read_struct(data, off, &segment_selector_size); off += str8_deserial_read_struct(data, off, &segment_selector_size);
// rjf: determine entry size // rjf: 0 addr size / segment selector size -> this is an offset table (e.g. stroffs).
U64 entry_size = dw_addr_size_from_format(format); // this means the table immediately follows the header, and the entry size is based
if(addr_size != 0) // 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_size = addr_size + segment_selector_size;
entry_count = (unit_data_off_opl - off) / entry_size;
} }
// rjf: fill table info // 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->addr_size = addr_size;
out->segment_selector_size = segment_selector_size; out->segment_selector_size = segment_selector_size;
out->entry_size = entry_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; out->entries = data.str + off;
// rjf: skip table // rjf: skip table
@@ -1247,14 +1277,14 @@ dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out)
} }
internal DW2_OffsetTableList 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}; DW2_OffsetTableList list = {0};
for(U64 off = 0; off < data.size;) for(U64 off = 0; off < data.size;)
{ {
U64 start_off = off; U64 start_off = off;
DW2_OffsetTable table = {0}; 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) if(table.entries != 0)
{ {
DW2_OffsetTableNode *n = push_array(arena, DW2_OffsetTableNode, 1); 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_size = tbl->entry_size;
U64 entry_off = idx * entry_size; U64 entry_off = idx * entry_size;
if(tbl->addr_size != 0) if(tbl->entries_are_addrs)
{ {
U64 segment_off = entry_off; U64 segment_off = entry_off;
U64 addr_off = entry_off + tbl->segment_selector_size; 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 struct
{ {
String8 data; String8 data;
B32 offset_count_entry;
U64 *tables_count_out; U64 *tables_count_out;
DW2_OffsetTable **tables_out; DW2_OffsetTable **tables_out;
Rng1U64 **tables_ranges_out; Rng1U64 **tables_ranges_out;
} }
tasks[] = 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_StrOffsets].data, 0, &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_RngLists].data, 1, &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_Addr].data, 0, &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_LocLists].data, 1, &result.loclists_tables_count, &result.loclists_tables, &result.loclists_tables_ranges},
}; };
for EachElement(task_idx, tasks) for EachElement(task_idx, tasks)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
String8 data = tasks[task_idx].data; 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_count_out[0] = tables.count;
tasks[task_idx].tables_out[0] = push_array(arena, DW2_OffsetTable, 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); 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) if(ctx->rnglists_table != 0)
{ {
U64 rnglist_off_idx = form_val.u128.u64[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; }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]; loclist_off = form_val.u128.u64[0];
}break; }break;
case DW_FormKind_LocListx: case DW_FormKind_LocListx:
if(ctx->rnglists_table != 0) if(ctx->loclists_table != 0)
{ {
U64 loclist_off_idx = form_val.u128.u64[0]; U64 loclist_off_idx = form_val.u128.u64[0];
dw2_try_offset_from_table_idx(ctx->loclists_table, loclist_off_idx, &loclist_off); dw2_try_offset_from_table_idx(ctx->loclists_table, loclist_off_idx, &loclist_off);
+3 -2
View File
@@ -104,6 +104,7 @@ struct DW2_OffsetTable
U8 segment_selector_size; U8 segment_selector_size;
U64 entry_size; U64 entry_size;
U64 entries_count; U64 entries_count;
B32 entries_are_addrs;
void *entries; 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) //~ rjf: Offset Table Parsing (.debug_str_offsets, .debug_rnglists)
internal U64 dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out); 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); 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 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); internal DW2_OffsetTableSet dw2_offset_table_set_from_raw(Arena *arena, DW_Raw *raw);
+2 -2
View File
@@ -52,11 +52,11 @@ dw_raw_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin)
// rjf: read compressed-section header // rjf: read compressed-section header
ELF_Chdr64 chdr64 = {0}; ELF_Chdr64 chdr64 = {0};
U64 chdr_size = 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); 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}; ELF_Chdr32 chdr32 = {0};
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32); chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32);
+1 -1
View File
@@ -199,7 +199,7 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
String8 raw_coff = coff_from_obj(scratch.arena, obj); String8 raw_coff = coff_from_obj(scratch.arena, obj);
t_write_file(str8_lit("dwarf.obj"), raw_coff); 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"))); delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
String8 exe = t_read_file(arena, str8_lit("a.exe")); String8 exe = t_read_file(arena, str8_lit("a.exe"));
+5
View File
@@ -133,6 +133,7 @@ eh_uwnd_step(Arch arch, MemoryMap *memory_map, UWND_ModuleInfo *module_info, U64
// rjf: determine CIE's full address range // rjf: determine CIE's full address range
Rng1U64 cie_vaddr_range = {0}; Rng1U64 cie_vaddr_range = {0};
DW_Format cie_fmt = DW_Format_Null; DW_Format cie_fmt = DW_Format_Null;
if(!done)
{ {
// rjf: read initial length data // rjf: read initial length data
String8 initial_length_data = {0}; 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 //- rjf: commit new register values, if we succeeded
if(!done) if(!done)
{ {
if(cfa_out)
{
cfa_out[0] = cfa;
}
result.status = UWND_StepStatus_Good; result.status = UWND_StepStatus_Good;
} }
} }
+192 -110
View File
@@ -122,46 +122,65 @@ elf_auxv64_from_auxv32(ELF_Auxv32 auxv32)
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: ELF -> Codebase enum Conversions
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);
}
////////////////////////////////
internal Arch internal Arch
arch_from_elf_machine(ELF_MachineKind e_machine) arch_from_elf_machine(ELF_MachineKind e_machine)
{ {
Arch arch = Arch_Null; Arch arch = Arch_Null;
switch (e_machine) { switch((ELF_MachineKindEnum)e_machine)
case ELF_MachineKind_None: arch = Arch_Null; break; {
case ELF_MachineKind_AARCH64: arch = Arch_arm32; break; default:{}break;
case ELF_MachineKind_ARM: arch = Arch_arm32; break; case ELF_MachineKind_None: {arch = Arch_Null;}break;
case ELF_MachineKind_386: arch = Arch_x86; break; case ELF_MachineKind_AARCH64: {arch = Arch_arm32;}break;
case ELF_MachineKind_X86_64: arch = Arch_x64; break; case ELF_MachineKind_ARM: {arch = Arch_arm32;}break;
default: NotImplemented; break; case ELF_MachineKind_386: {arch = Arch_x86;}break;
case ELF_MachineKind_X86_64: {arch = Arch_x64;}break;
} }
return arch; 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 internal U64
elf_phdr_size_from_class(ELF_Class elf_class) elf_phdr_size_from_class(ELF_Class elf_class)
{ {
U64 result = 0; U64 result = 0;
switch (elf_class) { switch((ELF_ClassEnum)elf_class)
case ELF_Class_None: break; {
case ELF_Class_32: { result = sizeof(ELF_Phdr32); } break; case ELF_Class_COUNT:
case ELF_Class_64: { result = sizeof(ELF_Phdr64); } break; case ELF_Class_None:{}break;
default: { NotImplemented; } break; case ELF_Class_32:{result = sizeof(ELF_Phdr32);} break;
case ELF_Class_64:{result = sizeof(ELF_Phdr64);} 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; return result;
} }
@@ -170,124 +189,187 @@ internal U64
elf_dyn_size_from_class(ELF_Class elf_class) elf_dyn_size_from_class(ELF_Class elf_class)
{ {
U64 result = 0; U64 result = 0;
switch (elf_class) { switch((ELF_ClassEnum)elf_class)
case ELF_Class_None: break; {
case ELF_Class_32: { result = sizeof(ELF_Dyn32); } break; case ELF_Class_COUNT:
case ELF_Class_64: { result = sizeof(ELF_Dyn64); } break; case ELF_Class_None:{}break;
default: { NotImplemented; } break; case ELF_Class_32:{result = sizeof(ELF_Dyn32);}break;
case ELF_Class_64:{result = sizeof(ELF_Dyn64);}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; return result;
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Optional Class Conversion Readers
internal MachineOpResult internal ELF_Hdr64
elf_read_ehdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Hdr64 *ehdr_out) elf_hdr64_from_class_data(ELF_Class elf_class, String8 data)
{ {
U8 e_ident[ELF_Identifier_Max] = {0}; ELF_Hdr64 result = {0};
MachineOpResult result = mem_read(addr, &e_ident, sizeof(e_ident), mem_read_ud); U64 needed_size = elf_hdr_size_from_class(elf_class);
if (result == MachineOpResult_Ok) { if(data.size >= needed_size)
if (str8_match(str8_prefix(str8_array_fixed(e_ident), elf_magic_string.size), elf_magic_string, 0)) { {
switch (e_ident[ELF_Identifier_Class]) { switch(elf_class)
default: { InvalidPath; }break; {
case ELF_Class_None: { }break; default:{}break;
case ELF_Class_32: { case ELF_Class_32:
ELF_Hdr32 ehdr32 = {0}; {
result = mem_read(addr, &ehdr32, sizeof(ehdr32), mem_read_ud); ELF_Hdr32 result32 = *(ELF_Hdr32 *)data.str;
if (result == MachineOpResult_Ok) { result = elf_hdr64_from_hdr32(result32);
*ehdr_out = elf_hdr64_from_hdr32(ehdr32); }break;
} case ELF_Class_64:
} break; {
case ELF_Class_64: { result = *(ELF_Hdr64 *)data.str;
result = mem_read(addr, ehdr_out, sizeof(*ehdr_out), mem_read_ud); }break;
} break;
}
} }
} }
return result; return result;
} }
internal MachineOpResult internal ELF_Phdr64
elf_read_phdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out) elf_phdr64_from_class_data(ELF_Class elf_class, String8 data)
{ {
MachineOpResult result = MachineOpResult_Fail; ELF_Phdr64 result = {0};
switch (elf_class) { U64 needed_size = elf_phdr_size_from_class(elf_class);
case ELF_Class_None: break; if(data.size >= needed_size)
case ELF_Class_32: { {
ELF_Phdr32 phdr32 = {0}; switch(elf_class)
result = mem_read(addr, &phdr32, sizeof(phdr32), mem_read_ud); {
if (result == MachineOpResult_Ok) { default:{}break;
*phdr_out = elf_phdr64_from_phdr32(phdr32); 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; return result;
} }
internal MachineOpResult internal ELF_Shdr64
elf_read_shdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out) elf_shdr64_from_class_data(ELF_Class elf_class, String8 data)
{ {
MachineOpResult result = MachineOpResult_Fail; ELF_Shdr64 result = {0};
switch (elf_class) { U64 needed_size = elf_shdr_size_from_class(elf_class);
case ELF_Class_None: break; if(data.size >= needed_size)
case ELF_Class_32: { {
ELF_Shdr32 shdr32 = {0}; switch(elf_class)
result = mem_read(addr, &shdr32, sizeof(shdr32), mem_read_ud); {
if (result == MachineOpResult_Ok) { default:{}break;
*shdr_out = elf_shdr64_from_shdr32(shdr32); 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; return result;
} }
internal MachineOpResult internal ELF_Dyn64
elf_read_dyn(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out) elf_dyn64_from_class_data(ELF_Class elf_class, String8 data)
{ {
MachineOpResult result = MachineOpResult_Fail; ELF_Dyn64 result = {0};
switch (elf_class) { U64 needed_size = elf_dyn_size_from_class(elf_class);
case ELF_Class_None: {} break; if(data.size >= needed_size)
case ELF_Class_32: { {
ELF_Dyn32 dyn32 = {0}; switch(elf_class)
result = mem_read(addr, &dyn32, sizeof(dyn32), mem_read_ud); {
if (result == MachineOpResult_Fail) { default:{}break;
*dyn_out = elf_dyn64_from_dyn32(dyn32); 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; return result;
} }
internal MachineOpResult internal ELF_Sym64
elf_read_symbol(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out) elf_sym64_from_class_data(ELF_Class elf_class, String8 data)
{ {
MachineOpResult result = MachineOpResult_Fail; ELF_Sym64 result = {0};
switch (elf_class) { U64 needed_size = elf_sym_size_from_class(elf_class);
case ELF_Class_None: {} break; if(data.size >= needed_size)
case ELF_Class_32: { {
ELF_Sym32 symbol32 = {0}; switch(elf_class)
result = mem_read(addr, &symbol32, sizeof(symbol32), mem_read_ud); {
if (result == MachineOpResult_Ok) { default:{}break;
*symbol_out = elf_sym64_from_sym32(symbol32); 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; 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;
}
+180 -138
View File
@@ -4,17 +4,21 @@
#ifndef ELF_H #ifndef ELF_H
#define ELF_H #define ELF_H
////////////////////////////////
//~ rjf: Primary ELF File enums/structures
typedef U8 ELF_Class; typedef U8 ELF_Class;
enum typedef enum ELF_ClassEnum
{ {
ELF_Class_None = 0, ELF_Class_None = 0,
ELF_Class_32 = 1, ELF_Class_32 = 1,
ELF_Class_64 = 2, ELF_Class_64 = 2,
ELF_Class_Count = 3 ELF_Class_COUNT = 3
}; }
ELF_ClassEnum;
typedef U8 ELF_OsAbi; typedef U8 ELF_OsAbi;
enum typedef enum ELF_OsAbiEnum
{ {
ELF_OsAbi_None, ELF_OsAbi_None,
ELF_OsAbi_SYSV, ELF_OsAbi_SYSV,
@@ -28,17 +32,19 @@ enum
ELF_OsAbi_TRU64, ELF_OsAbi_TRU64,
ELF_OsAbi_ARM = 97, ELF_OsAbi_ARM = 97,
ELF_OsAbi_STANDALONE = 255, ELF_OsAbi_STANDALONE = 255,
}; }
ELF_OsAbiEnum;
typedef U8 ELF_Version; typedef U8 ELF_Version;
enum typedef enum ELF_VersionEnum
{ {
ELF_Version_None, ELF_Version_None,
ELF_Version_Current, ELF_Version_Current,
}; }
ELF_VersionEnum;
typedef U16 ELF_MachineKind; typedef U16 ELF_MachineKind;
enum typedef enum ELF_MachineKindEnum
{ {
ELF_MachineKind_None = 0, ELF_MachineKind_None = 0,
ELF_MachineKind_M32 = 1, ELF_MachineKind_M32 = 1,
@@ -96,18 +102,20 @@ enum
ELF_MachineKind_K1OM = 181, ELF_MachineKind_K1OM = 181,
ELF_MachineKind_RISCV = 243, ELF_MachineKind_RISCV = 243,
ELF_MachineKind_S390_OLD = 0xA390, ELF_MachineKind_S390_OLD = 0xA390,
}; }
ELF_MachineKindEnum;
typedef U8 ELF_Data; typedef U8 ELF_Data;
enum typedef enum ELF_DataEnum
{ {
ELF_Data_None = 0, ELF_Data_None = 0,
ELF_Data_2LSB = 1, ELF_Data_2LSB = 1,
ELF_Data_2MSB = 2, ELF_Data_2MSB = 2,
}; }
ELF_DataEnum;
typedef U16 ELF_Type; typedef U16 ELF_Type;
enum typedef enum ELF_TypeEnum
{ {
ELF_Type_None = 0, ELF_Type_None = 0,
ELF_Type_Rel = 1, ELF_Type_Rel = 1,
@@ -118,10 +126,11 @@ enum
ELF_Type_HiOs = 0xff00, ELF_Type_HiOs = 0xff00,
ELF_Type_LoProc = 0xff00, ELF_Type_LoProc = 0xff00,
ELF_Type_HiProc = 0xffff ELF_Type_HiProc = 0xffff
}; }
ELF_TypeEnum;
typedef U32 ELF_PType; typedef U32 ELF_PType;
enum typedef enum ELF_PTypeEnum
{ {
ELF_PType_Null = 0, ELF_PType_Null = 0,
ELF_PType_Load = 1, ELF_PType_Load = 1,
@@ -141,18 +150,20 @@ enum
ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e551, // frame unwind information ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e551, // frame unwind information
ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e552, // stack flags ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e552, // stack flags
ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e553, // read-only after relocations ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e553, // read-only after relocations
}; }
ELF_PTypeEnum;
typedef U32 ELF_PFlag; typedef U32 ELF_PFlag;
enum typedef enum ELF_PFlagEnum
{ {
ELF_PFlag_Exec = (1 << 0), ELF_PFlag_Exec = (1 << 0),
ELF_PFlag_Write = (1 << 1), ELF_PFlag_Write = (1 << 1),
ELF_PFlag_Read = (1 << 2), ELF_PFlag_Read = (1 << 2),
}; }
ELF_PFlagEnum;
typedef U32 ELF_ShType; typedef U32 ELF_ShType;
enum typedef enum ELF_ShTypeEnum
{ {
ELF_ShType_Null = 0, ELF_ShType_Null = 0,
ELF_ShType_ProgBits = 1, ELF_ShType_ProgBits = 1,
@@ -187,10 +198,11 @@ enum
ELF_ShType_GNU_versym = ELF_ShType_SUNW_versym, ELF_ShType_GNU_versym = ELF_ShType_SUNW_versym,
ELF_ShType_Proc, ELF_ShType_Proc,
ELF_ShType_User, ELF_ShType_User,
}; }
ELF_ShTypeEnum;
typedef U32 ELF_SectionIndex; 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 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_TIC6X_Common = ELF_SectionIndex_LoReserve,
ELF_SectionIndex_MIPS_SUndefined = 0xff04, ELF_SectionIndex_MIPS_SUndefined = 0xff04,
}; }
ELF_SectionIndexEnum;
typedef U32 ELF_SectionFlags; typedef U32 ELF_SectionFlags;
enum 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_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) #define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask)
typedef U32 ELF_AuxType; typedef U32 ELF_AuxType;
enum typedef enum ELF_AuxTypeEnum
{ {
ELF_AuxType_Null = 0, ELF_AuxType_Null = 0,
ELF_AuxType_Phdr = 3, // program headers ELF_AuxType_Phdr = 3, // program headers
@@ -276,10 +289,11 @@ enum
ELF_AuxType_L2_CacheGeometry = 45, ELF_AuxType_L2_CacheGeometry = 45,
ELF_AuxType_L3_CacheSize = 46, ELF_AuxType_L3_CacheSize = 46,
ELF_AuxType_L3_CacheGeometry = 47, ELF_AuxType_L3_CacheGeometry = 47,
}; }
ELF_AuxTypeEnum;
typedef U32 ELF_DynTag; typedef U32 ELF_DynTag;
enum typedef enum ELF_DynTagEnum
{ {
ELF_DynTag_Null = 0, ELF_DynTag_Null = 0,
@@ -358,7 +372,8 @@ enum
ELF_DynTag_VerSym = 0x6ffffff0, ELF_DynTag_VerSym = 0x6ffffff0,
ELF_DynTag_LoProc = 0x70000000, ELF_DynTag_LoProc = 0x70000000,
ELF_DynTag_HiProc = 0x7fffffff, ELF_DynTag_HiProc = 0x7fffffff,
}; }
ELF_DynTagEnum;
typedef U32 ELF_DynFlag; typedef U32 ELF_DynFlag;
enum enum
@@ -532,9 +547,6 @@ enum
ELF_NoteType_STapSdt = 3, // System Tap probes 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 typedef enum ELF_Identifier
{ {
ELF_Identifier_Mag0 = 0, ELF_Identifier_Mag0 = 0,
@@ -547,76 +559,82 @@ typedef enum ELF_Identifier
ELF_Identifier_OsAbi = 7, ELF_Identifier_OsAbi = 7,
ELF_Identfiier_AbiBersion = 8, ELF_Identfiier_AbiBersion = 8,
ELF_Identifier_Max = 16, ELF_Identifier_Max = 16,
} ELF_Identifier; }
ELF_Identifier;
read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'}; read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'};
read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)}; 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]; U8 e_ident[ELF_Identifier_Max];
ELF_Type e_type; ELF_Type e_type;
ELF_MachineKind e_machine; ELF_MachineKind e_machine;
U32 e_version; U32 e_version;
U64 e_entry; U64 e_entry;
U64 e_phoff; U64 e_phoff;
U64 e_shoff; U64 e_shoff;
U32 e_flags; U32 e_flags;
U16 e_ehsize; U16 e_ehsize;
U16 e_phentsize; U16 e_phentsize;
U16 e_phnum; U16 e_phnum;
U16 e_shentsize; U16 e_shentsize;
U16 e_shnum; U16 e_shnum;
U16 e_shstrndx; U16 e_shstrndx;
} ELF_Hdr64; };
typedef struct ELF_Hdr32 typedef struct ELF_Hdr32 ELF_Hdr32;
struct ELF_Hdr32
{ {
U8 e_ident[ELF_Identifier_Max]; U8 e_ident[ELF_Identifier_Max];
ELF_Type e_type; ELF_Type e_type;
ELF_MachineKind e_machine; ELF_MachineKind e_machine;
U32 e_version; U32 e_version;
U32 e_entry; U32 e_entry;
U32 e_phoff; U32 e_phoff;
U32 e_shoff; U32 e_shoff;
U32 e_flags; U32 e_flags;
U16 e_ehsize; U16 e_ehsize;
U16 e_phentsize; U16 e_phentsize;
U16 e_phnum; U16 e_phnum;
U16 e_shentsize; U16 e_shentsize;
U16 e_shnum; U16 e_shnum;
U16 e_shstrndx; U16 e_shstrndx;
} ELF_Hdr32; };
typedef struct ELF_Shdr64 typedef struct ELF_Shdr64 ELF_Shdr64;
struct ELF_Shdr64
{ {
U32 sh_name; U32 sh_name;
ELF_ShType sh_type; ELF_ShType sh_type;
U64 sh_flags; U64 sh_flags;
U64 sh_addr; U64 sh_addr;
U64 sh_offset; U64 sh_offset;
U64 sh_size; U64 sh_size;
U32 sh_link; U32 sh_link;
U32 sh_info; U32 sh_info;
U64 sh_addralign; U64 sh_addralign;
U64 sh_entsize; U64 sh_entsize;
} ELF_Shdr64; };
typedef struct ELF_Shdr32 typedef struct ELF_Shdr32 ELF_Shdr32;
struct ELF_Shdr32
{ {
U32 sh_name; U32 sh_name;
ELF_ShType sh_type; ELF_ShType sh_type;
U32 sh_flags; U32 sh_flags;
U32 sh_addr; U32 sh_addr;
U32 sh_offset; U32 sh_offset;
U32 sh_size; U32 sh_size;
U32 sh_link; U32 sh_link;
U32 sh_info; U32 sh_info;
U32 sh_addralign; U32 sh_addralign;
U32 sh_entsize; U32 sh_entsize;
} ELF_Shdr32; };
typedef struct ELF_Phdr64 typedef struct ELF_Phdr64 ELF_Phdr64;
struct ELF_Phdr64
{ {
U32 p_type; U32 p_type;
U32 p_flags; U32 p_flags;
@@ -626,9 +644,10 @@ typedef struct ELF_Phdr64
U64 p_filesz; U64 p_filesz;
U64 p_memsz; U64 p_memsz;
U64 p_align; U64 p_align;
} ELF_Phdr64; };
typedef struct ELF_Phdr32 typedef struct ELF_Phdr32 ELF_Phdr32;
struct ELF_Phdr32
{ {
U32 p_type; U32 p_type;
U32 p_offset; U32 p_offset;
@@ -638,46 +657,53 @@ typedef struct ELF_Phdr32
U32 p_memsz; U32 p_memsz;
U32 p_flags; U32 p_flags;
U32 p_align; U32 p_align;
} ELF_Phdr32; };
//////////////////////////////// ////////////////////////////////
// Auxiliary Vectors //~ Auxiliary Vectors
//
// these appear in /proc/<pid>/auxv of a process, they are not in elf files // 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_type;
U32 a_val; U32 a_val;
} ELF_Auxv32; };
typedef struct ELF_Auxv64 typedef struct ELF_Auxv64 ELF_Auxv64;
struct ELF_Auxv64
{ {
U64 a_type; U64 a_type;
U64 a_val; 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 // 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 tag;
U32 val; U32 val;
} ELF_Dyn32; };
typedef struct ELF_Dyn64 typedef struct ELF_Dyn64 ELF_Dyn64;
struct ELF_Dyn64
{ {
U64 tag; U64 tag;
U64 val; 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_name; // Holds index into files string table.
U32 st_value; // Depending on the context, this may be address, size, etc. 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_info; // Contains symbols type and binding.
U8 st_other; // Reserved for future use, currenly zero. U8 st_other; // Reserved for future use, currenly zero.
U16 st_shndx; // Section index to which symbol is relevant. 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; U32 st_name;
U8 st_info; U8 st_info;
@@ -695,38 +722,42 @@ typedef struct
U16 st_shndx; U16 st_shndx;
U64 st_value; U64 st_value;
U64 st_size; U64 st_size;
} ELF_Sym64; };
#define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF)) #define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF))
#define ELF_ST_BIND(x) ((x) >> 4) #define ELF_ST_BIND(x) ((x) >> 4)
#define ELF_ST_TYPE(x) ((x) & 0xF) #define ELF_ST_TYPE(x) ((x) & 0xF)
#define ELF_ST_VISIBILITY(v) ((v) & 0x3) #define ELF_ST_VISIBILITY(v) ((v) & 0x3)
typedef struct typedef struct ELF_Rel32 ELF_Rel32;
struct ELF_Rel32
{ {
U32 r_offset; U32 r_offset;
U32 r_info; U32 r_info;
} ELF_Rel32; };
typedef struct typedef struct ELF_Rela32 ELF_Rela32;
struct ELF_Rela32
{ {
U32 r_offset; U32 r_offset;
U32 r_info; U32 r_info;
S32 r_addend; S32 r_addend;
} ELF_Rela32; };
typedef struct typedef struct ELF_Rel64 ELF_Rel64;
struct ELF_Rel64
{ {
U64 r_offset; U64 r_offset;
U64 r_info; U64 r_info;
} ELF_Rel64; };
typedef struct typedef struct ELF_Rela64 ELF_Rela64;
struct ELF_Rela64
{ {
U64 r_offset; U64 r_offset;
U64 r_info; U64 r_info;
S64 r_addend; S64 r_addend;
} ELF_Rela64; };
#define ELF32_R_SYM(x) ((x) >> 8) #define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xFF) #define ELF32_R_TYPE(x) ((x) & 0xFF)
@@ -740,7 +771,8 @@ typedef struct
#define ELF_EXTERNAL_VERSYM_MASK 0x7FFF #define ELF_EXTERNAL_VERSYM_MASK 0x7FFF
// Appears in .gnu.verdef (SHT_GNU_verdef) // Appears in .gnu.verdef (SHT_GNU_verdef)
typedef struct typedef struct ELF_ExternalVerdef ELF_ExternalVerdef;
struct ELF_ExternalVerdef
{ {
U16 vd_version; U16 vd_version;
U16 vd_flags; U16 vd_flags;
@@ -749,43 +781,47 @@ typedef struct
U32 vd_hash; U32 vd_hash;
U32 vd_aux; U32 vd_aux;
U32 vd_next; U32 vd_next;
} ELF_ExternalVerdef; };
// Appears in .gnu.verdef (SHT_GNU_verdef) // Appears in .gnu.verdef (SHT_GNU_verdef)
typedef struct typedef struct ELF_ExternalVerdaux ELF_ExternalVerdaux;
struct ELF_ExternalVerdaux
{ {
U32 vda_name; U32 vda_name;
U32 vda_next; U32 vda_next;
} ELF_ExternalVerdaux; };
// Appears in .gnu.verneed (SHT_GNU_verneed) // Appears in .gnu.verneed (SHT_GNU_verneed)
typedef struct typedef struct ELF_ExternalVerneed ELF_ExternalVerneed;
struct ELF_ExternalVerneed
{ {
U16 vn_version; U16 vn_version;
U16 vn_cnt; U16 vn_cnt;
U32 vn_file; U32 vn_file;
U32 vn_aux; U32 vn_aux;
U32 vn_next; U32 vn_next;
} ELF_ExternalVerneed; };
// Appears in .gnu.verneed (SHT_GNU_verneed) // Appears in .gnu.verneed (SHT_GNU_verneed)
typedef struct typedef struct ELF_ExternalVernaux ELF_ExternalVernaux;
struct ELF_ExternalVernaux
{ {
U32 vna_hash; U32 vna_hash;
U16 vna_flags; U16 vna_flags;
U16 vna_other; U16 vna_other;
U32 vna_name; U32 vna_name;
U32 vna_next; U32 vna_next;
} ELF_ExternalVernaux; };
// Appears in .gnu.version (SHT_GNU_versym) // Appears in .gnu.version (SHT_GNU_versym)
typedef struct typedef struct ELF_ExternalVersym ELF_ExternalVersym;
struct ELF_ExternalVersym
{ {
U16 vs_vers; U16 vs_vers;
} ELF_ExternalVersym; };
//////////////////////////////// ////////////////////////////////
// Extensions //~ Extensions
typedef U8 ELF_CompressType; typedef U8 ELF_CompressType;
enum ELF_CompressTypeEnum enum ELF_CompressTypeEnum
@@ -801,53 +837,59 @@ enum ELF_CompressTypeEnum
ELF_CompressType_HiProc = 0x7fffffff, ELF_CompressType_HiProc = 0x7fffffff,
}; };
typedef struct ELF_Chdr32 typedef struct ELF_Chdr32 ELF_Chdr32;
struct ELF_Chdr32
{ {
U32 ch_type; U32 ch_type;
U32 ch_size; U32 ch_size;
U32 ch_addr_align; U32 ch_addr_align;
} ELF_Chdr32; };
typedef struct ELF_Chdr64 typedef struct ELF_Chdr64 ELF_Chdr64;
struct ELF_Chdr64
{ {
U32 ch_type; U32 ch_type;
U32 ch_reserved; U32 ch_reserved;
U64 ch_size; U64 ch_size;
U64 ch_addr_align; U64 ch_addr_align;
} ELF_Chdr64; };
//////////////////////////////// ////////////////////////////////
//~ rjf: 32 => 64 bit conversions
internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32); internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32);
internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32); internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32);
internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32); internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32);
internal ELF_Dyn64 elf_dyn64_from_dyn32 (ELF_Dyn32 h32); internal ELF_Dyn64 elf_dyn64_from_dyn32(ELF_Dyn32 h32);
internal ELF_Sym64 elf_sym64_from_sym32 (ELF_Sym32 sym32); internal ELF_Sym64 elf_sym64_from_sym32(ELF_Sym32 sym32);
internal ELF_Rel64 elf_rel64_from_rel32 (ELF_Rel32 rel32); internal ELF_Rel64 elf_rel64_from_rel32(ELF_Rel32 rel32);
internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32); internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32);
internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32); internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32);
internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32); internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32);
//////////////////////////////// ////////////////////////////////
//~ rjf: ELF -> Codebase enum Conversions
internal String8 elf_string_from_class(Arena *arena, ELF_Class v);
////////////////////////////////
internal Arch arch_from_elf_machine(ELF_MachineKind machine); 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_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_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 ELF_Hdr64 elf_hdr64_from_class_data(ELF_Class elf_class, String8 data);
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);
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);
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);
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);
internal ELF_Auxv64 elf_auxv64_from_class_data(ELF_Class elf_class, String8 data);
#endif // ELF_H #endif // ELF_H
+2 -5
View File
@@ -172,8 +172,8 @@ internal ELF_NoteList
elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine) elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine)
{ {
ELF_NoteList result = {0}; ELF_NoteList result = {0};
for(U64 cursor = 0; cursor < raw_note.size; )
for (U64 cursor = 0; cursor < raw_note.size; ) { {
U32 owner_size; U32 owner_size;
U64 owner_size_size = str8_deserial_read_struct(raw_note, cursor, &owner_size); U64 owner_size_size = str8_deserial_read_struct(raw_note, cursor, &owner_size);
if (owner_size_size == 0) { goto exit; } 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); SLLQueuePush(result.first, result.last, n);
result.count += 1; result.count += 1;
} }
exit:; exit:;
return result; return result;
} }
+3 -3
View File
@@ -1251,11 +1251,11 @@ e_value_eval_from_eval(E_Eval eval)
{ {
default:{}break; default:{}break;
case E_TypeKind_Char8: 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_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_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;
} }
} }
} }
+1 -1
View File
@@ -1278,7 +1278,7 @@ internal E_DbgInfo *e_dbg_info_from_type_key(E_TypeKey type_key);
// //
// key // key
// ________________________________________________ // ________________________________________________
// / / | \ // _/ / | \_
// text -> expression -> ir tree and type -> interpretation result // text -> expression -> ir tree and type -> interpretation result
// //
// Each one of these calls refers to one stage in this pipeline. The cache will // Each one of these calls refers to one stage in this pipeline. The cache will
+4 -2
View File
@@ -402,8 +402,10 @@ e_interpret(String8 bytecode)
case RDI_EvalOp_ConstString: case RDI_EvalOp_ConstString:
{ {
MemoryCopy(&nval, ptr, imm.u64); U64 src_size = imm.u64;
ptr += imm.u64; U64 dst_size = Min(sizeof(nval), src_size);
MemoryCopy(&nval, ptr, dst_size);
ptr += src_size;
}break; }break;
case RDI_EvalOp_Abs: case RDI_EvalOp_Abs:
+16 -2
View File
@@ -3111,11 +3111,25 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder)
{ {
if(info.props.flags & FilePropertyFlag_IsFolder) if(info.props.flags & FilePropertyFlag_IsFolder)
{ {
str8_list_push(scratch.arena, &folder_paths, str8_copy(arena, info.name)); 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 else
{ {
str8_list_push(scratch.arena, &file_paths, str8_copy(arena, info.name)); 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));
}
} }
} }
} }
+48 -1
View File
@@ -199,6 +199,22 @@ e2_msgf(Arena *arena, E2_MsgList *msgs, Rng1U64 src_range, char *fmt, ...)
return msg; 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 //~ rjf: Assets
@@ -2594,7 +2610,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
internal E2_Compile 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_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; 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; good = 0;
interp.status = E2_InterpStatus_BadRegCode; 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; }break;
case RDI_EvalOp_FrameOff: {ctx_flags = E2_CtxFlag_HasFrameBase; ctx_base_addr = state->selected_ctx.frame_base_addr;}goto optional_base_off; 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 else
{ {
good = 0; 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.status = E2_InterpStatus_MissingCtxFlag;
interp.missing_ctx_flags |= ctx_flags; interp.missing_ctx_flags |= ctx_flags;
} }
@@ -3979,6 +4006,7 @@ BinOp(U, u64, u64, symbol);
{ {
good = 0; good = 0;
interp.status = E2_InterpStatus_BadOffset; 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; }break;
@@ -4029,6 +4057,25 @@ BinOp(U, u64, u64, symbol);
}break; }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 //- rjf: if opcode successful -> do stack pops
if(good) for EachIndex(pop_idx, pop_count) if(good) for EachIndex(pop_idx, pop_count)
{ {
+1 -1
View File
@@ -64,7 +64,6 @@ typedef enum E2_CompileStatus
//- rjf: caller-provided info //- rjf: caller-provided info
E2_CompileStatus_MissedIdentifierResolution, E2_CompileStatus_MissedIdentifierResolution,
E2_CompileStatus_NewIdentifierDefinition, E2_CompileStatus_NewIdentifierDefinition,
E2_CompileStatus_NewCtxID,
E2_CompileStatus_MemberAccess, E2_CompileStatus_MemberAccess,
E2_CompileStatus_IndexAccess, E2_CompileStatus_IndexAccess,
E2_CompileStatus_Call, 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_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 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 //~ rjf: Assets
+6
View File
@@ -65,6 +65,12 @@ E2_ExprKindTable:
COUNT, 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: @data(B8) e2_expr_kind_allow_type_operands_table:
{ {
0, 0,
+52
View File
@@ -4,6 +4,58 @@
//- GENERATED CODE //- GENERATED CODE
C_LINKAGE_BEGIN 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] = B8 e2_expr_kind_allow_type_operands_table[48] =
{ {
0, 0,
+1
View File
@@ -163,6 +163,7 @@ E2_ExprKindParseInfo *expr_kind_parse_infos;
}; };
C_LINKAGE_BEGIN 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_allow_type_operands_table[48];
extern B8 e2_expr_kind_is_type_expr_table[48]; extern B8 e2_expr_kind_is_type_expr_table[48];
extern B8 e2_expr_kind_is_first_operand_type_maybe_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))) 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) if(ptr_data->did_redirect)
+2 -2
View File
@@ -516,12 +516,12 @@ fnt_hash2style_from_tag_size_flags(FNT_Tag tag, F32 size, FNT_RasterFlags flags)
//- rjf: tag * size -> style hash //- rjf: tag * size -> style hash
U64 style_hash = {0}; U64 style_hash = {0};
{ {
F64 size_f64 = size; union { F64 size_f64; U64 size_u64; } size_pun = {.size_f64 = (F64)size};
U64 buffer[] = U64 buffer[] =
{ {
tag.u64[0], tag.u64[0],
tag.u64[1], tag.u64[1],
*(U64 *)(&size_f64), size_pun.size_u64,
(U64)flags, (U64)flags,
}; };
style_hash = fnt_little_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer))); style_hash = fnt_little_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer)));
+1 -1
View File
@@ -67,7 +67,7 @@ typedef S32 RAD_S32;
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define RADFORCEINLINE __forceinline # define RADFORCEINLINE __forceinline
#elif defined(__clang__) || defined(__GNUC__) #elif defined(__clang__) || defined(__GNUC__)
# define RADFORCEINLINE __attribute__((always_inline)) # define RADFORCEINLINE inline __attribute__((always_inline))
#else #else
# error need force inline for this compiler # error need force inline for this compiler
#endif #endif
+34 -4
View File
@@ -11,17 +11,37 @@
//~ Usage Samples //~ Usage Samples
// //
#if 0 #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 // Procedure Name -> Line
{ {
RDI_Parsed *rdi = ...; RDI_Parsed *rdi = ...;
char *name = "mule_main"; 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_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_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_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file
RDI_U64 file_path_size = 0; // 5. source file -> path 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); 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 // Line -> Procedure Name
@@ -31,10 +51,20 @@
RDI_U32 line_num = 2557; RDI_U32 line_num = 2557;
RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file 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_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_U64 name_size = 0; // 4. procedure -> name
RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size); 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 #endif
+2 -1
View File
@@ -442,7 +442,8 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count)
RDI_U64 j2_opl = range2->opl; RDI_U64 j2_opl = range2->opl;
for(;;) 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)); rdim_memcpy(dst + jd, src + j1, sizeof(*src));
j1 += 1; j1 += 1;
+2 -2
View File
@@ -41,12 +41,12 @@ bit_array_get_bit32(U32Array bit_array, U64 idx)
Assert(idx < bit_array.count*32); Assert(idx < bit_array.count*32);
U64 word_idx = idx / 32; U64 word_idx = idx / 32;
U64 bit_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; return bit;
} }
internal B32 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; U64 word_idx = bit_pos / 32;
Assert(word_idx < bit_arr.count); Assert(word_idx < bit_arr.count);
+1 -1
View File
@@ -3,7 +3,7 @@
#pragma once #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_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 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); internal void bit_array_set_bit32 (U32Array bit_array, U64 idx, B32 state);
+6 -93
View File
@@ -1,103 +1,16 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // 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" #include "third_party/blake3/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
#if defined(__aarch64__) || defined(_M_ARM64) #if defined(__aarch64__) || defined(_M_ARM64)
#include "third_party/blake3/c/blake3_neon.c" #include "third_party/blake3/blake3_neon.c"
#endif #endif
#include "third_party/blake3/c/blake3_dispatch.c" #include "third_party/blake3/blake3_dispatch.c"
#include "third_party/blake3/c/blake3.c" #include "third_party/blake3/blake3.c"
#if defined(__clang__) #if defined(_MSC_VER) && defined(_M_AMD64)
#pragma clang diagnostic pop #pragma comment (lib, "blake3")
#elif defined(_MSC_VER)
#pragma warning (pop, 0)
#endif #endif
+1 -1
View File
@@ -6,7 +6,7 @@
#define BLAKE3_API static #define BLAKE3_API static
#define BLAKE3_PRIVATE static #define BLAKE3_PRIVATE static
#include "third_party/blake3/c/blake3.h" #include "third_party/blake3/blake3.h"
static void static void
blake3(void* out, size_t outlen, void* in, size_t inlen) blake3(void* out, size_t outlen, void* in, size_t inlen)
+19 -19
View File
@@ -23,7 +23,7 @@ make_version(U64 major, U64 minor)
return version; return version;
} }
internal int internal force_inline int
version_compar(Version a, Version b) version_compar(Version a, Version b)
{ {
int cmp = 0; int cmp = 0;
@@ -48,7 +48,7 @@ isect_off(U32 isect, U32 off)
return result; return result;
} }
internal int internal force_inline int
u16_compar(const void *raw_a, const void *raw_b) u16_compar(const void *raw_a, const void *raw_b)
{ {
U16 a = *(U16*)raw_a; U16 a = *(U16*)raw_a;
@@ -59,7 +59,7 @@ u16_compar(const void *raw_a, const void *raw_b)
return result; return result;
} }
internal int internal force_inline int
u32_compar(const void *raw_a, const void *raw_b) u32_compar(const void *raw_a, const void *raw_b)
{ {
U32 a = *(U32*)raw_a; U32 a = *(U32*)raw_a;
@@ -70,7 +70,7 @@ u32_compar(const void *raw_a, const void *raw_b)
return result; return result;
} }
internal int internal force_inline int
u64_compar(const void *raw_a, const void *raw_b) u64_compar(const void *raw_a, const void *raw_b)
{ {
U64 a = *(const U64*)raw_a; U64 a = *(const U64*)raw_a;
@@ -79,7 +79,7 @@ u64_compar(const void *raw_a, const void *raw_b)
return result; return result;
} }
internal int internal force_inline int
u64_compar_inv(const void *raw_a, const void *raw_b) u64_compar_inv(const void *raw_a, const void *raw_b)
{ {
U64 a = *(const U64*)raw_a; U64 a = *(const U64*)raw_a;
@@ -88,7 +88,7 @@ u64_compar_inv(const void *raw_a, const void *raw_b)
return result; return result;
} }
internal int internal force_inline int
u16_compar_is_before(void *raw_a, void *raw_b) u16_compar_is_before(void *raw_a, void *raw_b)
{ {
U16 *a = (U16 *)raw_a; U16 *a = (U16 *)raw_a;
@@ -97,7 +97,7 @@ u16_compar_is_before(void *raw_a, void *raw_b)
return is_before; return is_before;
} }
internal int internal force_inline int
u32_compar_is_before(void *raw_a, void *raw_b) u32_compar_is_before(void *raw_a, void *raw_b)
{ {
U32 *a = (U32 *)raw_a; U32 *a = (U32 *)raw_a;
@@ -106,7 +106,7 @@ u32_compar_is_before(void *raw_a, void *raw_b)
return is_before; return is_before;
} }
internal int internal force_inline int
u64_compar_is_before(void *raw_a, void *raw_b) u64_compar_is_before(void *raw_a, void *raw_b)
{ {
U64 *a = (U64 *)raw_a; U64 *a = (U64 *)raw_a;
@@ -115,7 +115,7 @@ u64_compar_is_before(void *raw_a, void *raw_b)
return is_before; return is_before;
} }
internal int internal force_inline int
u8_is_before(void *raw_a, void *raw_b) u8_is_before(void *raw_a, void *raw_b)
{ {
U8 *a = (U8 *) raw_a; U8 *a = (U8 *) raw_a;
@@ -123,7 +123,7 @@ u8_is_before(void *raw_a, void *raw_b)
return *a < *b; return *a < *b;
} }
internal int internal force_inline int
u16_is_before(void *raw_a, void *raw_b) u16_is_before(void *raw_a, void *raw_b)
{ {
U16 *a = (U16 *) raw_a; U16 *a = (U16 *) raw_a;
@@ -131,7 +131,7 @@ u16_is_before(void *raw_a, void *raw_b)
return *a < *b; return *a < *b;
} }
internal int internal force_inline int
u32_is_before(void *raw_a, void *raw_b) u32_is_before(void *raw_a, void *raw_b)
{ {
U32 *a = (U32 *) raw_a; U32 *a = (U32 *) raw_a;
@@ -139,7 +139,7 @@ u32_is_before(void *raw_a, void *raw_b)
return *a < *b; return *a < *b;
} }
internal int internal force_inline int
u64_is_before(void *raw_a, void *raw_b) u64_is_before(void *raw_a, void *raw_b)
{ {
U64 *a = (U64 *) raw_a; U64 *a = (U64 *) raw_a;
@@ -147,7 +147,7 @@ u64_is_before(void *raw_a, void *raw_b)
return *a < *b; return *a < *b;
} }
internal int internal force_inline int
pair_u32_is_before_v0(void *raw_a, void *raw_b) pair_u32_is_before_v0(void *raw_a, void *raw_b)
{ {
PairU32 *a = raw_a; PairU32 *a = raw_a;
@@ -155,7 +155,7 @@ pair_u32_is_before_v0(void *raw_a, void *raw_b)
return a->v0 < b->v0; return a->v0 < b->v0;
} }
internal int internal force_inline int
pair_u32_is_before(void *raw_a, void *raw_b) pair_u32_is_before(void *raw_a, void *raw_b)
{ {
PairU32 *a = raw_a; PairU32 *a = raw_a;
@@ -163,7 +163,7 @@ pair_u32_is_before(void *raw_a, void *raw_b)
return a->v1 < b->v1; return a->v1 < b->v1;
} }
internal int internal force_inline int
pair_u64_is_before_v0(void *raw_a, void *raw_b) pair_u64_is_before_v0(void *raw_a, void *raw_b)
{ {
PairU64 *a = raw_a; PairU64 *a = raw_a;
@@ -171,7 +171,7 @@ pair_u64_is_before_v0(void *raw_a, void *raw_b)
return a->v0 < b->v0; return a->v0 < b->v0;
} }
internal int internal force_inline int
pair_u64_is_before_v1(void *raw_a, void *raw_b) pair_u64_is_before_v1(void *raw_a, void *raw_b)
{ {
PairU64 *a = raw_a; PairU64 *a = raw_a;
@@ -179,7 +179,7 @@ pair_u64_is_before_v1(void *raw_a, void *raw_b)
return a->v1 < b->v1; return a->v1 < b->v1;
} }
internal int internal force_inline int
pair_u32_compar_v0(const void *raw_a, const void *raw_b) pair_u32_compar_v0(const void *raw_a, const void *raw_b)
{ {
const PairU32 *a = raw_a; 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); 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) pair_u64_compar_v0(const void *raw_a, const void *raw_b)
{ {
const PairU64 *a = raw_a; 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); 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) pair_u64_compar_v1(const void *raw_a, const void *raw_b)
{ {
const PairU64 *a = raw_a; const PairU64 *a = raw_a;
+93
View File
@@ -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
+6
View File
@@ -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);
+33 -49
View File
@@ -1147,8 +1147,23 @@ cv_debug_t_from_data(Arena *arena, String8 data, U64 align)
{ {
CV_DebugT debug_t = { .data = data }; 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"); 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}; CV_Leaf leaf = {0};
TryRead(cv_read_leaf(data, cursor, align, &leaf), cursor, count_stop); 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; debug_t.source_counts[cv_type_index_source_from_leaf_kind(leaf.kind)] += 1;
@@ -1160,20 +1175,15 @@ count_stop:
ProfBegin("store leaf offsets"); ProfBegin("store leaf offsets");
debug_t.offsets = push_array_no_zero(arena, U32, debug_t.count); 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; debug_t.offsets[idx] = cursor;
TryRead(cv_read_leaf(data, cursor, align, &(CV_Leaf){0}), cursor, store_stop); TryRead(cv_read_leaf(data, cursor, align, &(CV_Leaf){0}), cursor, store_stop);
} }
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 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); }
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; }
}
ProfEnd(); ProfEnd();
return debug_t; 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); String8 sub_sect_data = str8_substr(c13_data, ss_range);
for (U64 cursor = 0; cursor + sizeof(CV_C13SubSecLinesHeader) <= sub_sect_data.size; ) { 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); CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader *)(sub_sect_data.str + cursor);
cursor += sizeof(*hdr); 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; lines_parsed_node->next = 0;
CV_C13LinesHeader *lines_parsed = &lines_parsed_node->v; 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_idx = hdr->sec;
lines_parsed->sec_off_lo = hdr->sec_off; lines_parsed->sec_off_lo = hdr->sec_off;
lines_parsed->sec_off_hi = hdr->sec_off + hdr->len; 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; 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 * internal CV_LinesAccel *
cv_c13_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines) 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; 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 internal U64
cv_nearest_line(CV_Line *arr, U64 count, U64 value) cv_nearest_line(CV_Line *arr, U64 count, U64 value)
{ {
if(count > 1 && arr[0].voff <= value && value < arr[count-1].voff) if(count > 1 && arr[0].voff <= value && value < arr[count-1].voff)
{ {
U64 l = 0; U64 l = 0;
U64 r = count - 1; U64 r = count;
for (; l <= r; ) { for (; l < r; ) {
U64 m = l + (r - l) / 2; U64 m = l + (r - l) / 2;
if (arr[m].voff == value) { if (arr[m].voff <= value) {
return m;
} else if (arr[m].voff < value) {
l = m + 1; l = m + 1;
} else { } else {
r = m - 1; r = m;
} }
} }
return l; return l - 1;
} }
else if (count == 1 && arr[0].voff == value) 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; 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) { if(accel->map[map_idx].voff != near_voff) {
break; break;
} }
+5 -2
View File
@@ -97,6 +97,7 @@ typedef struct CV_File
typedef struct CV_C13LinesHeader typedef struct CV_C13LinesHeader
{ {
U64 header_off;
U64 sec_idx; U64 sec_idx;
U64 sec_off_lo; U64 sec_off_lo;
U64 sec_off_hi; U64 sec_off_hi;
@@ -239,8 +240,10 @@ typedef struct CV_DebugT
Rng1U64 ti_ranges [CV_TypeIndexSource_COUNT]; Rng1U64 ti_ranges [CV_TypeIndexSource_COUNT];
// PCH // PCH
Rng1U64 pch_ti_range[CV_TypeIndexSource_COUNT]; B8 has_pch;
U32 pch_obj_idx; CV_PrecompInfo precomp;
Rng1U64 pch_ti_range[CV_TypeIndexSource_COUNT];
U32 pch_obj_idx;
} CV_DebugT; } CV_DebugT;
//////////////////////////////// ////////////////////////////////
+22 -14
View File
@@ -334,6 +334,7 @@ hash_table_purge_item(HashTable *ht, U64 hash, BucketNode *node)
{ {
U64 bucket_idx = hash % ht->cap; U64 bucket_idx = hash % ht->cap;
DLLRemove(ht->buckets[bucket_idx].first, ht->buckets[bucket_idx].last, node); 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; 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; } internal 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; } internal 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; } internal 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); } internal 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_path) { return str8_match(a->key_string, b->key_string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); }
internal U64 internal U64
hash_map_hash_from_path(String8 path) 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; 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 * internal void *
hash_map_search_raw_raw(HashMap *hm, void *key) hash_map_search_raw_raw(HashMap *hm, void *key)
{ {
@@ -941,29 +949,29 @@ hash_map_extract(Arena *arena,
} }
// { keys, value } // { 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; } 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 // keys
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_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)); } internal 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_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 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 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 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; } 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 // values
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_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_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 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; } 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; } 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; }
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_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_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_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); } internal void sort_hash_map_key_value_u64(HashMapKeyValue *pairs, U64 count) { radsort(pairs, count, hash_map_key_is_before_u64); }
+1
View File
@@ -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_path_raw (HashMap *hm, String8 key);
internal void * hash_map_search_u64_raw (HashMap *hm, U64 key); internal void * hash_map_search_u64_raw (HashMap *hm, U64 key);
internal U64 * hash_map_search_u64_u64 (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 void * hash_map_search_raw_raw (HashMap *hm, void *key);
internal U64 * hash_map_search_raw_u64 (HashMap *hm, void *key); internal U64 * hash_map_search_raw_u64 (HashMap *hm, void *key);
+27
View File
@@ -240,5 +240,32 @@
</Expand> </Expand>
</Type> </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> </AutoVisualizer>
+1174 -1112
View File
File diff suppressed because it is too large. Load diff
+9 -11
View File
@@ -64,6 +64,7 @@ typedef struct LNK_Inputer
LNK_InputList new_objs; LNK_InputList new_objs;
HashTable *libs_ht; HashTable *libs_ht;
HashTable *cmd_lib_names_ht;
HashTable *missing_lib_ht; HashTable *missing_lib_ht;
LNK_InputList libs; LNK_InputList libs;
LNK_InputList new_libs[LNK_InputSource_Count]; LNK_InputList new_libs[LNK_InputSource_Count];
@@ -98,6 +99,7 @@ typedef struct LNK_Link
LNK_LibList libs; LNK_LibList libs;
LNK_ObjNode **last_symbol_input; LNK_ObjNode **last_symbol_input;
LNK_IncludeSymbolNode **last_include; LNK_IncludeSymbolNode **last_include;
LNK_AltNameNode **last_func_override_alt_name;
String8Node **last_cmd_lib; String8Node **last_cmd_lib;
String8Node **last_default_lib; String8Node **last_default_lib;
String8Node **last_obj_lib; String8Node **last_obj_lib;
@@ -115,8 +117,9 @@ typedef struct LNK_LinkResult
// -- Image Layout ------------------------------------------------------------ // -- Image Layout ------------------------------------------------------------
#define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3 #define LNK_REMOVED_ASSOCIATIVE_SYMBOL_VALUE ((U32)-4)
#define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3 #define LNK_REMOVED_SECTION_NUMBER_32 ((U32)-3)
#define LNK_REMOVED_SECTION_NUMBER_16 ((U16)-3)
typedef struct LNK_ImageContext typedef struct LNK_ImageContext
{ {
@@ -130,7 +133,7 @@ typedef struct LNK_SectionDefinition
COFF_SectionFlags flags; COFF_SectionFlags flags;
U64 contribs_count; U64 contribs_count;
struct LNK_Obj *obj; struct LNK_Obj *obj;
U64 obj_sect_idx; U64 obj_section_number;
} LNK_SectionDefinition; } LNK_SectionDefinition;
typedef struct LNK_CommonBlockContrib typedef struct LNK_CommonBlockContrib
@@ -206,7 +209,6 @@ typedef struct LNK_BaseRelocPageArray
typedef struct typedef struct
{ {
B32 search_anti_deps; B32 search_anti_deps;
B32 reset_search_cursor;
LNK_Link *link; LNK_Link *link;
HashMap *imports_hm; HashMap *imports_hm;
LNK_SymbolTable *symtab; LNK_SymbolTable *symtab;
@@ -332,10 +334,6 @@ typedef struct
String8 image_data; String8 image_data;
} LNK_P2R; } LNK_P2R;
// --- Config -----------------------------------------------------------------
internal LNK_Config * lnk_config_from_cmdline(CmdLine *cmdline);
// --- Entry Point ------------------------------------------------------------- // --- Entry Point -------------------------------------------------------------
internal void lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config); 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_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_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 ----------------------------------------------------------------- // --- Inputer -----------------------------------------------------------------
@@ -380,9 +378,9 @@ 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_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 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 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); internal void lnk_inputer_release_file_maps(TP_Context *tp, LNK_Inputer *inputer);
// --- Link Context ------------------------------------------------------------ // --- Link Context ------------------------------------------------------------
+20 -57
View File
@@ -15,7 +15,7 @@ lnk_arg_list_parse_windows_rules(Arena *arena, String8 string)
while(ptr < opl) { while(ptr < opl) {
U64 size = (U64)(opl - ptr); U64 size = (U64)(opl - ptr);
UnicodeDecode uni = utf8_decode(ptr, size); 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; break;
} }
ptr += uni.inc; ptr += uni.inc;
@@ -31,7 +31,7 @@ lnk_arg_list_parse_windows_rules(Arena *arena, String8 string)
UnicodeDecode uni; UnicodeDecode uni;
uni = utf8_decode(ptr, (U64)(opl-ptr)); 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; break;
} }
@@ -89,12 +89,12 @@ lnk_cmd_line_push_option_node(LNK_CmdLine *cmd_line, LNK_CmdOption *opt)
} }
internal LNK_CmdOption * 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 // fill out node
LNK_CmdOption *opt = push_array(arena, LNK_CmdOption, 1); LNK_CmdOption *opt = push_array(arena, LNK_CmdOption, 1);
opt->string = string; opt->string = string;
opt->value_strings = value_strings; opt->value = value;
// push node // push node
lnk_cmd_line_push_option_node(cmd_line, opt); 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; 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 * internal LNK_CmdOption *
lnk_cmd_line_push_option(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value) 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) lnk_cmd_line_concat_in_place(LNK_CmdLine *list, LNK_CmdLine *to_concat)
{ {
if (list->option_count > 0) { if (list->option_count > 0) {
list->option_count += to_concat->option_count; if (to_concat->option_count > 0) {
list->last_option->next = to_concat->first_option; list->option_count += to_concat->option_count;
list->last_option = to_concat->last_option; 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->input_list, &to_concat->input_list);
str8_list_concat_in_place(&list->raw_cmd_line, &to_concat->raw_cmd_line); str8_list_concat_in_place(&list->raw_cmd_line, &to_concat->raw_cmd_line);
} else { } else {
@@ -147,11 +141,9 @@ lnk_cmd_line_parse_windows_rules(Arena *arena, String8List arg_list)
LNK_CmdLine cmd_line = {0}; LNK_CmdLine cmd_line = {0};
cmd_line.raw_cmd_line = str8_list_copy(arena, &arg_list); 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; String8 arg = arg_node->string;
B32 is_option = str8_match_lit("/", arg, StringMatchFlag_RightSideSloppy) || if (str8_starts_with(arg, str8_lit("/")) || str8_starts_with(arg, str8_lit("-"))) {
str8_match_lit("-", arg, StringMatchFlag_RightSideSloppy);
if (is_option) {
U64 param_start_pos = str8_find_needle(arg, 0, str8_lit(":"), 0); U64 param_start_pos = str8_find_needle(arg, 0, str8_lit(":"), 0);
String8 option_name = str8_chop(arg, arg.size - param_start_pos); 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 ':' // skip ':'
String8 value_string = str8_skip(arg, param_start_pos + 1); 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 // push command
option_name = push_str8_copy(arena, option_name); 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 { } else {
str8_list_push(arena, &cmd_line.input_list, push_str8_copy(arena, arg)); 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; LNK_CmdOption *opt;
for (opt = cmd_line.first_option; opt != NULL; opt = opt->next) { 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; break;
} }
} }
@@ -228,42 +219,14 @@ lnk_data_from_cmd_line(Arena *arena, LNK_CmdLine cmd_line)
{ {
String8List result = {0}; String8List result = {0};
for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) { for EachNode(opt, LNK_CmdOption, cmd_line.first_option) {
// separate directives // separate commands
if (opt != cmd_line.first_option) { if (opt != cmd_line.first_option) {
str8_list_pushf(arena, &result, " "); str8_list_pushf(arena, &result, " ");
} }
// push new directive // push command line option
str8_list_pushf(arena, &result, "/%.*s", str8_varg(opt->string)); str8_list_pushf(arena, &result, "/%S%s%S", opt->string, opt->value.size ? ":" : "", opt->value);
// 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));
} }
return result; return result;
Loaded 100 of 267 files, more files were not shown because too many files have changed in this diff. Show more