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