XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
param(
    [string]$ToolRoot = '',
    [string]$ProbeDirectory,
    [string]$OutputDirectory = ''
)
$ErrorActionPreference = 'Stop'
$taskRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../..'))
. (Join-Path $PSScriptRoot 'InputHashes.ps1')
. (Join-Path $taskRoot 'Tools/TlsEntropyPatch/VerifyReceipt.ps1')
if(!$ToolRoot) { $ToolRoot=Join-Path $taskRoot '.tools' }
& (Join-Path $PSScriptRoot 'VerifyToolchain.ps1')
if (!$ProbeDirectory) { throw 'Provide the directory returned by CompileProbe.ps1.' }
$probe = [IO.Path]::GetFullPath($ProbeDirectory)
$probeReceipt = Get-Content -Raw -Encoding UTF8 -LiteralPath (Join-Path $probe 'ProbeReceipt.json') | ConvertFrom-Json
$probeReceiptHash=Get-RuntimeInputHash (Join-Path $probe 'ProbeReceipt.json')
if (!$probeReceipt.ElfObjectGenerated -or $probeReceipt.CosmosReferenced) { throw 'The probe is not an independently compiled ELF object.' }
if ((Get-FileHash -LiteralPath $probeReceipt.ObjectPath -Algorithm SHA256).Hash.ToLowerInvariant() -cne $probeReceipt.ObjectSha256) { throw 'The managed ELF object differs from its receipt.' }
$tlsEntropyPort=$null
if(@($probeReceipt.AssemblySha256.PSObject.Properties | Where-Object {[IO.Path]::GetFileName($_.Name) -ceq 'BouncyCastle.Cryptography.dll'}).Count -gt 0) {
    $tlsEntropyPort=Assert-XfeNativeEntropyPort $taskRoot $probeReceipt.NativeTlsEntropyPort
    foreach($pair in @(@('BouncyCastlePath','BouncyCastleSha256'),@('AdapterPath','AdapterSha256'))) {
        $entry=$probeReceipt.AssemblySha256.PSObject.Properties[[string]$tlsEntropyPort.($pair[0])]
        if(!$entry -or $entry.Value -cne $tlsEntropyPort.($pair[1])) {throw 'The entropy port is not the BC/adapter supplied to ILC.'}
    }
}
if (!$OutputDirectory) { $OutputDirectory = Join-Path $taskRoot ('build/IndependentKernel/RuntimePort/Port-' + [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()) }
$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory)
[void][IO.Directory]::CreateDirectory($OutputDirectory)
$taskNugetRoot = if ($env:NUGET_PACKAGES) { $env:NUGET_PACKAGES } else { Join-Path ([Environment]::GetFolderPath('UserProfile')) '.nuget/packages' }
$pack = Join-Path $taskNugetRoot 'microsoft.netcore.app.runtime.nativeaot.linux-x64/10.0.12'
$native = Join-Path $pack 'runtimes/linux-x64/native'
$llvm = Join-Path $ToolRoot 'llvm/bin'
$original = Join-Path $native 'libRuntime.WorkstationGC.a'
$runtime = Join-Path $OutputDirectory 'libXfeMicrosoftRuntime.a'
Copy-Item -LiteralPath $original -Destination $runtime
$removed = @('PalUnix.cpp.o','PalCreateDump.cpp.o','gcenv.unix.cpp.o','numasupport.cpp.o','cgroup.cpp.o','cgroupcpu.cpp.o','events.cpp.o','HardwareExceptions.cpp.o','UnixSignals.cpp.o')
$before = @(& (Join-Path $llvm 'llvm-ar.exe') t $runtime)
foreach ($member in $removed) { if ($before -notcontains $member) { throw ('The pinned runtime member is unavailable: ' + $member) } }
& (Join-Path $llvm 'llvm-ar.exe') d $runtime @removed
if ($LASTEXITCODE -ne 0) { throw 'Filtering the private runtime copy failed.' }
$after = @(& (Join-Path $llvm 'llvm-ar.exe') t $runtime)
foreach ($member in $removed) { if ($after -contains $member) { throw ('Removed PAL member is still present: ' + $member) } }
$objects = @()
$sources = @('NativePal.cpp','KernelPalBridge.cpp','RuntimeStart.cpp','Native/ThreadLocal.c','Native/SystemNativeShim.cpp','Native/RuntimeLocks.cpp','Native/HardwareDivide.cpp','Native/NativeEntropy.c')
foreach ($support in @('Native/BasicLibc.c','Native/Stdio.c','Native/PosixSupport.cpp','Native/SystemNativeExtras.cpp')) {
    if (Test-Path -LiteralPath (Join-Path $taskRoot ('Source/XFESystem.NativeRuntime/' + $support))) { $sources += $support }
}
$sourceHashes=[ordered]@{}
foreach($source in $sources) {
    $path=Join-Path $taskRoot ('Source/XFESystem.NativeRuntime/'+$source)
    $sourceHashes[(Get-RuntimeRelativeInput $taskRoot $path)]=Get-RuntimeInputHash $path
}
foreach($path in @($PSCommandPath,(Join-Path $PSScriptRoot 'InputHashes.ps1'),(Join-Path $taskRoot 'Tools/TlsEntropyPatch/VerifyReceipt.ps1'),(Join-Path $PSScriptRoot 'VerifyToolchain.ps1'),(Join-Path $PSScriptRoot 'NativeToolchain.json'),(Join-Path $PSScriptRoot 'NativeToolchain.csproj'),(Join-Path $taskRoot 'Source/XFESystem.NativeRuntime/NativePal.h'))) {
    $sourceHashes[(Get-RuntimeRelativeInput $taskRoot $path)]=Get-RuntimeInputHash $path
}
foreach($path in Get-ChildItem -LiteralPath (Join-Path $taskRoot 'Source/XFESystem.NativeRuntime/Native') -File -Filter '*.h') {
    $sourceHashes[(Get-RuntimeRelativeInput $taskRoot $path.FullName)]=Get-RuntimeInputHash $path.FullName
}
foreach($path in Get-ChildItem -LiteralPath (Join-Path $taskRoot 'Source/XFESystem.NativeRuntime/ThirdParty') -File -Recurse) {
    $sourceHashes[(Get-RuntimeRelativeInput $taskRoot $path.FullName)]=Get-RuntimeInputHash $path.FullName
}
if($probeReceipt.SourceSha256) {
    foreach($property in $probeReceipt.SourceSha256.PSObject.Properties) { $sourceHashes[$property.Name]=$property.Value }
}
Assert-RuntimeSourceInputs $taskRoot $sourceHashes
foreach ($source in $sources) {
    $sourcePath = Join-Path $taskRoot ('Source/XFESystem.NativeRuntime/' + $source)
    $objectPath = Join-Path $OutputDirectory ([IO.Path]::GetFileNameWithoutExtension($source) + '.o')
    $compiler = if ($source.EndsWith('.cpp')) { 'clang++.exe' } else { 'clang.exe' }
    $args = @('--target=x86_64-unknown-none-elf','-ffreestanding','-fno-builtin','-fno-stack-protector','-fasynchronous-unwind-tables','-mno-red-zone','-mcmodel=large','-O2','-c',$sourcePath,'-o',$objectPath)
    if ($source.EndsWith('.cpp')) { $args += @('-fno-exceptions','-fno-rtti','-std=c++17') }
    if ($source -eq 'Native/ThreadLocal.c') { $args += '-ftls-model=local-exec' }
    $ErrorActionPreference = 'Continue'
    & (Join-Path $llvm $compiler) @args > (Join-Path $OutputDirectory ([IO.Path]::GetFileNameWithoutExtension($source) + '.log')) 2>&1
    $compileExit = $LASTEXITCODE
    $ErrorActionPreference = 'Stop'
    if ($compileExit -ne 0) { throw ('Native port compilation failed: ' + $source) }
    $objects += $objectPath
}
$libraries = @('libRuntime.VxsortDisabled.a','libaotminipal.a','libeventpipe-disabled.a','libstandalonegc-disabled.a','libstdc++compat.a') | ForEach-Object { Join-Path $native $_ }
$runtimeHashes=[ordered]@{}
foreach($path in (@($original,$runtime)+$libraries)) { $runtimeHashes[$path]=Get-RuntimeInputHash $path }
$combined = Join-Path $OutputDirectory 'ManagedRuntimePort.o'
& (Join-Path $llvm 'ld.lld.exe') -r -u XfeRuntimeStart $probeReceipt.ObjectPath @objects $runtime @libraries -o $combined > (Join-Path $OutputDirectory 'PartialLink.log') 2>&1
if ($LASTEXITCODE -ne 0) { throw 'The official runtime and independent PAL cannot be combined; see PartialLink.log.' }
$symbols = @(& (Join-Path $llvm 'llvm-nm.exe') --undefined-only --format=posix $combined | ForEach-Object { ($_ -split ' ')[0] } | Sort-Object -Unique)
[IO.File]::WriteAllLines((Join-Path $OutputDirectory 'UndefinedObjectSymbols.txt'), $symbols, [Text.UTF8Encoding]::new($false))
$ErrorActionPreference = 'Continue'
$linkOutput = @(& (Join-Path $llvm 'ld.lld.exe') -static -nostdlib --error-limit=0 -e XfeRuntimeStart $probeReceipt.ObjectPath @objects $runtime @libraries -o (Join-Path $OutputDirectory 'UnsupportedWithoutKernel.elf') 2>&1)
$linkExit = $LASTEXITCODE
$ErrorActionPreference = 'Stop'
[IO.File]::WriteAllLines((Join-Path $OutputDirectory 'KernelServicesRequired.log'), @($linkOutput | ForEach-Object { $_.ToString() }), [Text.UTF8Encoding]::new($false))
$actualMissing = @($linkOutput | ForEach-Object { if ($_.ToString() -match '^ld.lld: error: undefined symbol: (.+)$') { $Matches[1] } } | Sort-Object -Unique)
[IO.File]::WriteAllLines((Join-Path $OutputDirectory 'ActualMissingLinkSymbols.txt'), $actualMissing, [Text.UTF8Encoding]::new($false))
Copy-Item -LiteralPath (Join-Path $pack 'LICENSE.TXT') -Destination (Join-Path $OutputDirectory 'MicrosoftNativeAOT.LICENSE.TXT')
Copy-Item -LiteralPath (Join-Path $pack 'THIRD-PARTY-NOTICES.TXT') -Destination (Join-Path $OutputDirectory 'MicrosoftNativeAOT.THIRD-PARTY-NOTICES.TXT')
Assert-RuntimeSourceInputs $taskRoot $sourceHashes
if((Get-RuntimeInputHash (Join-Path $probe 'ProbeReceipt.json')) -cne $probeReceiptHash) { throw 'Managed probe receipt changed during native compilation.' }
if($tlsEntropyPort) {$null=Assert-XfeNativeEntropyPort $taskRoot $tlsEntropyPort}
foreach($entry in $runtimeHashes.GetEnumerator()) { if((Get-RuntimeInputHash $entry.Key) -cne $entry.Value) { throw ('An external runtime library changed: '+$entry.Key) } }
$objectHashes=[ordered]@{}
foreach($path in $objects) { $objectHashes[$path]=Get-RuntimeInputHash $path }
$finalInputs=@($probeReceipt.ObjectPath)+@($objects)+@($runtime)+@($libraries)
$finalHashes=[ordered]@{}
foreach($path in $finalInputs) { $finalHashes[$path]=Get-RuntimeInputHash $path }
$receipt = [ordered]@{
    Schema = 'XfeIndependentNativeRuntimePort1'; MicrosoftRuntimeVersion = '10.0.12'
    MicrosoftSourceRepository = 'https://github.com/dotnet/dotnet'; MicrosoftSourceCommit = '95017c711e6afc1085133d440e42b4bd78155701'
    MicrosoftPackage = 'Microsoft.NETCore.App.Runtime.NativeAOT.linux-x64'; CosmosReferenced = $false
    RemovedPlatformObjects = $removed; OriginalRuntimeSha256 = (Get-FileHash -LiteralPath $original -Algorithm SHA256).Hash.ToLowerInvariant()
    FilteredRuntimeSha256 = (Get-FileHash -LiteralPath $runtime -Algorithm SHA256).Hash.ToLowerInvariant()
    SourceSha256 = $sourceHashes; AssemblySha256 = $probeReceipt.AssemblySha256
    RuntimeLibrariesSha256 = $runtimeHashes; NativeObjectsSha256 = $objectHashes
    FinalLinkInputs = $finalInputs; FinalLinkInputsSha256 = $finalHashes
    CombinedObjectSha256 = (Get-RuntimeInputHash $combined); ProbeObjectSha256 = $probeReceipt.ObjectSha256
    ProbeReceiptSha256 = $probeReceiptHash
    NativeTlsEntropyPort = $tlsEntropyPort
    NativeCompilerSha256 = (Get-RuntimeInputHash (Join-Path $llvm 'clang.exe')); NativeCppCompilerSha256 = (Get-RuntimeInputHash (Join-Path $llvm 'clang++.exe'))
    NativePortCompilationPassed = $true; RelocatableRuntimeLinkPassed = $true
    FinalExecutableLinkExitCode = $linkExit; FinalExecutableSupported = ($linkExit -eq 0)
    ActualMissingLinkSymbols = $actualMissing; NativeGuestTested = $false
    GarbageCollectionExecuted = $false; ExceptionHandlingExecuted = $false; ManagedThreadExecuted = $false
    RuntimeArchivePath = $runtime; NativeObjects = $objects; CombinedObjectPath = $combined; ProbeReceipt = (Join-Path $probe 'ProbeReceipt.json')
    CombinedObjectPurpose = 'Symbol inspection only; final ELF links the original objects and archives once to preserve COMDAT unwind associations.'
}
$receipt | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'PortReceipt.json') -Encoding UTF8
Write-Output ('Independent PAL compiled; actual remaining native link symbols: ' + $actualMissing.Count)
Write-Output ('Receipt: ' + (Join-Path $OutputDirectory 'PortReceipt.json'))