From edc80a0957f753802355903465381b3eb2e67685 Mon Sep 17 00:00:00 2001 From: Nick Hastings Date: Sun, 21 May 2023 12:07:22 -0400 Subject: [PATCH] Add dll2lib helper script --- support/dll2lib.ps1 | 96 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 support/dll2lib.ps1 diff --git a/support/dll2lib.ps1 b/support/dll2lib.ps1 new file mode 100644 index 0000000..0f1cae3 --- /dev/null +++ b/support/dll2lib.ps1 @@ -0,0 +1,96 @@ +<# +.SYNOPSIS + Generate a .lib file for linking to a dll. +.DESCRIPTION + This script generates a .lib from from a dynamic link library (dll) file. + + The .lib file can then be linked against to resolve symbols in the dll file. +.PARAMETER InputBinary + The path to the dll file. +.PARAMETER OutPath + The output folder in which to save the .lib file. Defaults to the directory of the dll file. + + The folder must already exist. +#> +[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] +param( + [Parameter(Mandatory, ValueFromPipeline)] + [ValidateScript({($_ -match '\.dll$') -and (Test-Path -Path $_ -PathType Leaf)})] + [string]$InputBinary, + + [Parameter()] + [ValidateScript({Test-Path -Path $_ -PathType Container})] + [string]$OutPath, + + [Parameter()] + [switch]$Force +) + +try { + $dumpbinBin = (Get-Command -Name 'dumpbin.exe').Source +} catch { + throw 'Could not find dumpbin.exe in PATH. (Are you running from a Developer Command Prompt?)' +} + +Write-Verbose "Found dumpbin.exe at '$dumpbinBin'" + +try { + $libBin = (Get-Command -Name 'lib.exe').Source +} catch { + throw 'Could not find lib.exe in PATH. (Are you running from a Developer Command Prompt?)' +} + +Write-Verbose "Found lib.exe at '$libBin'" + +$inputBinInfo = Get-Item -Path $InputBinary + +$defTempPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ('{0}.def' -f $inputBinInfo.BaseName) + +if (-not $OutPath) { + $OutPath = $inputBinInfo.DirectoryName +} + +Write-Verbose "Using output path '$OutPath'" + +$outLibFullName = Join-Path -Path $OutPath -ChildPath ('{0}.lib' -f $inputBinInfo.BaseName) +if ((-not (Test-Path -Path $outLibFullName)) -or $PSCmdlet.ShouldProcess($outLibFullName, 'overwrite')) +{ + $archCode = ((. $dumpbinBin /headers $inputBinInfo.FullName | Select-String -Context 1 -SimpleMatch -Pattern 'FILE HEADER VALUES' -CaseSensitive).Context.PostContext | Select-String -Pattern '^\s*([A-Z0-9]+) machine \(.*\)$' -CaseSensitive).Matches[0].Groups[1].Value + switch ($archCode) + { + '14C' { $arch = 'X86' } + '8664' { $arch = 'X64' } + 'AA64' { $arch = 'ARM64' } + default { + if ([Environment]::Is64BitOperatingSystem) { + $arch = 'X64' + } else { + $arch = 'X86' + } + # TODO: Add ARM64 detection fallback + + Write-Warning "Unable to determine arch of binary. Defaulting to $arch for lib." + } + } + + Write-Verbose "Using arch '$arch' for lib generation." + + $funcs = . $dumpbinBin /exports $inputBinInfo.FullName | + Select-String -Pattern '^\s+\d+\s+[A-Z0-9]+\s+[A-Z0-9]+\s+(.+)$' -CaseSensitive | + Select-Object -ExpandProperty 'Matches' | + ForEach-Object -Process { + $_.Groups[1].Value + } + + Write-Verbose "Found $($funcs.Count) functions in '$InputBinary'" + + Write-Verbose "Creating def file at '$defTempPath'" + 'EXPORTS' | Out-File $defTempPath -Force + $funcs | Out-File $defTempPath -Append + + Write-Verbose "Calling lib.exe to generate '$outLibFullName'" + . $libBin /def:$defTempPath /OUT:$outLibFullName /MACHINE:$arch + + Write-Verbose "Removing temp def file at '$defTempPath'" + Remove-Item -Path $defTempPath -Confirm:$false +} \ No newline at end of file