-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pe: Add tests for TLS parser and characteristics constants (#426)
* pe: add tests for TLS parser and characteristics constants * Fix panic on malformed callbacks may cause subtract with overflow * Add reproducible cxx project
- Loading branch information
1 parent
48da3d8
commit 19d88ec
Showing
12 changed files
with
825 additions
and
1 deletion.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
cmake_minimum_required(VERSION 3.12) | ||
project(bingen LANGUAGES CXX) | ||
option(ENABLE_TLS "Whether to generate TLS in resulting binary" ON) | ||
|
||
if(ENABLE_TLS) | ||
add_definitions(-DENABLE_TLS) | ||
endif() | ||
|
||
set(CMAKE_SYSTEM_NAME Windows) | ||
|
||
add_executable(bin WIN32 "main.cc") | ||
set_target_properties(bin PROPERTIES LANGUAGE CXX) | ||
target_compile_options(bin PRIVATE | ||
/GS- # Disable generation of stack check handlers | ||
/GL # Enable whole program optimization | ||
) | ||
target_link_options(bin PRIVATE | ||
/ENTRY:main # Explicit entry symbol since there are no CRT/libs to be linked | ||
/MANIFEST:NO # Disable manifest | ||
/NODEFAULTLIB # No libs; we want a pure binary | ||
/FIXED # No relocs | ||
/DYNAMICBASE:NO # No ASLR | ||
/SAFESEH # No unwinds | ||
/MERGE:.data=.text /MERGE:.CRT=.text /MERGE:.tls=.text # Combine sections to avoid paddings | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Test binary generator for Portable Executable | ||
|
||
## Preprocessor definitions | ||
|
||
- `ENABLE_TLS`: if defined, compile the binary with Thread Local Storage (TLS) enabled. | ||
|
||
## How to build | ||
|
||
This project is designed to be compiled by Clang (`clang-cl`) _not_ MSVC toolchain, primarily because 1) MSVC linker supports more features and may unexpectedly generate larger binaries than LLD linker under Clang, 2) compiler and linker flags are designed for specifically Clang for best efforts in reducing size of the resulting binary, 3) sometimes LLD links much smarter e.g., metadatas such as unnecessary rich headers (can be disabled by `/EMITTOOLVERSIONINFO:NO`). | ||
|
||
While MSVC toolchains are theoretically possible; but not recommended. | ||
|
||
### CMake | ||
|
||
**Prerequisites** | ||
- 64-bit Windows host | ||
- CMake 3.12 or later | ||
- [Ninja build system](https://ninja-build.org) (any version) | ||
- Clang (ideally 17 or later) | ||
|
||
Firstly run the following commands on terminal: | ||
|
||
```bash | ||
mkdir build | ||
``` | ||
|
||
```bash | ||
cd build | ||
``` | ||
|
||
```bash | ||
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang-cl | ||
``` | ||
|
||
Then build the binary: | ||
|
||
```bash | ||
cmake --build . --config release | ||
``` | ||
|
||
### Visual Studio | ||
|
||
**Prerequisites** | ||
- 64-bit Windows host | ||
- Visual Studio 2022 (editions do not matter) | ||
- C++ Clang Compiler for Windows [or this method if you have manual installation](#optional-referencing-manually-installed-clang-toolchain) | ||
- MSBuild support for LLVM (clang-cl) toolset | ||
|
||
Open `bingen.sln` under [`etc/projects/bingen`](etc/projects/bingen/) and compile as Release (Debug configuration is redacted). | ||
|
||
#### Optional: Referencing manually-installed Clang toolchain | ||
|
||
If you do not have or not willing to install Clang under Visual Studio individual components, [customize the build by folder for MSBuild](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) by deploying following `Directory.build.props` right next to the `.sln`: | ||
|
||
```xml | ||
<!-- Directory.build.props --> | ||
<Project> | ||
<PropertyGroup> | ||
<LLVMInstallDir>C:/path/to/llvm/bin</LLVMInstallDir> | ||
<LLVMToolsVersion>xx.xxxx.x</LLVMToolsVersion> | ||
</PropertyGroup> | ||
</Project> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.12.35527.113 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bingen", "bingen.vcxproj", "{45EE6877-125F-49B9-9837-D91D38F6C2A3}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Release|x64 = Release|x64 | ||
Release|x86 = Release|x86 | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{45EE6877-125F-49B9-9837-D91D38F6C2A3}.Release|x64.ActiveCfg = Release|x64 | ||
{45EE6877-125F-49B9-9837-D91D38F6C2A3}.Release|x64.Build.0 = Release|x64 | ||
{45EE6877-125F-49B9-9837-D91D38F6C2A3}.Release|x86.ActiveCfg = Release|Win32 | ||
{45EE6877-125F-49B9-9837-D91D38F6C2A3}.Release|x86.Build.0 = Release|Win32 | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<ItemGroup Label="ProjectConfigurations"> | ||
<ProjectConfiguration Include="Release|Win32"> | ||
<Configuration>Release</Configuration> | ||
<Platform>Win32</Platform> | ||
</ProjectConfiguration> | ||
<ProjectConfiguration Include="Release|x64"> | ||
<Configuration>Release</Configuration> | ||
<Platform>x64</Platform> | ||
</ProjectConfiguration> | ||
</ItemGroup> | ||
<PropertyGroup Label="Globals"> | ||
<ProjectGuid>{45EE6877-125F-49B9-9837-D91D38F6C2A3}</ProjectGuid> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<ClCompile Include="main.cc" /> | ||
</ItemGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | ||
<ConfigurationType>Application</ConfigurationType> | ||
<UseDebugLibraries>false</UseDebugLibraries> | ||
<PlatformToolset>v143</PlatformToolset> | ||
<WholeProgramOptimization>true</WholeProgramOptimization> | ||
<CharacterSet>Unicode</CharacterSet> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | ||
<ConfigurationType>Application</ConfigurationType> | ||
<UseDebugLibraries>false</UseDebugLibraries> | ||
<PlatformToolset>ClangCL</PlatformToolset> | ||
<WholeProgramOptimization>true</WholeProgramOptimization> | ||
<CharacterSet>Unicode</CharacterSet> | ||
</PropertyGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||
<ImportGroup Label="ExtensionSettings"> | ||
</ImportGroup> | ||
<ImportGroup Label="Shared"> | ||
</ImportGroup> | ||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||
</ImportGroup> | ||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||
</ImportGroup> | ||
<PropertyGroup Label="UserMacros" /> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
<GenerateManifest>false</GenerateManifest> | ||
</PropertyGroup> | ||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||
<ClCompile> | ||
<WarningLevel>Level3</WarningLevel> | ||
<FunctionLevelLinking>true</FunctionLevelLinking> | ||
<IntrinsicFunctions>true</IntrinsicFunctions> | ||
<SDLCheck>true</SDLCheck> | ||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
<ConformanceMode>true</ConformanceMode> | ||
</ClCompile> | ||
<Link> | ||
<SubSystem>Console</SubSystem> | ||
<EnableCOMDATFolding>true</EnableCOMDATFolding> | ||
<OptimizeReferences>true</OptimizeReferences> | ||
<GenerateDebugInformation>true</GenerateDebugInformation> | ||
</Link> | ||
</ItemDefinitionGroup> | ||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
<ClCompile> | ||
<WarningLevel>Level3</WarningLevel> | ||
<FunctionLevelLinking>true</FunctionLevelLinking> | ||
<IntrinsicFunctions>true</IntrinsicFunctions> | ||
<SDLCheck>true</SDLCheck> | ||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ENABLE_TLS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||
<ConformanceMode>true</ConformanceMode> | ||
<BufferSecurityCheck>false</BufferSecurityCheck> | ||
</ClCompile> | ||
<Link> | ||
<SubSystem>Console</SubSystem> | ||
<EnableCOMDATFolding>true</EnableCOMDATFolding> | ||
<OptimizeReferences>true</OptimizeReferences> | ||
<GenerateDebugInformation>false</GenerateDebugInformation> | ||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> | ||
<EntryPointSymbol>main</EntryPointSymbol> | ||
<RandomizedBaseAddress>false</RandomizedBaseAddress> | ||
<FixedBaseAddress>true</FixedBaseAddress> | ||
<MergeSections>/MERGE:.data=.text /MERGE:.CRT=.text /MERGE:.tls=.text</MergeSections> | ||
<ImageHasSafeExceptionHandlers>true</ImageHasSafeExceptionHandlers> | ||
</Link> | ||
</ItemDefinitionGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||
<ImportGroup Label="ExtensionTargets"> | ||
</ImportGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include <Windows.h> | ||
|
||
#if !(_WIN64) | ||
#error "Only x64 is supported" | ||
#endif | ||
|
||
#ifdef ENABLE_TLS | ||
EXTERN_C unsigned int _tls_index{}; | ||
static void NTAPI tls_callback(PVOID, DWORD, PVOID) {} | ||
|
||
// Force include unreferenced symbols | ||
// Marker symbol to tell the linker that TLS is being used | ||
#pragma comment(linker, "/INCLUDE:_tls_used") | ||
#pragma comment(linker, "/INCLUDE:_tls_callback") | ||
|
||
#pragma data_seg(".tls") | ||
int _tls_start = 0; | ||
#pragma const_seg() | ||
|
||
#pragma data_seg(".tls$ZZZ") | ||
int _tls_end = 0; | ||
#pragma const_seg() | ||
|
||
#pragma data_seg(".CRT$XLA") | ||
int __xl_a = 0; | ||
#pragma const_seg() | ||
|
||
#pragma data_seg(".CRT$XLZ") | ||
int __xl_z = 0; | ||
#pragma const_seg() | ||
|
||
#pragma const_seg(".CRT$XLB") | ||
EXTERN_C const PIMAGE_TLS_CALLBACK _tls_callback[] = { &tls_callback, 0 }; | ||
#pragma const_seg() | ||
|
||
EXTERN_C IMAGE_TLS_DIRECTORY _tls_used = { | ||
/*StartAddressOfRawData*/(ULONG64)&_tls_start, | ||
/*EndAddressOfRawData*/(ULONG64)&_tls_end, | ||
/*AddressOfIndex*/(ULONG64)&_tls_index, | ||
/*AddressOfCallbacks*/(ULONG64)&_tls_callback, | ||
/*SizeOfZeroFill*/0, | ||
/*Characteristics*/{0}, | ||
}; | ||
#endif // #ifdef ENABLE_TLS | ||
|
||
int main() { return 0; } |
Oops, something went wrong.