diff --git a/.venv312/Scripts/Activate.ps1 b/.venv312/Scripts/Activate.ps1 new file mode 100644 index 0000000000..918eac3e8e --- /dev/null +++ b/.venv312/Scripts/Activate.ps1 @@ -0,0 +1,528 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" + +# SIG # Begin signature block +# MII0CQYJKoZIhvcNAQcCoIIz+jCCM/YCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk +# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCG9IwggXMMIIDtKADAgECAhBUmNLR1FsZ +# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK +# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu +# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy +# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT +# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv +# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo +# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD +# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH +# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD +# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV +# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70 +# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1 +# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3 +# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK +# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg +# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj +# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7 +# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE +# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ +# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn +# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c +# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF +# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx +# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8 +# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY +# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2 +# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY +# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al +# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk +# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T +# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggb+MIIE5qADAgECAhMzAAM/y2Wy +# WWnFfpZcAAAAAz/LMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD +# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ +# RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDEwHhcNMjUwNDA4MDEwNzI0WhcNMjUwNDEx +# MDEwNzI0WjB8MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQH +# EwlCZWF2ZXJ0b24xIzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9u +# MSMwIQYDVQQDExpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAaIwDQYJKoZI +# hvcNAQEBBQADggGPADCCAYoCggGBAI0elXEcbTdGLOszMU2fzimHGM9Y4EjwFgC2 +# iGPdieHc0dK1DyEIdtnvjKxnG/KICC3J2MrhePGzMEkie3yQjx05B5leG0q8YoGU +# m9z9K67V6k3DSXX0vQe9FbaNVuyXed31MEf/qek7Zo4ELxu8n/LO3ibURBLRHNoW +# Dz9zr4DcU+hha0bdIL6SnKMLwHqRj59gtFFEPqXcOVO7kobkzQS3O1T5KNL/zGuW +# UGQln7fS4YI9bj24bfrSeG/QzLgChVYScxnUgjAANfT1+SnSxrT4/esMtfbcvfID +# BIvOWk+FPPj9IQWsAMEG/LLG4cF/pQ/TozUXKx362GJBbe6paTM/RCUTcffd83h2 +# bXo9vXO/roZYk6H0ecd2h2FFzLUQn/0i4RQQSOp6zt1eDf28h6F8ev+YYKcChph8 +# iRt32bJPcLQVbUzhehzT4C0pz6oAqPz8s0BGvlj1G6r4CY1Cs2YiMU09/Fl64pWf +# IsA/ReaYj6yNsgQZNUcvzobK2mTxMwIDAQABo4ICGTCCAhUwDAYDVR0TAQH/BAIw +# ADAOBgNVHQ8BAf8EBAMCB4AwPAYDVR0lBDUwMwYKKwYBBAGCN2EBAAYIKwYBBQUH +# AwMGGysGAQQBgjdhgqKNuwqmkohkgZH0oEWCk/3hbzAdBgNVHQ4EFgQU4Y4Xr/Xn +# zEXblXrNC0ZLdaPEJYUwHwYDVR0jBBgwFoAU6IPEM9fcnwycdpoKptTfh6ZeWO4w +# ZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w +# cy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwQU9DJTIwQ0El +# MjAwMS5jcmwwgaUGCCsGAQUFBwEBBIGYMIGVMGQGCCsGAQUFBzAChlhodHRwOi8v +# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw +# VmVyaWZpZWQlMjBDUyUyMEFPQyUyMENBJTIwMDEuY3J0MC0GCCsGAQUFBzABhiFo +# dHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwZgYDVR0gBF8wXTBRBgwr +# BgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu +# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEEATANBgkqhkiG +# 9w0BAQwFAAOCAgEAKTeVGPXsDKqQLe1OuKx6K6q711FPxNQyLOOqeenH8zybHwNo +# k05cMk39HQ7u+R9BQIL0bWexb7wa3XeKaX06p7aY/OQs+ycvUi/fC6RGlaLWmQ9D +# YhZn2TBz5znimvSf3P+aidCuXeDU5c8GpBFog6fjEa/k+n7TILi0spuYZ4yC9R48 +# R63/VvpLi2SqxfJbx5n92bY6driNzAntjoravF25BSejXVrdzefbnqbQnZPB39g8 +# XHygGPb0912fIuNKPLQa/uCnmYdXJnPb0ZgMxxA8fyxvL2Q30Qf5xpFDssPDElvD +# DoAbvR24CWvuHbu+CMMr2SJUpX4RRvDioO7JeB6wZb+64MXyPUSSf6QwkKNsHPIa +# e9tSfREh86sYn5bOA0Wd+Igk0RpA5jDRTu3GgPOPWbm1PU+VoeqThtHt6R3l17pr +# aQ5wIuuLXgxi1K4ZWgtvXw8BtIXfZz24qCtoo0+3kEGUpEHBgkF1SClbRb8uAzx+ +# 0ROGniLPJRU20Xfn7CgipeKLcNn33JPFwQHk1zpbGS0090mi0erOQCz0S47YdHmm +# RJcbkNIL9DeNAglTZ/TFxrYUM1NRS1Cp4e63MgBKcWh9VJNokInzzmS+bofZz+u1 +# mm8YNtiJjdT8fmizXdUEk68EXQhOs0+HBNvc9nMRK6R28MZu/J+PaUcPL84wggda +# MIIFQqADAgECAhMzAAAABzeMW6HZW4zUAAAAAAAHMA0GCSqGSIb3DQEBDAUAMGMx +# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAy +# BgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIw +# MjEwHhcNMjEwNDEzMTczMTU0WhcNMjYwNDEzMTczMTU0WjBaMQswCQYDVQQGEwJV +# UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNy +# b3NvZnQgSUQgVmVyaWZpZWQgQ1MgQU9DIENBIDAxMIICIjANBgkqhkiG9w0BAQEF +# AAOCAg8AMIICCgKCAgEAt/fAAygHxbo+jxA04hNI8bz+EqbWvSu9dRgAawjCZau1 +# Y54IQal5ArpJWi8cIj0WA+mpwix8iTRguq9JELZvTMo2Z1U6AtE1Tn3mvq3mywZ9 +# SexVd+rPOTr+uda6GVgwLA80LhRf82AvrSwxmZpCH/laT08dn7+Gt0cXYVNKJORm +# 1hSrAjjDQiZ1Jiq/SqiDoHN6PGmT5hXKs22E79MeFWYB4y0UlNqW0Z2LPNua8k0r +# bERdiNS+nTP/xsESZUnrbmyXZaHvcyEKYK85WBz3Sr6Et8Vlbdid/pjBpcHI+Hyt +# oaUAGE6rSWqmh7/aEZeDDUkz9uMKOGasIgYnenUk5E0b2U//bQqDv3qdhj9UJYWA +# DNYC/3i3ixcW1VELaU+wTqXTxLAFelCi/lRHSjaWipDeE/TbBb0zTCiLnc9nmOjZ +# PKlutMNho91wxo4itcJoIk2bPot9t+AV+UwNaDRIbcEaQaBycl9pcYwWmf0bJ4IF +# n/CmYMVG1ekCBxByyRNkFkHmuMXLX6PMXcveE46jMr9syC3M8JHRddR4zVjd/FxB +# nS5HOro3pg6StuEPshrp7I/Kk1cTG8yOWl8aqf6OJeAVyG4lyJ9V+ZxClYmaU5yv +# tKYKk1FLBnEBfDWw+UAzQV0vcLp6AVx2Fc8n0vpoyudr3SwZmckJuz7R+S79BzMC +# AwEAAaOCAg4wggIKMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAd +# BgNVHQ4EFgQU6IPEM9fcnwycdpoKptTfh6ZeWO4wVAYDVR0gBE0wSzBJBgRVHSAA +# MEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv +# RG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAS +# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRI +# ajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w +# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2ln +# bmluZyUyMFBDQSUyMDIwMjEuY3JsMIGuBggrBgEFBQcBAQSBoTCBnjBtBggrBgEF +# BQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy +# b3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAy +# MDIxLmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3AubWljcm9zb2Z0LmNv +# bS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB3/utLItkwLTp4Nfh99vrbpSsL8NwP +# Ij2+TBnZGL3C8etTGYs+HZUxNG+rNeZa+Rzu9oEcAZJDiGjEWytzMavD6Bih3nEW +# FsIW4aGh4gB4n/pRPeeVrK4i1LG7jJ3kPLRhNOHZiLUQtmrF4V6IxtUFjvBnijaZ +# 9oIxsSSQP8iHMjP92pjQrHBFWHGDbkmx+yO6Ian3QN3YmbdfewzSvnQmKbkiTibJ +# gcJ1L0TZ7BwmsDvm+0XRsPOfFgnzhLVqZdEyWww10bflOeBKqkb3SaCNQTz8nsha +# UZhrxVU5qNgYjaaDQQm+P2SEpBF7RolEC3lllfuL4AOGCtoNdPOWrx9vBZTXAVdT +# E2r0IDk8+5y1kLGTLKzmNFn6kVCc5BddM7xoDWQ4aUoCRXcsBeRhsclk7kVXP+zJ +# GPOXwjUJbnz2Kt9iF/8B6FDO4blGuGrogMpyXkuwCC2Z4XcfyMjPDhqZYAPGGTUI +# NMtFbau5RtGG1DOWE9edCahtuPMDgByfPixvhy3sn7zUHgIC/YsOTMxVuMQi/bga +# memo/VNKZrsZaS0nzmOxKpg9qDefj5fJ9gIHXcp2F0OHcVwe3KnEXa8kqzMDfrRl +# /wwKrNSFn3p7g0b44Ad1ONDmWt61MLQvF54LG62i6ffhTCeoFT9Z9pbUo2gxlyTF +# g7Bm0fgOlnRfGDCCB54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJ +# KoZIhvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBD +# b3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNh +# dGlvbiBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIw +# MDUyMFoXDTM2MDQwMTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1p +# Y3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlm +# aWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +# ADCCAgoCggIBALLwwK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3 +# qrZilYKJNqztA9OQacr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrw +# eLoQ71lzCHkD7A4As1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9 +# rGQ//h890Q8JdjLLw0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8s +# ZU6ZE7iRrRZywRmrKDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfW +# o5tTgkoSMoayqoDpHOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC6 +# 9oKpRQXY9bGH6jn9NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjk +# Vd6CGUAf0K+Jw+GE/5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHg +# YYjHs1NbOc6brH+eKpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu +# 0t+gCwLdN0A6cFtSRtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeL +# zdpt32cdYKp+dhr2ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGj +# ggI1MIICMTAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0O +# BBYEFNlBKbAPD2Ns72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8G +# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv +# UmVwb3NpdG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0T +# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYD +# VR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j +# cmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIw +# Q2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEE +# gbYwgbMwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp +# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw +# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYB +# BQUHMAGGIWh0dHA6Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG +# 9w0BAQwFAAOCAgEAfyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdP +# Q4H55v7VOInnmezQEeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVI +# E1CRFfNF4XKO8XYEa3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T +# 8FG7/VEURIVWArbAzPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4 +# e0ejRA7mB2IoX5hNh3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaB +# jhWmirYyANb0RJSLWjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/t +# uLjAsKP6SzYZ+1Ry358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQw +# K8VtsBdekBmdTbQVoCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX +# 3mccFgx6UsQeRSdVVVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQL +# Uz6ZTl65yPUiOh3k7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i +# 3IpaDcR+iuGjH2TdaC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxgheN +# MIIXiQIBATBxMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +# cG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBBT0Mg +# Q0EgMDECEzMAAz/LZbJZacV+llwAAAADP8swDQYJYIZIAWUDBAIBBQCggcowGQYJ +# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB +# gjcCARUwLwYJKoZIhvcNAQkEMSIEIGcBno/ti9PCrR9sXrajsTvlHQvGxbk63JiI +# URJByQuGMF4GCisGAQQBgjcCAQwxUDBOoEiARgBCAHUAaQBsAHQAOgAgAFIAZQBs +# AGUAYQBzAGUAXwB2ADMALgAxADIALgAxADAAXwAyADAAMgA1ADAANAAwADgALgAw +# ADKhAoAAMA0GCSqGSIb3DQEBAQUABIIBgE9xMVem4h5iAbvBzmB1pTdA4LYNkvd/ +# hSbYmJRt5oJqBR0RGbUmcfYAgTlhdb/S84aGvI3N62I8qeMApnH89q+UF0i8p6+U +# Qza6Mu1cAHCq0NkHH6+N8g7nIfe5Cn+BBCBJ6kuYfQm9bx1JwEm5/yVCwG9I6+XV +# 3WonOeA8djuZFfB9OIW6N9ubX7X+nYqWaeT6w6/lDs8mL+s0Fumy4mJ8B15pd9mr +# N6dIRFokzhuALq6G0USKFzYf3qJQ4GyCos/Luez3cr8sE/78ds6vah5IlLP6qXMM +# ETwAdoymIYSm3Dly3lflodd4d7/nkMhfHITOxSUDoBbCP6MO1rhChX591rJy/omK +# 0RdM9ZpMl6VXHhzZ+lB8U/6j7xJGlxJSJHet7HFEuTnJEjY9dDy2bUgzk0vK1Rs2 +# l7VLOP3X87p9iVz5vDAOQB0fcsMDJvhIzJlmIb5z2uZ6hqD4UZdTDMLIBWe9H7Kv +# rhmGDPHPRboFKtTrKoKcWaf4fJJ2NUtYlKGCFKAwghScBgorBgEEAYI3AwMBMYIU +# jDCCFIgGCSqGSIb3DQEHAqCCFHkwghR1AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFh +# BgsqhkiG9w0BCRABBKCCAVAEggFMMIIBSAIBAQYKKwYBBAGEWQoDATAxMA0GCWCG +# SAFlAwQCAQUABCAY3nVyqXzzboHwsVGd+j5FjG9eaMv+O3mJKpX+3EJ43AIGZ9gU +# uyvYGBMyMDI1MDQwODEyNDEyMi40MTNaMASAAgH0oIHgpIHdMIHaMQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg +# QW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1 +# LTk2M0ItRTFGNDE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBT +# dGFtcGluZyBBdXRob3JpdHmggg8gMIIHgjCCBWqgAwIBAgITMwAAAAXlzw//Zi7J +# hwAAAAAABTANBgkqhkiG9w0BAQwFADB3MQswCQYDVQQGEwJVUzEeMBwGA1UEChMV +# TWljcm9zb2Z0IENvcnBvcmF0aW9uMUgwRgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRp +# dHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAw +# HhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5MjA0MjMxWjBhMQswCQYDVQQGEwJVUzEe +# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +# ZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDCCAiIwDQYJKoZIhvcN +# AQEBBQADggIPADCCAgoCggIBAJ5851Jj/eDFnwV9Y7UGIqMcHtfnlzPREwW9ZUZH +# d5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqOQxwuEQXG8kB41wsDJP5d0zmLYKAY8Zxv +# 3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEESnt0MbPEoKdNihwM5xGv0rGofJ1qOYST +# Ncc55EbBT7uq3wx3mXhtVmtcCEr5ZKTkKKE1CxZvNPWdGWJUPC6e4uRfWHIhZcgC +# sJ+sozf5EeH5KrlFnxpjKKTavwfFP6XaGZGWUG8TZaiTogRoAlqcevbiqioUz1Yt +# 4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm5sOTiEQtBLGd9Vhd1MadxoGcHrRCsS5r +# O9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+eZ4CNE3ctW4uvSDQVeSp9h1SaPV8UWEf +# yTxgGjOsRpeexIveR1MPTVf7gt8hY64XNPO6iyUGsEgt8c2PxF87E+CO7A28TpjN +# q5eLiiunhKbq0XbjkNoU5JhtYUrlmAbpxRjb9tSreDdtACpm3rkpxp7AQndnI0Sh +# u/fk1/rE3oWsDqMX3jjv40e8KN5YsJBnczyWB4JyeeFMW3JBfdeAKhzohFe8U5w9 +# WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8Y5SwB1lt5dQhABYyzR3dxEO/T1K/BVF3 +# rV69AgMBAAGjggIbMIICFzAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMC +# AQAwHQYDVR0OBBYEFGtpKDo1L0hjQM972K9J6T7ZPdshMFQGA1UdIARNMEswSQYE +# VR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp +# b3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJ +# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +# GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0 +# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl +# bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo +# b3JpdHklMjAyMDIwLmNybDCBlAYIKwYBBQUHAQEEgYcwgYQwgYEGCCsGAQUFBzAC +# hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m +# dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl +# JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwDQYJKoZIhvcNAQEMBQADggIBAF+Idsd+ +# bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/pO+4ge/XEizXvhs0Y7+KVYyb4nHlugBes +# nFqBGEdC2IWmtKMyS1OWIviwpnK3aL5JedwzbeBF7POyg6IGG/XhhJ3UqWeWTO+C +# zb1c2NP5zyEh89F72u9UIw+IfvM9lzDmc2O2END7MPnrcjWdQnrLn1Ntday7JSyr +# DvBdmgbNnCKNZPmhzoa8PccOiQljjTW6GePe5sGFuRHzdFt8y+bN2neF7Zu8hTO1 +# I64XNGqst8S+w+RUdie8fXC1jKu3m9KGIqF4aldrYBamyh3g4nJPj/LR2CBaLyD+ +# 2BuGZCVmoNR/dSpRCxlot0i79dKOChmoONqbMI8m04uLaEHAv4qwKHQ1vBzbV/nG +# 89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFfR4f/gksSkbJp7oqLwliDm/h+w0aJ/U5c +# cnYhYb7vPKNMN+SZDWycU5ODIRfyoGl59BsXR/HpRGtiJquOYGmvA/pk5vC1lcnb +# eMrcWD/26ozePQ/TWfNXKBOmkFpvPE8CH+EeGGWzqTCjdAsno2jzTeNSxlx3glDG +# Jgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqPTXPmaCAJKVHAP19oEjJIBwD1LyHbaEgB +# xFCogYSOiUIr0Xqcr1nJfiWG2GwYe6ZoAF1bMIIHljCCBX6gAwIBAgITMwAAAEYX +# 5HV6yv3a5QAAAAAARjANBgkqhkiG9w0BAQwFADBhMQswCQYDVQQGEwJVUzEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQg +# UHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAeFw0yNDExMjYxODQ4NDla +# Fw0yNTExMTkxODQ4NDlaMIHaMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu +# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +# cmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYw +# JAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1LTk2M0ItRTFGNDE1MDMGA1UEAxMs +# TWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHkwggIi +# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwlXzoj/MNL1BfnV+gg4d0fZum +# 1HdUJidSNTcDzpHJvmIBqH566zBYcV0TyN7+3qOnJjpoTx6JBMgNYnL5BmTX9Hrm +# X0WdNMLf74u7NtBSuAD2sf6n2qUUrz7i8f7r0JiZixKJnkvA/1akLHppQMDCug1o +# C0AYjd753b5vy1vWdrHXE9hL71BZe5DCq5/4LBny8aOQZlzvjewgONkiZm+Sfctk +# Jjh9LxdkDlq5EvGE6YU0uC37XF7qkHvIksD2+XgBP0lEMfmPJo2fI9FwIA9YMX7K +# IINEM5OY6nkvKryM9s5bK6LV4z48NYpiI1xvH15YDps+19nHCtKMVTZdB4cYhA0d +# VqJ7dAu4VcxUwD1AEcMxWbIOR1z6OFkVY9GX5oH8k17d9t35PWfn0XuxW4SG/rim +# gtFgpE/shRsy5nMCbHyeCdW0He1plrYQqTsSHP2n/lz2DCgIlnx+uvPLVf5+JG/1 +# d1i/LdwbC2WH6UEEJyZIl3a0YwM4rdzoR+P4dO9I/2oWOxXCYqFytYdCy9ljELUw +# byLjrjRddteR8QTxrCfadKpKfFY6Ak/HNZPUHaAPak3baOIvV7Q8axo3DWQy2ib3 +# zXV6hMPNt1v90pv+q9daQdwUzUrgcbwThdrRhWHwlRIVg2sR668HPn4/8l9ikGok +# rL6gAmVxNswEZ9awCwIDAQABo4IByzCCAccwHQYDVR0OBBYEFBE20NSvdrC6Z6cm +# 6RPGP8YbqIrxMB8GA1UdIwQYMBaAFGtpKDo1L0hjQM972K9J6T7ZPdshMGwGA1Ud +# HwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js +# L01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIw +# MjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUFBzAChl1odHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFB1YmxpYyUy +# MFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5jcnQwDAYDVR0TAQH/BAIw +# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0g +# BF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t +# aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEE +# AjANBgkqhkiG9w0BAQwFAAOCAgEAFIW5L+gGzX4gyHorS33YKXuK9iC91iZTpm30 +# x/EdHG6U8NAu2qityxjZVq6MDq300gspG0ntzLYqVhjfku7iNzE78k6tNgFCr9wv +# GkIHeK+Q2RAO9/s5R8rhNC+lywOB+6K5Zi0kfO0agVXf7Nk2O6F6D9AEzNLijG+c +# Oe5Ef2F5l4ZsVSkLFCI5jELC+r4KnNZjunc+qvjSz2DkNsXfrjFhyk+K7v7U7+JF +# Z8kZ58yFuxEX0cxDKpJLxiNh/ODCOL2UxYkhyfI3AR0EhfxX9QZHVgxyZwnavR35 +# FxqLSiGTeAJsK7YN3bIxyuP6eCcnkX8TMdpu9kPD97sHnM7po0UQDrjaN7etviLD +# xnax2nemdvJW3BewOLFrD1nSnd7ZHdPGPB3oWTCaK9/3XwQERLi3Xj+HZc89RP50 +# Nt7h7+3G6oq2kXYNidI9iWd+gL+lvkQZH9YTIfBCLWjvuXvUUUU+AvFI00Utqrvd +# rIdqCFaqE9HHQgSfXeQ53xLWdMCztUP/YnMXiJxNBkc6UE2px/o6+/LXJDIpwIXR +# 4HSodLfkfsNQl6FFrJ1xsOYGSHvcFkH8389RmUvrjr1NBbdesc4Bu4kox+3cabOZ +# c1zm89G+1RRL2tReFzSMlYSGO3iKn3GGXmQiRmFlBb3CpbUVQz+fgxVMfeL0j4Lm +# KQfT1jIxggPUMIID0AIBATB4MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNB +# IFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAARhfkdXrK/drlAAAAAABGMA0GCWCG +# SAFlAwQCAQUAoIIBLTAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI +# hvcNAQkEMSIEIHgwQkiMhul6IrfEKmPaCFR+R91oZOlPqVgP/9PPcfn+MIHdBgsq +# hkiG9w0BCRACLzGBzTCByjCBxzCBoAQgEid2SJpUPj5xQm73M4vqDmVh1QR6TiuT +# UVkL3P8Wis4wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m +# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGlt +# ZXN0YW1waW5nIENBIDIwMjACEzMAAABGF+R1esr92uUAAAAAAEYwIgQgVp6I1YBM +# Mni0rCuD57vEK/tzWZypHqWFikWLFVY11RwwDQYJKoZIhvcNAQELBQAEggIAnRBH +# voM5+wbJp+aOwrrL8fi8Rv/eFV820Nhr+jMny73UscN60OWdcdcZDbjDlnDX1KEP +# sNcEOFvaruHHrF4kDK8N0yemElNz63IgqhUoGoXXQKT2RgVg7T/kiQJH7zuaEjgB +# YNniAZdXXJJ1C+uv2ZQzkGIEVIEA6pB5/xo4kFhrfkOrdGzqL8HXT/RZQDMn5Uzk +# W+Sl2JmsyYBS4sgI9Ay3qT5nv+frzngbWlqx1dre21uj37Fgk5mWHJEdmY1nqTTd +# 25j6oDLGPC8AS9wtgZBXggemKAXwyeOFFahXUFN7X7cbwTALy5aWjE/rqp+N5J7M +# +YApl3aknUZ13KTXz9pfAF0uhmZimngvBHjijyctleF8HUP2RNAhS/l68OqW7oKi +# Dqvb7tSHJbcnYkxo7dUq6ppfN51ah61ZsyMVG6SaH015+5QO1k50ohXcFff2GOuZ +# d3Z9JOoAjIkeiVTNeRlPDlHtS0CSYu4ZKsWsst+0VY2R9rJBeoii9Xa0oiIggkYL +# 1pHAPH0B1uLlvFcI6B+fAXe0OiCJodbO5lk8ZpvCG5WWYbjzp2c3B8PZGSBgEpSf +# KYlVavvBAvaJCORUO7j8PyzzDINuzQorP9+i399ORjOnqeC92Cb0V12LcoqqtJaf +# 7oSB86VOI0lfHnPUlLWvoiLHrFR5PsYkltOuPqU= +# SIG # End signature block diff --git a/.venv312/Scripts/about.exe b/.venv312/Scripts/about.exe new file mode 100644 index 0000000000..5e03832b23 Binary files /dev/null and b/.venv312/Scripts/about.exe differ diff --git a/.venv312/Scripts/activate b/.venv312/Scripts/activate new file mode 100644 index 0000000000..0e5c587a10 --- /dev/null +++ b/.venv312/Scripts/activate @@ -0,0 +1,76 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past locations. Without forgetting + # past locations the $PATH changes we made may not be respected. + # See "man bash" for more details. hash is usually a builtin of your shell + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +case "$(uname)" in + CYGWIN*|MSYS*|MINGW*) + # transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW + # and to /cygdrive/d/path/to/venv on Cygwin + VIRTUAL_ENV=$(cygpath 'E:\hell\scancode.io\.venv312') + export VIRTUAL_ENV + ;; + *) + # use the path as-is + export VIRTUAL_ENV='E:\hell\scancode.io\.venv312' + ;; +esac + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/"Scripts":$PATH" +export PATH + +VIRTUAL_ENV_PROMPT='(.venv312) ' +export VIRTUAL_ENV_PROMPT + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="("'(.venv312) '") ${PS1:-}" + export PS1 +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/.venv312/Scripts/activate.bat b/.venv312/Scripts/activate.bat new file mode 100644 index 0000000000..d206c98b59 --- /dev/null +++ b/.venv312/Scripts/activate.bat @@ -0,0 +1,34 @@ +@echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set _OLD_CODEPAGE=%%a +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + +set "VIRTUAL_ENV=E:\hell\scancode.io\.venv312" + +if not defined PROMPT set PROMPT=$P$G + +if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% +if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% + +set _OLD_VIRTUAL_PROMPT=%PROMPT% +set PROMPT=(.venv312) %PROMPT% + +if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +set PYTHONHOME= + +if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% +if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% + +set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" +set "VIRTUAL_ENV_PROMPT=(.venv312) " + +:END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set _OLD_CODEPAGE= +) diff --git a/.venv312/Scripts/add-required-phrases.exe b/.venv312/Scripts/add-required-phrases.exe new file mode 100644 index 0000000000..e01d28bc99 Binary files /dev/null and b/.venv312/Scripts/add-required-phrases.exe differ diff --git a/.venv312/Scripts/bids-analyser.exe b/.venv312/Scripts/bids-analyser.exe new file mode 100644 index 0000000000..5fe293df71 Binary files /dev/null and b/.venv312/Scripts/bids-analyser.exe differ diff --git a/.venv312/Scripts/bids-scan.exe b/.venv312/Scripts/bids-scan.exe new file mode 100644 index 0000000000..976b85518f Binary files /dev/null and b/.venv312/Scripts/bids-scan.exe differ diff --git a/.venv312/Scripts/bids-search.exe b/.venv312/Scripts/bids-search.exe new file mode 100644 index 0000000000..548bb80a88 Binary files /dev/null and b/.venv312/Scripts/bids-search.exe differ diff --git a/.venv312/Scripts/bids-ui.exe b/.venv312/Scripts/bids-ui.exe new file mode 100644 index 0000000000..118301470d Binary files /dev/null and b/.venv312/Scripts/bids-ui.exe differ diff --git a/.venv312/Scripts/chardetect.exe b/.venv312/Scripts/chardetect.exe new file mode 100644 index 0000000000..094a5abbce Binary files /dev/null and b/.venv312/Scripts/chardetect.exe differ diff --git a/.venv312/Scripts/container_inspector.exe b/.venv312/Scripts/container_inspector.exe new file mode 100644 index 0000000000..a11e3a1e9b Binary files /dev/null and b/.venv312/Scripts/container_inspector.exe differ diff --git a/.venv312/Scripts/container_inspector_dockerfile.exe b/.venv312/Scripts/container_inspector_dockerfile.exe new file mode 100644 index 0000000000..849f442b40 Binary files /dev/null and b/.venv312/Scripts/container_inspector_dockerfile.exe differ diff --git a/.venv312/Scripts/container_inspector_squash.exe b/.venv312/Scripts/container_inspector_squash.exe new file mode 100644 index 0000000000..7913c483b9 Binary files /dev/null and b/.venv312/Scripts/container_inspector_squash.exe differ diff --git a/.venv312/Scripts/csv2rdf.exe b/.venv312/Scripts/csv2rdf.exe new file mode 100644 index 0000000000..19ab127354 Binary files /dev/null and b/.venv312/Scripts/csv2rdf.exe differ diff --git a/.venv312/Scripts/deactivate.bat b/.venv312/Scripts/deactivate.bat new file mode 100644 index 0000000000..62a39a7584 --- /dev/null +++ b/.venv312/Scripts/deactivate.bat @@ -0,0 +1,22 @@ +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= +set VIRTUAL_ENV_PROMPT= + +:END diff --git a/.venv312/Scripts/django-admin.exe b/.venv312/Scripts/django-admin.exe new file mode 100644 index 0000000000..cdac90cd4d Binary files /dev/null and b/.venv312/Scripts/django-admin.exe differ diff --git a/.venv312/Scripts/dotenv.exe b/.venv312/Scripts/dotenv.exe new file mode 100644 index 0000000000..75cba52ab8 Binary files /dev/null and b/.venv312/Scripts/dotenv.exe differ diff --git a/.venv312/Scripts/dumppdf.py b/.venv312/Scripts/dumppdf.py new file mode 100644 index 0000000000..e009845bda --- /dev/null +++ b/.venv312/Scripts/dumppdf.py @@ -0,0 +1,468 @@ +#!E:\hell\scancode.io\.venv312\Scripts\python.exe +"""Extract pdf structure in XML format""" + +import logging +import os.path +import re +import sys +from argparse import ArgumentParser +from collections.abc import Container, Iterable +from typing import Any, TextIO, cast + +import pdfminer +from pdfminer.pdfdocument import PDFDocument, PDFNoOutlines, PDFXRefFallback +from pdfminer.pdfexceptions import ( + PDFIOError, + PDFObjectNotFound, + PDFTypeError, + PDFValueError, +) +from pdfminer.pdfpage import PDFPage +from pdfminer.pdfparser import PDFParser +from pdfminer.pdftypes import PDFObjRef, PDFStream, resolve1, stream_value +from pdfminer.psparser import LIT, PSKeyword, PSLiteral +from pdfminer.utils import isnumber + +logging.basicConfig() +logger = logging.getLogger(__name__) + +ESC_PAT = re.compile(r'[\000-\037&<>()"\042\047\134\177-\377]') + + +def escape(s: str | bytes) -> str: + us = str(s, "latin-1") if isinstance(s, bytes) else s + return ESC_PAT.sub(lambda m: f"&#{ord(m.group(0))};", us) + + +def dumpxml(out: TextIO, obj: object, codec: str | None = None) -> None: + if obj is None: + out.write("") + return + + if isinstance(obj, dict): + out.write(f'\n') + for k, v in obj.items(): + out.write(f"{k}\n") + out.write("") + dumpxml(out, v) + out.write("\n") + out.write("") + return + + if isinstance(obj, list): + out.write(f'\n') + for v in obj: + dumpxml(out, v) + out.write("\n") + out.write("") + return + + if isinstance(obj, (str, bytes)): + out.write(f'{escape(obj)}') + return + + if isinstance(obj, PDFStream): + if codec == "raw": + # Bug: writing bytes to text I/O. This will raise TypeError. + out.write(obj.get_rawdata()) # type: ignore [arg-type] + elif codec == "binary": + # Bug: writing bytes to text I/O. This will raise TypeError. + out.write(obj.get_data()) # type: ignore [arg-type] + else: + out.write("\n\n") + dumpxml(out, obj.attrs) + out.write("\n\n") + if codec == "text": + data = obj.get_data() + out.write(f'{escape(data)}\n') + out.write("") + return + + if isinstance(obj, PDFObjRef): + out.write(f'') + return + + if isinstance(obj, PSKeyword): + # Likely bug: obj.name is bytes, not str + out.write(f"{obj.name}") # type: ignore [str-bytes-safe] + return + + if isinstance(obj, PSLiteral): + # Likely bug: obj.name may be bytes, not str + out.write(f"{obj.name}") # type: ignore [str-bytes-safe] + return + + if isnumber(obj): + out.write(f"{obj}") + return + + raise PDFTypeError(obj) + + +def dumptrailers( + out: TextIO, + doc: PDFDocument, + show_fallback_xref: bool = False, +) -> None: + for xref in doc.xrefs: + if not isinstance(xref, PDFXRefFallback) or show_fallback_xref: + out.write("\n") + dumpxml(out, xref.get_trailer()) + out.write("\n\n\n") + no_xrefs = all(isinstance(xref, PDFXRefFallback) for xref in doc.xrefs) + if no_xrefs and not show_fallback_xref: + msg = ( + "This PDF does not have an xref. Use --show-fallback-xref if " + "you want to display the content of a fallback xref that " + "contains all objects." + ) + logger.warning(msg) + + +def dumpallobjs( + out: TextIO, + doc: PDFDocument, + codec: str | None = None, + show_fallback_xref: bool = False, +) -> None: + visited = set() + out.write("") + for xref in doc.xrefs: + for objid in xref.get_objids(): + if objid in visited: + continue + visited.add(objid) + try: + obj = doc.getobj(objid) + if obj is None: + continue + out.write(f'\n') + dumpxml(out, obj, codec=codec) + out.write("\n\n\n") + except PDFObjectNotFound as e: + print(f"not found: {e!r}") + dumptrailers(out, doc, show_fallback_xref) + out.write("") + + +def dumpoutline( + outfp: TextIO, + fname: str, + objids: Any, + pagenos: Container[int], + password: str = "", + dumpall: bool = False, + codec: str | None = None, + extractdir: str | None = None, +) -> None: + with open(fname, "rb") as fp: + parser = PDFParser(fp) + doc = PDFDocument(parser, password) + pages = { + page.pageid: pageno + for (pageno, page) in enumerate(PDFPage.create_pages(doc), 1) + } + + def resolve_dest(dest: object) -> Any: + if isinstance(dest, (str, bytes)): + dest = resolve1(doc.get_dest(dest)) + elif isinstance(dest, PSLiteral): + dest = resolve1(doc.get_dest(dest.name)) + if isinstance(dest, dict): + dest = dest["D"] + if isinstance(dest, PDFObjRef): + dest = dest.resolve() + return dest + + try: + outlines = doc.get_outlines() + outfp.write("\n") + for level, title, dest, a, _se in outlines: + pageno = None + if dest: + dest = resolve_dest(dest) + pageno = pages[dest[0].objid] + elif a: + action = a + if isinstance(action, dict): + subtype = action.get("S") + if subtype and repr(subtype) == "/'GoTo'" and action.get("D"): + dest = resolve_dest(action["D"]) + pageno = pages[dest[0].objid] + s = escape(title) + outfp.write(f'\n') + if dest is not None: + outfp.write("") + dumpxml(outfp, dest) + outfp.write("\n") + if pageno is not None: + outfp.write(f"{pageno!r}\n") + outfp.write("\n") + outfp.write("\n") + except PDFNoOutlines: + pass + parser.flush() + + +LITERAL_FILESPEC = LIT("Filespec") +LITERAL_EMBEDDEDFILE = LIT("EmbeddedFile") + + +def extractembedded(fname: str, password: str, extractdir: str) -> None: + def extract1(objid: int, obj: dict[str, Any]) -> None: + filename = os.path.basename(obj.get("UF") or cast(bytes, obj.get("F")).decode()) + fileref = obj["EF"].get("UF") or obj["EF"].get("F") + fileobj = doc.getobj(fileref.objid) + if not isinstance(fileobj, PDFStream): + error_msg = ( + f"unable to process PDF: reference for {filename!r} is not a PDFStream" + ) + raise PDFValueError(error_msg) + if fileobj.get("Type") is not LITERAL_EMBEDDEDFILE: + raise PDFValueError( + f"unable to process PDF: reference for {filename!r} " + "is not an EmbeddedFile", + ) + path = os.path.join(extractdir, f"{objid:06d}-{filename}") + if os.path.exists(path): + raise PDFIOError(f"file exists: {path!r}") + print(f"extracting: {path!r}") + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "wb") as out: + out.write(fileobj.get_data()) + + with open(fname, "rb") as fp: + parser = PDFParser(fp) + doc = PDFDocument(parser, password) + extracted_objids = set() + for xref in doc.xrefs: + for objid in xref.get_objids(): + obj = doc.getobj(objid) + if ( + objid not in extracted_objids + and isinstance(obj, dict) + and obj.get("Type") is LITERAL_FILESPEC + ): + extracted_objids.add(objid) + extract1(objid, obj) + + +def dumppdf( + outfp: TextIO, + fname: str, + objids: Iterable[int], + pagenos: Container[int], + password: str = "", + dumpall: bool = False, + codec: str | None = None, + extractdir: str | None = None, + show_fallback_xref: bool = False, +) -> None: + with open(fname, "rb") as fp: + parser = PDFParser(fp) + doc = PDFDocument(parser, password) + if objids: + for objid in objids: + obj = doc.getobj(objid) + dumpxml(outfp, obj, codec=codec) + if pagenos: + for pageno, page in enumerate(PDFPage.create_pages(doc)): + if pageno in pagenos: + if codec: + for obj in page.contents: + obj = stream_value(obj) + dumpxml(outfp, obj, codec=codec) + else: + dumpxml(outfp, page.attrs) + if dumpall: + dumpallobjs(outfp, doc, codec, show_fallback_xref) + if (not objids) and (not pagenos) and (not dumpall): + dumptrailers(outfp, doc, show_fallback_xref) + if codec not in ("raw", "binary"): + outfp.write("\n") + + +def create_parser() -> ArgumentParser: + parser = ArgumentParser(description=__doc__, add_help=True) + parser.add_argument( + "files", + type=str, + default=None, + nargs="+", + help="One or more paths to PDF files.", + ) + + parser.add_argument( + "--version", + "-v", + action="version", + version=f"pdfminer.six v{pdfminer.__version__}", + ) + parser.add_argument( + "--debug", + "-d", + default=False, + action="store_true", + help="Use debug logging level.", + ) + procedure_parser = parser.add_mutually_exclusive_group() + procedure_parser.add_argument( + "--extract-toc", + "-T", + default=False, + action="store_true", + help="Extract structure of outline", + ) + procedure_parser.add_argument( + "--extract-embedded", + "-E", + type=str, + help="Extract embedded files", + ) + + parse_params = parser.add_argument_group( + "Parser", + description="Used during PDF parsing", + ) + parse_params.add_argument( + "--page-numbers", + type=int, + default=None, + nargs="+", + help="A space-seperated list of page numbers to parse.", + ) + parse_params.add_argument( + "--pagenos", + "-p", + type=str, + help="A comma-separated list of page numbers to parse. Included for " + "legacy applications, use --page-numbers for more idiomatic " + "argument entry.", + ) + parse_params.add_argument( + "--objects", + "-i", + type=str, + help="Comma separated list of object numbers to extract", + ) + parse_params.add_argument( + "--all", + "-a", + default=False, + action="store_true", + help="If the structure of all objects should be extracted", + ) + parse_params.add_argument( + "--show-fallback-xref", + action="store_true", + help="Additionally show the fallback xref. Use this if the PDF " + "has zero or only invalid xref's. This setting is ignored if " + "--extract-toc or --extract-embedded is used.", + ) + parse_params.add_argument( + "--password", + "-P", + type=str, + default="", + help="The password to use for decrypting PDF file.", + ) + + output_params = parser.add_argument_group( + "Output", + description="Used during output generation.", + ) + output_params.add_argument( + "--outfile", + "-o", + type=str, + default="-", + help='Path to file where output is written. Or "-" (default) to ' + "write to stdout.", + ) + codec_parser = output_params.add_mutually_exclusive_group() + codec_parser.add_argument( + "--raw-stream", + "-r", + default=False, + action="store_true", + help="Write stream objects without encoding", + ) + codec_parser.add_argument( + "--binary-stream", + "-b", + default=False, + action="store_true", + help="Write stream objects with binary encoding", + ) + codec_parser.add_argument( + "--text-stream", + "-t", + default=False, + action="store_true", + help="Write stream objects as plain text", + ) + + return parser + + +def main(argv: list[str] | None = None) -> None: + parser = create_parser() + args = parser.parse_args(args=argv) + + if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + + objids = [int(x) for x in args.objects.split(",")] if args.objects else [] + + if args.page_numbers: + pagenos = {x - 1 for x in args.page_numbers} + elif args.pagenos: + pagenos = {int(x) - 1 for x in args.pagenos.split(",")} + else: + pagenos = set() + + password = args.password + + if args.raw_stream: + codec: str | None = "raw" + elif args.binary_stream: + codec = "binary" + elif args.text_stream: + codec = "text" + else: + codec = None + + # Use context manager for file output, ensuring proper cleanup + with sys.stdout if args.outfile == "-" else open(args.outfile, "w") as outfp: + for fname in args.files: + if args.extract_toc: + dumpoutline( + outfp, + fname, + objids, + pagenos, + password=password, + dumpall=args.all, + codec=codec, + extractdir=None, + ) + elif args.extract_embedded: + extractembedded( + fname, password=password, extractdir=args.extract_embedded + ) + else: + dumppdf( + outfp, + fname, + objids, + pagenos, + password=password, + dumpall=args.all, + codec=codec, + extractdir=None, + show_fallback_xref=args.show_fallback_xref, + ) + + +if __name__ == "__main__": + main() diff --git a/.venv312/Scripts/extractcode.exe b/.venv312/Scripts/extractcode.exe new file mode 100644 index 0000000000..15c1d32753 Binary files /dev/null and b/.venv312/Scripts/extractcode.exe differ diff --git a/.venv312/Scripts/ftfy.exe b/.venv312/Scripts/ftfy.exe new file mode 100644 index 0000000000..02c56bf7fc Binary files /dev/null and b/.venv312/Scripts/ftfy.exe differ diff --git a/.venv312/Scripts/gen-new-required-phrases-rules.exe b/.venv312/Scripts/gen-new-required-phrases-rules.exe new file mode 100644 index 0000000000..a78db0936f Binary files /dev/null and b/.venv312/Scripts/gen-new-required-phrases-rules.exe differ diff --git a/.venv312/Scripts/jsonschema.exe b/.venv312/Scripts/jsonschema.exe new file mode 100644 index 0000000000..9928bd7cc7 Binary files /dev/null and b/.venv312/Scripts/jsonschema.exe differ diff --git a/.venv312/Scripts/markdown-it.exe b/.venv312/Scripts/markdown-it.exe new file mode 100644 index 0000000000..e8ec391077 Binary files /dev/null and b/.venv312/Scripts/markdown-it.exe differ diff --git a/.venv312/Scripts/normalizer.exe b/.venv312/Scripts/normalizer.exe new file mode 100644 index 0000000000..06419d539e Binary files /dev/null and b/.venv312/Scripts/normalizer.exe differ diff --git a/.venv312/Scripts/pdf2txt.py b/.venv312/Scripts/pdf2txt.py new file mode 100644 index 0000000000..dbe6a8af6c --- /dev/null +++ b/.venv312/Scripts/pdf2txt.py @@ -0,0 +1,324 @@ +#!E:\hell\scancode.io\.venv312\Scripts\python.exe +"""A command line tool for extracting text and images from PDF and +output it to plain text, html, xml or tags. +""" + +import argparse +import logging +import sys +from collections.abc import Container, Iterable +from typing import Any + +import pdfminer.high_level +from pdfminer.layout import LAParams +from pdfminer.pdfexceptions import PDFValueError +from pdfminer.utils import AnyIO + +logging.basicConfig() + +OUTPUT_TYPES = ((".htm", "html"), (".html", "html"), (".xml", "xml"), (".tag", "tag")) + + +def float_or_disabled(x: str) -> float | None: + if x.lower().strip() == "disabled": + return None + try: + return float(x) + except ValueError as err: + raise argparse.ArgumentTypeError(f"invalid float value: {x}") from err + + +def extract_text( + files: Iterable[str] = [], + outfile: str = "-", + laparams: LAParams | None = None, + output_type: str = "text", + codec: str = "utf-8", + strip_control: bool = False, + maxpages: int = 0, + page_numbers: Container[int] | None = None, + password: str = "", + scale: float = 1.0, + rotation: int = 0, + layoutmode: str = "normal", + output_dir: str | None = None, + debug: bool = False, + disable_caching: bool = False, + **kwargs: Any, +) -> None: + if not files: + raise PDFValueError("Must provide files to work upon!") + + if output_type == "text" and outfile != "-": + for override, alttype in OUTPUT_TYPES: + if outfile.endswith(override): + output_type = alttype + + if outfile == "-": + outfp: AnyIO = sys.stdout + if sys.stdout.encoding is not None: + codec = "utf-8" + for fname in files: + with open(fname, "rb") as fp: + pdfminer.high_level.extract_text_to_fp(fp, **locals()) + else: + # Use context manager for file output, ensuring proper cleanup + with open(outfile, "wb") as outfp: + for fname in files: + with open(fname, "rb") as fp: + pdfminer.high_level.extract_text_to_fp(fp, **locals()) + + +def create_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description=__doc__, add_help=True) + parser.add_argument( + "files", + type=str, + default=None, + nargs="+", + help="One or more paths to PDF files.", + ) + + parser.add_argument( + "--version", + "-v", + action="version", + version=f"pdfminer.six v{pdfminer.__version__}", + ) + parser.add_argument( + "--debug", + "-d", + default=False, + action="store_true", + help="Use debug logging level.", + ) + parser.add_argument( + "--disable-caching", + "-C", + default=False, + action="store_true", + help="If caching or resources, such as fonts, should be disabled.", + ) + + parse_params = parser.add_argument_group( + "Parser", + description="Used during PDF parsing", + ) + parse_params.add_argument( + "--page-numbers", + type=int, + default=None, + nargs="+", + help="A space-seperated list of page numbers to parse.", + ) + parse_params.add_argument( + "--pagenos", + "-p", + type=str, + help="A comma-separated list of page numbers to parse. " + "Included for legacy applications, use --page-numbers " + "for more idiomatic argument entry.", + ) + parse_params.add_argument( + "--maxpages", + "-m", + type=int, + default=0, + help="The maximum number of pages to parse.", + ) + parse_params.add_argument( + "--password", + "-P", + type=str, + default="", + help="The password to use for decrypting PDF file.", + ) + parse_params.add_argument( + "--rotation", + "-R", + default=0, + type=int, + help="The number of degrees to rotate the PDF " + "before other types of processing.", + ) + + la_params = LAParams() # will be used for defaults + la_param_group = parser.add_argument_group( + "Layout analysis", + description="Used during layout analysis.", + ) + la_param_group.add_argument( + "--no-laparams", + "-n", + default=False, + action="store_true", + help="If layout analysis parameters should be ignored.", + ) + la_param_group.add_argument( + "--detect-vertical", + "-V", + default=la_params.detect_vertical, + action="store_true", + help="If vertical text should be considered during layout analysis", + ) + la_param_group.add_argument( + "--line-overlap", + type=float, + default=la_params.line_overlap, + help="If two characters have more overlap than this they " + "are considered to be on the same line. The overlap is specified " + "relative to the minimum height of both characters.", + ) + la_param_group.add_argument( + "--char-margin", + "-M", + type=float, + default=la_params.char_margin, + help="If two characters are closer together than this margin they " + "are considered to be part of the same line. The margin is " + "specified relative to the width of the character.", + ) + la_param_group.add_argument( + "--word-margin", + "-W", + type=float, + default=la_params.word_margin, + help="If two characters on the same line are further apart than this " + "margin then they are considered to be two separate words, and " + "an intermediate space will be added for readability. The margin " + "is specified relative to the width of the character.", + ) + la_param_group.add_argument( + "--line-margin", + "-L", + type=float, + default=la_params.line_margin, + help="If two lines are close together they are considered to " + "be part of the same paragraph. The margin is specified " + "relative to the height of a line.", + ) + la_param_group.add_argument( + "--boxes-flow", + "-F", + type=float_or_disabled, + default=la_params.boxes_flow, + help="Specifies how much a horizontal and vertical position of a " + "text matters when determining the order of lines. The value " + "should be within the range of -1.0 (only horizontal position " + "matters) to +1.0 (only vertical position matters). You can also " + "pass `disabled` to disable advanced layout analysis, and " + "instead return text based on the position of the bottom left " + "corner of the text box.", + ) + la_param_group.add_argument( + "--all-texts", + "-A", + default=la_params.all_texts, + action="store_true", + help="If layout analysis should be performed on text in figures.", + ) + + output_params = parser.add_argument_group( + "Output", + description="Used during output generation.", + ) + output_params.add_argument( + "--outfile", + "-o", + type=str, + default="-", + help="Path to file where output is written. " + 'Or "-" (default) to write to stdout.', + ) + output_params.add_argument( + "--output_type", + "-t", + type=str, + default="text", + help="Type of output to generate {text,html,xml,tag}.", + ) + output_params.add_argument( + "--codec", + "-c", + type=str, + default="utf-8", + help="Text encoding to use in output file.", + ) + output_params.add_argument( + "--output-dir", + "-O", + default=None, + help="The output directory to put extracted images in. If not given, " + "images are not extracted.", + ) + output_params.add_argument( + "--layoutmode", + "-Y", + default="normal", + type=str, + help="Type of layout to use when generating html " + "{normal,exact,loose}. If normal,each line is" + " positioned separately in the html. If exact" + ", each character is positioned separately in" + " the html. If loose, same result as normal " + "but with an additional newline after each " + "text line. Only used when output_type is html.", + ) + output_params.add_argument( + "--scale", + "-s", + type=float, + default=1.0, + help="The amount of zoom to use when generating html file. " + "Only used when output_type is html.", + ) + output_params.add_argument( + "--strip-control", + "-S", + default=False, + action="store_true", + help="Remove control statement from text. Only used when output_type is xml.", + ) + + return parser + + +def parse_args(args: list[str] | None) -> argparse.Namespace: + parsed_args = create_parser().parse_args(args=args) + + # Propagate parsed layout parameters to LAParams object + if parsed_args.no_laparams: + parsed_args.laparams = None + else: + parsed_args.laparams = LAParams( + line_overlap=parsed_args.line_overlap, + char_margin=parsed_args.char_margin, + line_margin=parsed_args.line_margin, + word_margin=parsed_args.word_margin, + boxes_flow=parsed_args.boxes_flow, + detect_vertical=parsed_args.detect_vertical, + all_texts=parsed_args.all_texts, + ) + + if parsed_args.page_numbers: + parsed_args.page_numbers = {x - 1 for x in parsed_args.page_numbers} + + if parsed_args.pagenos: + parsed_args.page_numbers = {int(x) - 1 for x in parsed_args.pagenos.split(",")} + + if parsed_args.output_type == "text" and parsed_args.outfile != "-": + for override, alttype in OUTPUT_TYPES: + if parsed_args.outfile.endswith(override): + parsed_args.output_type = alttype + + return parsed_args + + +def main(args: list[str] | None = None) -> int: + parsed_args = parse_args(args) + extract_text(**vars(parsed_args)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.venv312/Scripts/pip.exe b/.venv312/Scripts/pip.exe new file mode 100644 index 0000000000..68f707af83 Binary files /dev/null and b/.venv312/Scripts/pip.exe differ diff --git a/.venv312/Scripts/pip3.12.exe b/.venv312/Scripts/pip3.12.exe new file mode 100644 index 0000000000..68f707af83 Binary files /dev/null and b/.venv312/Scripts/pip3.12.exe differ diff --git a/.venv312/Scripts/pip3.exe b/.venv312/Scripts/pip3.exe new file mode 100644 index 0000000000..68f707af83 Binary files /dev/null and b/.venv312/Scripts/pip3.exe differ diff --git a/.venv312/Scripts/pkginfo2.exe b/.venv312/Scripts/pkginfo2.exe new file mode 100644 index 0000000000..35ea0e0f3d Binary files /dev/null and b/.venv312/Scripts/pkginfo2.exe differ diff --git a/.venv312/Scripts/pygmentize.exe b/.venv312/Scripts/pygmentize.exe new file mode 100644 index 0000000000..68a2ac6138 Binary files /dev/null and b/.venv312/Scripts/pygmentize.exe differ diff --git a/.venv312/Scripts/pyinstrument.exe b/.venv312/Scripts/pyinstrument.exe new file mode 100644 index 0000000000..9892a21349 Binary files /dev/null and b/.venv312/Scripts/pyinstrument.exe differ diff --git a/.venv312/Scripts/pysemver.exe b/.venv312/Scripts/pysemver.exe new file mode 100644 index 0000000000..aac2251dcc Binary files /dev/null and b/.venv312/Scripts/pysemver.exe differ diff --git a/.venv312/Scripts/pyspdxtools.exe b/.venv312/Scripts/pyspdxtools.exe new file mode 100644 index 0000000000..e8c4886dba Binary files /dev/null and b/.venv312/Scripts/pyspdxtools.exe differ diff --git a/.venv312/Scripts/pyspdxtools3.exe b/.venv312/Scripts/pyspdxtools3.exe new file mode 100644 index 0000000000..923f4a2991 Binary files /dev/null and b/.venv312/Scripts/pyspdxtools3.exe differ diff --git a/.venv312/Scripts/python-inspector.exe b/.venv312/Scripts/python-inspector.exe new file mode 100644 index 0000000000..bc86b3f3a9 Binary files /dev/null and b/.venv312/Scripts/python-inspector.exe differ diff --git a/.venv312/Scripts/python.exe b/.venv312/Scripts/python.exe new file mode 100644 index 0000000000..ba0cd04091 Binary files /dev/null and b/.venv312/Scripts/python.exe differ diff --git a/.venv312/Scripts/pythonw.exe b/.venv312/Scripts/pythonw.exe new file mode 100644 index 0000000000..68b3cfe988 Binary files /dev/null and b/.venv312/Scripts/pythonw.exe differ diff --git a/.venv312/Scripts/rdf2dot.exe b/.venv312/Scripts/rdf2dot.exe new file mode 100644 index 0000000000..5c3d428544 Binary files /dev/null and b/.venv312/Scripts/rdf2dot.exe differ diff --git a/.venv312/Scripts/rdfgraphisomorphism.exe b/.venv312/Scripts/rdfgraphisomorphism.exe new file mode 100644 index 0000000000..7abbff76a1 Binary files /dev/null and b/.venv312/Scripts/rdfgraphisomorphism.exe differ diff --git a/.venv312/Scripts/rdfpipe.exe b/.venv312/Scripts/rdfpipe.exe new file mode 100644 index 0000000000..7694572985 Binary files /dev/null and b/.venv312/Scripts/rdfpipe.exe differ diff --git a/.venv312/Scripts/rdfs2dot.exe b/.venv312/Scripts/rdfs2dot.exe new file mode 100644 index 0000000000..924608fa9e Binary files /dev/null and b/.venv312/Scripts/rdfs2dot.exe differ diff --git a/.venv312/Scripts/readelf.py b/.venv312/Scripts/readelf.py new file mode 100644 index 0000000000..a5edaca08e --- /dev/null +++ b/.venv312/Scripts/readelf.py @@ -0,0 +1,1996 @@ +#!E:\hell\scancode.io\.venv312\Scripts\python.exe +#------------------------------------------------------------------------------- +# scripts/readelf.py +# +# A clone of 'readelf' in Python, based on the pyelftools library +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +import argparse +import os, sys +import re +import string +import traceback +import itertools +# Note: zip has different behaviour between Python 2.x and 3.x. +# - Using izip ensures compatibility. +try: + from itertools import izip +except: + izip = zip + +# For running from development directory. It should take precedence over the +# installed pyelftools. +sys.path.insert(0, '.') + + +from elftools import __version__ +from elftools.common.exceptions import ELFError +from elftools.common.utils import bytes2str, iterbytes +from elftools.elf.elffile import ELFFile +from elftools.elf.dynamic import DynamicSection, DynamicSegment +from elftools.elf.enums import ENUM_D_TAG +from elftools.elf.segments import InterpSegment +from elftools.elf.sections import ( + NoteSection, SymbolTableSection, SymbolTableIndexSection +) +from elftools.elf.gnuversions import ( + GNUVerSymSection, GNUVerDefSection, + GNUVerNeedSection, + ) +from elftools.elf.relocation import RelocationSection +from elftools.elf.descriptions import ( + describe_ei_class, describe_ei_data, describe_ei_version, + describe_ei_osabi, describe_e_type, describe_e_machine, + describe_e_version_numeric, describe_p_type, describe_p_flags, + describe_rh_flags, describe_sh_type, describe_sh_flags, + describe_symbol_type, describe_symbol_bind, describe_symbol_visibility, + describe_symbol_shndx, describe_reloc_type, describe_dyn_tag, + describe_dt_flags, describe_dt_flags_1, describe_ver_flags, describe_note, + describe_attr_tag_arm, describe_attr_tag_riscv, describe_symbol_other + ) +from elftools.elf.constants import E_FLAGS +from elftools.elf.constants import E_FLAGS_MASKS +from elftools.elf.constants import SH_FLAGS +from elftools.elf.constants import SHN_INDICES +from elftools.dwarf.dwarfinfo import DWARFInfo +from elftools.dwarf.descriptions import ( + describe_reg_name, describe_attr_value, set_global_machine_arch, + describe_CFI_instructions, describe_CFI_register_rule, + describe_CFI_CFA_rule, describe_DWARF_expr + ) +from elftools.dwarf.constants import ( + DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file) +from elftools.dwarf.locationlists import LocationParser, LocationEntry, LocationViewPair, BaseAddressEntry as LocBaseAddressEntry, LocationListsPair +from elftools.dwarf.ranges import RangeEntry, BaseAddressEntry as RangeBaseAddressEntry, RangeListsPair +from elftools.dwarf.callframe import CIE, FDE, ZERO +from elftools.ehabi.ehabiinfo import CorruptEHABIEntry, CannotUnwindEHABIEntry, GenericEHABIEntry +from elftools.dwarf.enums import ENUM_DW_UT + +def _get_cu_base(cu): + top_die = cu.get_top_DIE() + attr = top_die.attributes + if 'DW_AT_low_pc' in attr: + return attr['DW_AT_low_pc'].value + elif 'DW_AT_entry_pc' in attr: + return attr['DW_AT_entry_pc'].value + elif 'DW_AT_ranges' in attr: + # Rare case but happens: rangelist in the top DIE. + # If there is a base or at least one absolute entry, + # this will give us the base IP for the CU. + rl = cu.dwarfinfo.range_lists().get_range_list_at_offset(attr['DW_AT_ranges'].value, cu) + base_ip = None + for r in rl: + if isinstance(r, RangeBaseAddressEntry): + ip = r.base_address + elif isinstance(r, RangeEntry) and r.is_absolute: + ip = r.begin_offset + else: + ip = None + if ip is not None and (base_ip is None or ip < base_ip): + base_ip = ip + if base_ip is None: + raise ValueError("Can't find the base IP (low_pc) for a CU") + return base_ip + else: + raise ValueError("Can't find the base IP (low_pc) for a CU") + +# Matcher for all control characters, for transforming them into "^X" form when +# formatting symbol names for display. +_CONTROL_CHAR_RE = re.compile(r'[\x01-\x1f]') + +def _format_symbol_name(s): + return _CONTROL_CHAR_RE.sub(lambda match: '^' + chr(0x40 + ord(match[0])), s) + +class ReadElf(object): + """ display_* methods are used to emit output into the output stream + """ + def __init__(self, file, output): + """ file: + stream object with the ELF file to read + + output: + output stream to write to + """ + self.elffile = ELFFile(file) + self.output = output + + # Lazily initialized if a debug dump is requested + self._dwarfinfo = None + + self._versioninfo = None + + self._shndx_sections = None + + def display_file_header(self): + """ Display the ELF file header + """ + self._emitline('ELF Header:') + self._emit(' Magic: ') + self._emit(' '.join('%2.2x' % b + for b in self.elffile.e_ident_raw)) + self._emitline(' ') + header = self.elffile.header + e_ident = header['e_ident'] + self._emitline(' Class: %s' % + describe_ei_class(e_ident['EI_CLASS'])) + self._emitline(' Data: %s' % + describe_ei_data(e_ident['EI_DATA'])) + self._emitline(' Version: %s' % + describe_ei_version(e_ident['EI_VERSION'])) + self._emitline(' OS/ABI: %s' % + describe_ei_osabi(e_ident['EI_OSABI'])) + self._emitline(' ABI Version: %d' % + e_ident['EI_ABIVERSION']) + self._emitline(' Type: %s' % + describe_e_type(header['e_type'], self.elffile)) + self._emitline(' Machine: %s' % + describe_e_machine(header['e_machine'])) + self._emitline(' Version: %s' % + describe_e_version_numeric(header['e_version'])) + self._emitline(' Entry point address: %s' % + self._format_hex(header['e_entry'])) + self._emit(' Start of program headers: %s' % + header['e_phoff']) + self._emitline(' (bytes into file)') + self._emit(' Start of section headers: %s' % + header['e_shoff']) + self._emitline(' (bytes into file)') + self._emitline(' Flags: %s%s' % + (self._format_hex(header['e_flags']), + self.decode_flags(header['e_flags']))) + self._emitline(' Size of this header: %s (bytes)' % + header['e_ehsize']) + self._emitline(' Size of program headers: %s (bytes)' % + header['e_phentsize']) + self._emitline(' Number of program headers: %s' % + header['e_phnum']) + self._emitline(' Size of section headers: %s (bytes)' % + header['e_shentsize']) + self._emit(' Number of section headers: %s' % + header['e_shnum']) + if header['e_shnum'] == 0 and self.elffile.num_sections() != 0: + self._emitline(' (%d)' % self.elffile.num_sections()) + else: + self._emitline('') + self._emit(' Section header string table index: %s' % + header['e_shstrndx']) + if header['e_shstrndx'] == SHN_INDICES.SHN_XINDEX: + self._emitline(' (%d)' % self.elffile.get_shstrndx()) + else: + self._emitline('') + + def decode_flags(self, flags): + description = "" + if self.elffile['e_machine'] == "EM_ARM": + eabi = flags & E_FLAGS.EF_ARM_EABIMASK + flags &= ~E_FLAGS.EF_ARM_EABIMASK + + if flags & E_FLAGS.EF_ARM_RELEXEC: + description += ', relocatable executabl' + flags &= ~E_FLAGS.EF_ARM_RELEXEC + + if eabi == E_FLAGS.EF_ARM_EABI_VER5: + EF_ARM_KNOWN_FLAGS = E_FLAGS.EF_ARM_ABI_FLOAT_SOFT|E_FLAGS.EF_ARM_ABI_FLOAT_HARD|E_FLAGS.EF_ARM_LE8|E_FLAGS.EF_ARM_BE8 + description += ', Version5 EABI' + if flags & E_FLAGS.EF_ARM_ABI_FLOAT_SOFT: + description += ", soft-float ABI" + elif flags & E_FLAGS.EF_ARM_ABI_FLOAT_HARD: + description += ", hard-float ABI" + + if flags & E_FLAGS.EF_ARM_BE8: + description += ", BE8" + elif flags & E_FLAGS.EF_ARM_LE8: + description += ", LE8" + + if flags & ~EF_ARM_KNOWN_FLAGS: + description += ', ' + else: + description += ', ' + + elif self.elffile['e_machine'] == 'EM_PPC64': + if flags & E_FLAGS.EF_PPC64_ABI_V2: + description += ', abiv2' + + elif self.elffile['e_machine'] == "EM_MIPS": + if flags & E_FLAGS.EF_MIPS_NOREORDER: + description += ", noreorder" + if flags & E_FLAGS.EF_MIPS_PIC: + description += ", pic" + if flags & E_FLAGS.EF_MIPS_CPIC: + description += ", cpic" + if (flags & E_FLAGS.EF_MIPS_ABI2): + description += ", abi2" + if (flags & E_FLAGS.EF_MIPS_32BITMODE): + description += ", 32bitmode" + if (flags & E_FLAGS_MASKS.EFM_MIPS_ABI_O32): + description += ", o32" + elif (flags & E_FLAGS_MASKS.EFM_MIPS_ABI_O64): + description += ", o64" + elif (flags & E_FLAGS_MASKS.EFM_MIPS_ABI_EABI32): + description += ", eabi32" + elif (flags & E_FLAGS_MASKS.EFM_MIPS_ABI_EABI64): + description += ", eabi64" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_1: + description += ", mips1" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_2: + description += ", mips2" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_3: + description += ", mips3" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_4: + description += ", mips4" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_5: + description += ", mips5" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_32R2: + description += ", mips32r2" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_64R2: + description += ", mips64r2" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_32: + description += ", mips32" + if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_64: + description += ", mips64" + + elif self.elffile['e_machine'] == "EM_RISCV": + if flags & E_FLAGS.EF_RISCV_RVC: + description += ", RVC" + if (flags & E_FLAGS.EF_RISCV_RVE): + description += ", RVE" + if (flags & E_FLAGS.EF_RISCV_TSO): + description += ", TSO" + if (flags & E_FLAGS.EF_RISCV_FLOAT_ABI) == E_FLAGS.EF_RISCV_FLOAT_ABI_SOFT: + description += ", soft-float ABI" + if (flags & E_FLAGS.EF_RISCV_FLOAT_ABI) == E_FLAGS.EF_RISCV_FLOAT_ABI_SINGLE: + description += ", single-float ABI" + if (flags & E_FLAGS.EF_RISCV_FLOAT_ABI) == E_FLAGS.EF_RISCV_FLOAT_ABI_DOUBLE: + description += ", double-float ABI" + if (flags & E_FLAGS.EF_RISCV_FLOAT_ABI) == E_FLAGS.EF_RISCV_FLOAT_ABI_QUAD: + description += ", quad-float ABI" + + elif self.elffile['e_machine'] == "EM_LOONGARCH": + if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_SOFT_FLOAT: + description += ", SOFT-FLOAT" + if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_SINGLE_FLOAT: + description += ", SINGLE-FLOAT" + if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_DOUBLE_FLOAT: + description += ", DOUBLE-FLOAT" + if (flags & E_FLAGS.EF_LOONGARCH_OBJABI_MASK) == E_FLAGS.EF_LOONGARCH_OBJABI_V0: + description += ", OBJ-v0" + if (flags & E_FLAGS.EF_LOONGARCH_OBJABI_MASK) == E_FLAGS.EF_LOONGARCH_OBJABI_V1: + description += ", OBJ-v1" + + return description + + def display_program_headers(self, show_heading=True): + """ Display the ELF program headers. + If show_heading is True, displays the heading for this information + (Elf file type is...) + """ + self._emitline() + if self.elffile.num_segments() == 0: + self._emitline('There are no program headers in this file.') + return + + elfheader = self.elffile.header + if show_heading: + self._emitline('Elf file type is %s' % + describe_e_type(elfheader['e_type'], self.elffile)) + self._emitline('Entry point is %s' % + self._format_hex(elfheader['e_entry'])) + # readelf weirness - why isn't e_phoff printed as hex? (for section + # headers, it is...) + self._emitline('There are %s program headers, starting at offset %s' % ( + self.elffile.num_segments(), elfheader['e_phoff'])) + self._emitline() + + self._emitline('Program Headers:') + + # Now comes the table of program headers with their attributes. Note + # that due to different formatting constraints of 32-bit and 64-bit + # addresses, there are some conditions on elfclass here. + # + # First comes the table heading + # + if self.elffile.elfclass == 32: + self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align') + else: + self._emitline(' Type Offset VirtAddr PhysAddr') + self._emitline(' FileSiz MemSiz Flags Align') + + # Now the entries + # + for segment in self.elffile.iter_segments(): + self._emit(' %-14s ' % describe_p_type(segment['p_type'])) + + if self.elffile.elfclass == 32: + self._emitline('%s %s %s %s %s %-3s %s' % ( + self._format_hex(segment['p_offset'], fieldsize=6), + self._format_hex(segment['p_vaddr'], fullhex=True), + self._format_hex(segment['p_paddr'], fullhex=True), + self._format_hex(segment['p_filesz'], fieldsize=5), + self._format_hex(segment['p_memsz'], fieldsize=5), + describe_p_flags(segment['p_flags']), + self._format_hex(segment['p_align']))) + else: # 64 + self._emitline('%s %s %s' % ( + self._format_hex(segment['p_offset'], fullhex=True), + self._format_hex(segment['p_vaddr'], fullhex=True), + self._format_hex(segment['p_paddr'], fullhex=True))) + self._emitline(' %s %s %-3s %s' % ( + self._format_hex(segment['p_filesz'], fullhex=True), + self._format_hex(segment['p_memsz'], fullhex=True), + describe_p_flags(segment['p_flags']), + # lead0x set to False for p_align, to mimic readelf. + # No idea why the difference from 32-bit mode :-| + self._format_hex(segment['p_align'], lead0x=False))) + + if isinstance(segment, InterpSegment): + self._emitline(' [Requesting program interpreter: %s]' % + segment.get_interp_name()) + + # Sections to segments mapping + # + if self.elffile.num_sections() == 0: + # No sections? We're done + return + + self._emitline('\n Section to Segment mapping:') + self._emitline(' Segment Sections...') + + for nseg, segment in enumerate(self.elffile.iter_segments()): + self._emit(' %2.2d ' % nseg) + + for section in self.elffile.iter_sections(): + if ( not section.is_null() and + not ((section['sh_flags'] & SH_FLAGS.SHF_TLS) != 0 and + section['sh_type'] == 'SHT_NOBITS' and + segment['p_type'] != 'PT_TLS') and + segment.section_in_segment(section)): + self._emit('%s ' % section.name) + + self._emitline('') + + def display_section_headers(self, show_heading=True): + """ Display the ELF section headers + """ + elfheader = self.elffile.header + if show_heading: + self._emitline('There are %s section headers, starting at offset %s' % ( + elfheader['e_shnum'], self._format_hex(elfheader['e_shoff']))) + + if self.elffile.num_sections() == 0: + self._emitline('There are no sections in this file.') + return + + self._emitline('\nSection Header%s:' % ( + 's' if self.elffile.num_sections() > 1 else '')) + + # Different formatting constraints of 32-bit and 64-bit addresses + # + if self.elffile.elfclass == 32: + self._emitline(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al') + else: + self._emitline(' [Nr] Name Type Address Offset') + self._emitline(' Size EntSize Flags Link Info Align') + + # Now the entries + # + for nsec, section in enumerate(self.elffile.iter_sections()): + self._emit(' [%2u] %-17.17s %-15.15s ' % ( + nsec, section.name, describe_sh_type(section['sh_type']))) + + if self.elffile.elfclass == 32: + self._emitline('%s %s %s %s %3s %2s %3s %2s' % ( + self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False), + self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False), + self._format_hex(section['sh_size'], fieldsize=6, lead0x=False), + self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False), + describe_sh_flags(section['sh_flags']), + section['sh_link'], section['sh_info'], + section['sh_addralign'])) + else: # 64 + self._emitline(' %s %s' % ( + self._format_hex(section['sh_addr'], fullhex=True, lead0x=False), + self._format_hex(section['sh_offset'], + fieldsize=16 if section['sh_offset'] > 0xffffffff else 8, + lead0x=False))) + self._emitline(' %s %s %3s %2s %3s %s' % ( + self._format_hex(section['sh_size'], fullhex=True, lead0x=False), + self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False), + describe_sh_flags(section['sh_flags']), + section['sh_link'], section['sh_info'], + section['sh_addralign'])) + + self._emitline('Key to Flags:') + self._emitline(' W (write), A (alloc), X (execute), M (merge),' + ' S (strings), I (info),') + self._emitline(' L (link order), O (extra OS processing required),' + ' G (group), T (TLS),') + self._emitline(' C (compressed), x (unknown), o (OS specific),' + ' E (exclude),') + self._emit(' ') + if self.elffile['e_machine'] == 'EM_ARM': + self._emit('y (purecode), ') + self._emitline('p (processor specific)') + + def display_symbol_tables(self): + """ Display the symbol tables contained in the file + """ + self._init_versioninfo() + + symbol_tables = [(idx, s) for idx, s in enumerate(self.elffile.iter_sections()) + if isinstance(s, SymbolTableSection)] + + if not symbol_tables and self.elffile.num_sections() == 0: + self._emitline('') + self._emitline('Dynamic symbol information is not available for' + ' displaying symbols.') + + for section_index, section in symbol_tables: + if not isinstance(section, SymbolTableSection): + continue + + if section['sh_entsize'] == 0: + self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % ( + section.name)) + continue + + self._emitline("\nSymbol table '%s' contains %d %s:" % ( + section.name, + section.num_symbols(), + 'entry' if section.num_symbols() == 1 else 'entries')) + + if self.elffile.elfclass == 32: + self._emitline(' Num: Value Size Type Bind Vis Ndx Name') + else: # 64 + self._emitline(' Num: Value Size Type Bind Vis Ndx Name') + + for nsym, symbol in enumerate(section.iter_symbols()): + version_info = '' + # readelf doesn't display version info for Solaris versioning + if (section['sh_type'] == 'SHT_DYNSYM' and + self._versioninfo['type'] == 'GNU'): + version = self._symbol_version(nsym) + if (version['name'] != symbol.name and + version['index'] not in ('VER_NDX_LOCAL', + 'VER_NDX_GLOBAL')): + if version['filename']: + # external symbol + version_info = '@%(name)s (%(index)i)' % version + else: + # internal symbol + if version['hidden']: + version_info = '@%(name)s' % version + else: + version_info = '@@%(name)s' % version + + symbol_name = symbol.name + # Print section names for STT_SECTION symbols as readelf does + if (symbol['st_info']['type'] == 'STT_SECTION' + and symbol['st_shndx'] != 'SHN_UNDEF' + and symbol['st_shndx'] < self.elffile.num_sections() + and symbol['st_name'] == 0): + symbol_name = self.elffile.get_section(symbol['st_shndx']).name + + # symbol names are truncated to 25 chars, similarly to readelf + self._emitline('%6d: %s %s %-7s %-6s %-7s %4s %.25s%s' % ( + nsym, + self._format_hex( + symbol['st_value'], fullhex=True, lead0x=False), + "%5d" % symbol['st_size'] if symbol['st_size'] < 100000 else hex(symbol['st_size']), + describe_symbol_type(symbol['st_info']['type']), + describe_symbol_bind(symbol['st_info']['bind']), + describe_symbol_other(symbol['st_other']), + describe_symbol_shndx(self._get_symbol_shndx(symbol, + nsym, + section_index)), + _format_symbol_name(symbol_name), + version_info)) + + def display_dynamic_tags(self): + """ Display the dynamic tags contained in the file + """ + has_dynamic_sections = False + for section in self.elffile.iter_sections(): + if not isinstance(section, DynamicSection): + continue + + has_dynamic_sections = True + self._emitline("\nDynamic section at offset %s contains %d %s:" % ( + self._format_hex(section['sh_offset']), + section.num_tags(), + 'entry' if section.num_tags() == 1 else 'entries')) + self._emitline(" Tag Type Name/Value") + + padding = 20 + (8 if self.elffile.elfclass == 32 else 0) + for tag in section.iter_tags(): + if tag.entry.d_tag == 'DT_NEEDED': + parsed = 'Shared library: [%s]' % tag.needed + elif tag.entry.d_tag == 'DT_RPATH': + parsed = 'Library rpath: [%s]' % tag.rpath + elif tag.entry.d_tag == 'DT_RUNPATH': + parsed = 'Library runpath: [%s]' % tag.runpath + elif tag.entry.d_tag == 'DT_SONAME': + parsed = 'Library soname: [%s]' % tag.soname + elif tag.entry.d_tag.endswith(('SZ', 'ENT')): + parsed = '%i (bytes)' % tag['d_val'] + elif tag.entry.d_tag == 'DT_FLAGS': + parsed = describe_dt_flags(tag.entry.d_val) + elif tag.entry.d_tag == 'DT_FLAGS_1': + parsed = 'Flags: %s' % describe_dt_flags_1(tag.entry.d_val) + elif tag.entry.d_tag.endswith(('NUM', 'COUNT')): + parsed = '%i' % tag['d_val'] + elif tag.entry.d_tag == 'DT_PLTREL': + s = describe_dyn_tag(tag.entry.d_val) + if s.startswith('DT_'): + s = s[3:] + parsed = '%s' % s + elif tag.entry.d_tag == 'DT_MIPS_FLAGS': + parsed = describe_rh_flags(tag.entry.d_val) + elif tag.entry.d_tag in ('DT_MIPS_SYMTABNO', + 'DT_MIPS_LOCAL_GOTNO'): + parsed = str(tag.entry.d_val) + elif tag.entry.d_tag == 'DT_AARCH64_BTI_PLT': + parsed = '' + else: + parsed = '%#x' % tag['d_val'] + + self._emitline(" %s %-*s %s" % ( + self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag), + fullhex=True, lead0x=True), + padding, + '(%s)' % (tag.entry.d_tag[3:],), + parsed)) + if not has_dynamic_sections: + self._emitline("\nThere is no dynamic section in this file.") + + def display_notes(self): + """ Display the notes contained in the file + """ + for section in self.elffile.iter_sections(): + if isinstance(section, NoteSection): + for note in section.iter_notes(): + self._emitline("\nDisplaying notes found in: {}".format( + section.name)) + self._emitline(' Owner Data size Description') + self._emitline(' %s %s\t%s' % ( + note['n_name'].ljust(20), + self._format_hex(note['n_descsz'], fieldsize=8), + describe_note(note, self.elffile.header.e_machine))) + + def display_relocations(self): + """ Display the relocations contained in the file + """ + has_relocation_sections = False + for section in self.elffile.iter_sections(): + if not isinstance(section, RelocationSection): + continue + + has_relocation_sections = True + self._emitline("\nRelocation section '%.128s' at offset %s contains %d %s:" % ( + section.name, + self._format_hex(section['sh_offset']), + section.num_relocations(), + 'entry' if section.num_relocations() == 1 else 'entries')) + if section.is_RELA(): + self._emitline(" Offset Info Type Sym. Value Sym. Name + Addend") + else: + self._emitline(" Offset Info Type Sym.Value Sym. Name") + + # The symbol table section pointed to in sh_link + symtable = self.elffile.get_section(section['sh_link']) + + for rel in section.iter_relocations(): + hexwidth = 8 if self.elffile.elfclass == 32 else 12 + self._emit('%s %s %-17.17s' % ( + self._format_hex(rel['r_offset'], + fieldsize=hexwidth, lead0x=False), + self._format_hex(rel['r_info'], + fieldsize=hexwidth, lead0x=False), + describe_reloc_type( + rel['r_info_type'], self.elffile))) + + if rel['r_info_sym'] == 0: + if section.is_RELA(): + fieldsize = 8 if self.elffile.elfclass == 32 else 16 + addend = self._format_hex(rel['r_addend'], lead0x=False) + self._emit(' %s %s' % (' ' * fieldsize, addend)) + self._emitline() + + else: + symbol = symtable.get_symbol(rel['r_info_sym']) + # Some symbols have zero 'st_name', so instead what's used + # is the name of the section they point at. Truncate symbol + # names (excluding version info) to 22 chars, similarly to + # readelf. + if symbol['st_name'] == 0: + symsecidx = self._get_symbol_shndx(symbol, + rel['r_info_sym'], + section['sh_link']) + symsec = self.elffile.get_section(symsecidx) + symbol_name = symsec.name + version = '' + else: + symbol_name = symbol.name + version = self._symbol_version(rel['r_info_sym']) + version = (version['name'] + if version and version['name'] else '') + symbol_name = '%.22s' % symbol_name + if version: + symbol_name += '@' + version + + self._emit(' %s %s' % ( + self._format_hex( + symbol['st_value'], + fullhex=True, lead0x=False), + _format_symbol_name(symbol_name))) + if section.is_RELA(): + self._emit(' %s %x' % ( + '+' if rel['r_addend'] >= 0 else '-', + abs(rel['r_addend']))) + self._emitline() + + # Emit the two additional relocation types for ELF64 MIPS + # binaries. + if (self.elffile.elfclass == 64 and + self.elffile['e_machine'] == 'EM_MIPS'): + for i in (2, 3): + rtype = rel['r_info_type%s' % i] + self._emit(' Type%s: %s' % ( + i, + describe_reloc_type(rtype, self.elffile))) + self._emitline() + + if not has_relocation_sections: + self._emitline('\nThere are no relocations in this file.') + + def display_arm_unwind(self): + if not self.elffile.has_ehabi_info(): + self._emitline('There are no .ARM.idx sections in this file.') + return + for ehabi_info in self.elffile.get_ehabi_infos(): + # Unwind section '.ARM.exidx' at offset 0x203e8 contains 1009 entries: + self._emitline("\nUnwind section '%s' at offset 0x%x contains %d %s" % ( + ehabi_info.section_name(), + ehabi_info.section_offset(), + ehabi_info.num_entry(), + 'entry' if ehabi_info.num_entry() == 1 else 'entries')) + + for i in range(ehabi_info.num_entry()): + entry = ehabi_info.get_entry(i) + self._emitline() + self._emitline("Entry %d:" % i) + if isinstance(entry, CorruptEHABIEntry): + self._emitline(" [corrupt] %s" % entry.reason) + continue + self._emit(" Function offset 0x%x: " % entry.function_offset) + if isinstance(entry, CannotUnwindEHABIEntry): + self._emitline("[cantunwind]") + continue + elif entry.eh_table_offset: + self._emitline("@0x%x" % entry.eh_table_offset) + else: + self._emitline("Compact (inline)") + if isinstance(entry, GenericEHABIEntry): + self._emitline(" Personality: 0x%x" % entry.personality) + else: + self._emitline(" Compact model index: %d" % entry.personality) + for mnemonic_item in entry.mnmemonic_array(): + self._emit(' ') + self._emitline(mnemonic_item) + + def display_version_info(self): + """ Display the version info contained in the file + """ + self._init_versioninfo() + + if not self._versioninfo['type']: + self._emitline("\nNo version information found in this file.") + return + + for section in self.elffile.iter_sections(): + if isinstance(section, GNUVerSymSection): + self._print_version_section_header(section, 'Version symbols') + num_symbols = section.num_symbols() + + # Symbol version info are printed four by four entries + for idx_by_4 in range(0, num_symbols, 4): + + self._emit(' %03x:' % idx_by_4) + + for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)): + + symbol_version = self._symbol_version(idx) + if symbol_version['index'] == 'VER_NDX_LOCAL': + version_index = 0 + version_name = '(*local*)' + elif symbol_version['index'] == 'VER_NDX_GLOBAL': + version_index = 1 + version_name = '(*global*)' + else: + version_index = symbol_version['index'] + version_name = '(%(name)s)' % symbol_version + + visibility = 'h' if symbol_version['hidden'] else ' ' + + self._emit('%4x%s%-13s' % ( + version_index, visibility, version_name)) + + self._emitline() + + elif isinstance(section, GNUVerDefSection): + self._print_version_section_header( + section, 'Version definition', indent=2) + + offset = 0 + for verdef, verdaux_iter in section.iter_versions(): + verdaux = next(verdaux_iter) + + name = verdaux.name + if verdef['vd_flags']: + flags = describe_ver_flags(verdef['vd_flags']) + # Mimic exactly the readelf output + flags += ' ' + else: + flags = 'none' + + self._emitline(' %s: Rev: %i Flags: %s Index: %i' + ' Cnt: %i Name: %s' % ( + self._format_hex(offset, fieldsize=6, + alternate=True), + verdef['vd_version'], flags, verdef['vd_ndx'], + verdef['vd_cnt'], name)) + + verdaux_offset = ( + offset + verdef['vd_aux'] + verdaux['vda_next']) + for idx, verdaux in enumerate(verdaux_iter, start=1): + self._emitline(' %s: Parent %i: %s' % + (self._format_hex(verdaux_offset, fieldsize=4), + idx, verdaux.name)) + verdaux_offset += verdaux['vda_next'] + + offset += verdef['vd_next'] + + elif isinstance(section, GNUVerNeedSection): + self._print_version_section_header(section, 'Version needs') + + offset = 0 + for verneed, verneed_iter in section.iter_versions(): + + self._emitline(' %s: Version: %i File: %s Cnt: %i' % ( + self._format_hex(offset, fieldsize=6, + alternate=True), + verneed['vn_version'], verneed.name, + verneed['vn_cnt'])) + + vernaux_offset = offset + verneed['vn_aux'] + for idx, vernaux in enumerate(verneed_iter, start=1): + if vernaux['vna_flags']: + flags = describe_ver_flags(vernaux['vna_flags']) + # Mimic exactly the readelf output + flags += ' ' + else: + flags = 'none' + + self._emitline( + ' %s: Name: %s Flags: %s Version: %i' % ( + self._format_hex(vernaux_offset, fieldsize=4), + vernaux.name, flags, + vernaux['vna_other'])) + + vernaux_offset += vernaux['vna_next'] + + offset += verneed['vn_next'] + + def display_arch_specific(self): + """ Display the architecture-specific info contained in the file. + """ + if self.elffile['e_machine'] == 'EM_ARM': + self._display_arch_specific_arm() + elif self.elffile['e_machine'] == 'EM_RISCV': + self._display_arch_specific_riscv() + + def display_hex_dump(self, section_spec): + """ Display a hex dump of a section. section_spec is either a section + number or a name. + """ + section = self._section_from_spec(section_spec) + if section is None: + # readelf prints the warning to stderr. Even though stderrs are not compared + # in tests, we comply with that behavior. + sys.stderr.write('readelf: Warning: Section \'%s\' was not dumped because it does not exist!\n' % ( + section_spec)) + return + if section['sh_type'] == 'SHT_NOBITS': + self._emitline("\nSection '%s' has no data to dump." % ( + section_spec)) + return + + self._emitline("\nHex dump of section '%s':" % section.name) + self._note_relocs_for_section(section) + addr = section['sh_addr'] + data = section.data() + dataptr = 0 + + while dataptr < len(data): + bytesleft = len(data) - dataptr + # chunks of 16 bytes per line + linebytes = 16 if bytesleft > 16 else bytesleft + + self._emit(' %s ' % self._format_hex(addr, fieldsize=8)) + for i in range(16): + if i < linebytes: + self._emit('%2.2x' % data[dataptr + i]) + else: + self._emit(' ') + if i % 4 == 3: + self._emit(' ') + + for i in range(linebytes): + c = data[dataptr + i : dataptr + i + 1] + if c[0] >= 32 and c[0] < 0x7f: + self._emit(bytes2str(c)) + else: + self._emit(bytes2str(b'.')) + + self._emitline() + addr += linebytes + dataptr += linebytes + + self._emitline() + + def display_string_dump(self, section_spec): + """ Display a strings dump of a section. section_spec is either a + section number or a name. + """ + section = self._section_from_spec(section_spec) + if section is None: + # readelf prints the warning to stderr. Even though stderrs are not compared + # in tests, we comply with that behavior. + sys.stderr.write('readelf.py: Warning: Section \'%s\' was not dumped because it does not exist!\n' % ( + section_spec)) + return + if section['sh_type'] == 'SHT_NOBITS': + self._emitline("\nSection '%s' has no data to dump." % ( + section_spec)) + return + + self._emitline("\nString dump of section '%s':" % section.name) + + found = False + data = section.data() + dataptr = 0 + + while dataptr < len(data): + while ( dataptr < len(data) and + not (32 <= data[dataptr] <= 127)): + dataptr += 1 + + if dataptr >= len(data): + break + + endptr = dataptr + while endptr < len(data) and data[endptr] != 0: + endptr += 1 + + found = True + self._emitline(' [%6x] %s' % ( + dataptr, bytes2str(data[dataptr:endptr]))) + + dataptr = endptr + + if not found: + self._emitline(' No strings found in this section.') + else: + self._emitline() + + def display_debug_dump(self, dump_what): + """ Dump a DWARF section + """ + self._init_dwarfinfo() + if self._dwarfinfo is None: + return + + set_global_machine_arch(self.elffile.get_machine_arch()) + + if dump_what == 'info': + self._dump_debug_info() + self._dump_debug_types() + elif dump_what == 'decodedline': + self._dump_debug_line_programs() + elif dump_what == 'frames': + self._dump_debug_frames() + elif dump_what == 'frames-interp': + self._dump_debug_frames_interp() + elif dump_what == 'aranges': + self._dump_debug_aranges() + elif dump_what in { 'pubtypes', 'pubnames' }: + self._dump_debug_namelut(dump_what) + elif dump_what == 'loc': + self._dump_debug_locations() + elif dump_what == 'Ranges': + self._dump_debug_ranges() + else: + self._emitline('debug dump not yet supported for "%s"' % dump_what) + + def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True, + alternate=False): + """ Format an address into a hexadecimal string. + + fieldsize: + Size of the hexadecimal field (with leading zeros to fit the + address into. For example with fieldsize=8, the format will + be %08x + If None, the minimal required field size will be used. + + fullhex: + If True, override fieldsize to set it to the maximal size + needed for the elfclass + + lead0x: + If True, leading 0x is added + + alternate: + If True, override lead0x to emulate the alternate + hexadecimal form specified in format string with the # + character: only non-zero values are prefixed with 0x. + This form is used by readelf. + """ + if alternate: + if addr == 0: + lead0x = False + else: + lead0x = True + if fieldsize is not None: + fieldsize -= 2 + + s = '0x' if lead0x else '' + if fullhex: + fieldsize = 8 if self.elffile.elfclass == 32 else 16 + if fieldsize is None: + field = '%x' + else: + field = '%' + '0%sx' % fieldsize + return s + field % addr + + def _print_version_section_header(self, version_section, name, lead0x=True, + indent=1): + """ Print a section header of one version related section (versym, + verneed or verdef) with some options to accomodate readelf + little differences between each header (e.g. indentation + and 0x prefixing). + """ + if hasattr(version_section, 'num_versions'): + num_entries = version_section.num_versions() + else: + num_entries = version_section.num_symbols() + + self._emitline("\n%s section '%s' contains %d %s:" % ( + name, version_section.name, num_entries, + 'entry' if num_entries == 1 else 'entries')) + self._emitline('%sAddr: %s Offset: %s Link: %i (%s)' % ( + ' ' * indent, + self._format_hex( + version_section['sh_addr'], fieldsize=16, lead0x=lead0x), + self._format_hex( + version_section['sh_offset'], fieldsize=8, lead0x=True), + version_section['sh_link'], + self.elffile.get_section(version_section['sh_link']).name + ) + ) + + def _init_versioninfo(self): + """ Search and initialize informations about version related sections + and the kind of versioning used (GNU or Solaris). + """ + if self._versioninfo is not None: + return + + self._versioninfo = {'versym': None, 'verdef': None, + 'verneed': None, 'type': None} + + for section in self.elffile.iter_sections(): + if isinstance(section, GNUVerSymSection): + self._versioninfo['versym'] = section + elif isinstance(section, GNUVerDefSection): + self._versioninfo['verdef'] = section + elif isinstance(section, GNUVerNeedSection): + self._versioninfo['verneed'] = section + elif isinstance(section, DynamicSection): + for tag in section.iter_tags(): + if tag['d_tag'] == 'DT_VERSYM': + self._versioninfo['type'] = 'GNU' + break + + if not self._versioninfo['type'] and ( + self._versioninfo['verneed'] or self._versioninfo['verdef']): + self._versioninfo['type'] = 'Solaris' + + def _symbol_version(self, nsym): + """ Return a dict containing information on the + or None if no version information is available + """ + self._init_versioninfo() + + symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden')) + + if (not self._versioninfo['versym'] or + nsym >= self._versioninfo['versym'].num_symbols()): + return None + + symbol = self._versioninfo['versym'].get_symbol(nsym) + index = symbol.entry['ndx'] + if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'): + index = int(index) + + if self._versioninfo['type'] == 'GNU': + # In GNU versioning mode, the highest bit is used to + # store whether the symbol is hidden or not + if index & 0x8000: + index &= ~0x8000 + symbol_version['hidden'] = True + + if (self._versioninfo['verdef'] and + index <= self._versioninfo['verdef'].num_versions()): + _, verdaux_iter = \ + self._versioninfo['verdef'].get_version(index) + symbol_version['name'] = next(verdaux_iter).name + else: + verneed, vernaux = \ + self._versioninfo['verneed'].get_version(index) + symbol_version['name'] = vernaux.name + symbol_version['filename'] = verneed.name + + symbol_version['index'] = index + return symbol_version + + def _section_from_spec(self, spec): + """ Retrieve a section given a "spec" (either number or name). + Return None if no such section exists in the file. + """ + try: + num = int(spec) + if num < self.elffile.num_sections(): + return self.elffile.get_section(num) + else: + return None + except ValueError: + # Not a number. Must be a name then + return self.elffile.get_section_by_name(spec) + + def _get_symbol_shndx(self, symbol, symbol_index, symtab_index): + """ Get the index into the section header table for the "symbol" + at "symbol_index" located in the symbol table with section index + "symtab_index". + """ + symbol_shndx = symbol['st_shndx'] + if symbol_shndx != SHN_INDICES.SHN_XINDEX: + return symbol_shndx + + # Check for or lazily construct index section mapping (symbol table + # index -> corresponding symbol table index section object) + if self._shndx_sections is None: + self._shndx_sections = {sec.symboltable: sec for sec in self.elffile.iter_sections() + if isinstance(sec, SymbolTableIndexSection)} + return self._shndx_sections[symtab_index].get_section_index(symbol_index) + + def _note_relocs_for_section(self, section): + """ If there are relocation sections pointing to the givne section, + emit a note about it. + """ + for relsec in self.elffile.iter_sections(): + if isinstance(relsec, RelocationSection): + info_idx = relsec['sh_info'] + if self.elffile.get_section(info_idx) == section: + self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.') + return + + def _init_dwarfinfo(self): + """ Initialize the DWARF info contained in the file and assign it to + self._dwarfinfo. + Leave self._dwarfinfo at None if no DWARF info was found in the file + """ + if self._dwarfinfo is not None: + return + + if self.elffile.has_dwarf_info(): + self._dwarfinfo = self.elffile.get_dwarf_info() + else: + self._dwarfinfo = None + + def _dump_debug_info(self): + """ Dump the debugging info section. + """ + if not self._dwarfinfo.has_debug_info: + return + self._emitline('Contents of the %s section:\n' % self._dwarfinfo.debug_info_sec.name) + + # Offset of the .debug_info section in the stream + section_offset = self._dwarfinfo.debug_info_sec.global_offset + + for cu in self._dwarfinfo.iter_CUs(): + self._emitline(' Compilation Unit @ offset %s:' % + self._format_hex(cu.cu_offset, alternate=True)) + self._emitline(' Length: %s (%s)' % ( + self._format_hex(cu['unit_length']), + '%s-bit' % cu.dwarf_format())) + self._emitline(' Version: %s' % cu['version']) + if cu['version'] >= 5: + if cu.header.get("unit_type", ''): + unit_type = cu.header.unit_type + self._emitline(' Unit Type: %s (%d)' % ( + unit_type, ENUM_DW_UT.get(cu.header.unit_type, 0))) + self._emitline(' Abbrev Offset: %s' % ( + self._format_hex(cu['debug_abbrev_offset'], alternate=True))) + self._emitline(' Pointer Size: %s' % cu['address_size']) + if unit_type in ('DW_UT_skeleton', 'DW_UT_split_compile'): + self._emitline(' Dwo id: %s' % cu['dwo_id']) + elif unit_type in ('DW_UT_type', 'DW_UT_split_type'): + self._emitline(' Signature: 0x%x' % cu['type_signature']) + self._emitline(' Type Offset: 0x%x' % cu['type_offset']) + else: + self._emitline(' Abbrev Offset: %s' % ( + self._format_hex(cu['debug_abbrev_offset'], alternate=True))), + self._emitline(' Pointer Size: %s' % cu['address_size']) + + # The nesting depth of each DIE within the tree of DIEs must be + # displayed. To implement this, a counter is incremented each time + # the current DIE has children, and decremented when a null die is + # encountered. Due to the way the DIE tree is serialized, this will + # correctly reflect the nesting depth + # + die_depth = 0 + current_function = None + for die in cu.iter_DIEs(): + if die.tag == 'DW_TAG_subprogram': + current_function = die + self._emitline(' <%s><%x>: Abbrev Number: %s%s' % ( + die_depth, + die.offset, + die.abbrev_code, + (' (%s)' % die.tag) if not die.is_null() else '')) + if die.is_null(): + die_depth -= 1 + continue + + for attr in die.attributes.values(): + name = attr.name + # Unknown attribute values are passed-through as integers + if isinstance(name, int): + name = 'Unknown AT value: %x' % name + + attr_desc = describe_attr_value(attr, die, section_offset) + + if 'DW_OP_fbreg' in attr_desc and current_function and not 'DW_AT_frame_base' in current_function.attributes: + postfix = ' [without dw_at_frame_base]' + else: + postfix = '' + + self._emitline(' <%x> %-18s: %s%s' % ( + attr.offset, + name, + attr_desc, + postfix)) + + if die.has_children: + die_depth += 1 + + self._emitline() + + def _dump_debug_types(self): + """Dump the debug types section + """ + if not self._dwarfinfo.has_debug_info: + return + if self._dwarfinfo.debug_types_sec is None: + return + self._emitline('Contents of the %s section:\n' % self._dwarfinfo.debug_types_sec.name) + + # Offset of the .debug_types section in the stream + section_offset = self._dwarfinfo.debug_types_sec.global_offset + + for tu in self._dwarfinfo.iter_TUs(): + self._emitline(' Compilation Unit @ offset %s:' % + self._format_hex(tu.tu_offset, alternate=True)) + self._emitline(' Length: %s (%s)' % (self._format_hex(tu['unit_length']), + '%s-bit' % tu.dwarf_format())) + self._emitline(' Version: %s' % tu['version']) + self._emitline(' Abbrev Offset: %s' % (self._format_hex(tu['debug_abbrev_offset'], alternate=True))) + self._emitline(' Pointer Size: %s' % tu['address_size']) + self._emitline(' Signature: 0x%x' % tu['signature']) + self._emitline(' Type Offset: 0x%x' % tu['type_offset']) + + die_depth = 0 + for die in tu.iter_DIEs(): + self._emitline(' <%s><%x>: Abbrev Number: %s%s' % ( + die_depth, + die.offset, + die.abbrev_code, + (' (%s)' % die.tag) if not die.is_null() else '')) + if die.is_null(): + die_depth -= 1 + continue + + for attr in die.attributes.values(): + name = attr.name + # Unknown attribute values are passed-through as integers + if isinstance(name, int): + name = 'Unknown AT value: %x' % name + + attr_desc = describe_attr_value(attr, die, section_offset) + + self._emitline(' <%x> %-18s: %s' % ( + attr.offset, + name, + attr_desc)) + + if die.has_children: + die_depth += 1 + + self._emitline() + + def _dump_debug_line_programs(self): + """ Dump the (decoded) line programs from .debug_line + The programs are dumped in the order of the CUs they belong to. + """ + if not self._dwarfinfo.has_debug_info: + return + self._emitline('Contents of the %s section:' % self._dwarfinfo.debug_line_sec.name) + self._emitline() + lineprogram_list = [] + + for cu in self._dwarfinfo.iter_CUs(): + # Avoid dumping same lineprogram multiple times + lineprogram = self._dwarfinfo.line_program_for_CU(cu) + + if lineprogram is None or lineprogram in lineprogram_list: + continue + + lineprogram_list.append(lineprogram) + ver5 = lineprogram.header.version >= 5 + + cu_filename = bytes2str(lineprogram['file_entry'][0].name) + if len(lineprogram['include_directory']) > 0: + # GNU readelf 2.38 only outputs directory in wide mode + self._emitline('%s:' % cu_filename) + else: + self._emitline('CU: %s:' % cu_filename) + + self._emitline('File name Line number Starting address Stmt') + # GNU readelf has a View column that we don't try to replicate + # The autotest has logic in place to ignore that + + # Print each state's file, line and address information. For some + # instructions other output is needed to be compatible with + # readelf. + for entry in lineprogram.get_entries(): + state = entry.state + if state is None: + # Special handling for commands that don't set a new state + if entry.command == DW_LNS_set_file: + file_entry = lineprogram['file_entry'][entry.args[0] - 1] + if file_entry.dir_index == 0: + # current directory + self._emitline('\n./%s:[++]' % ( + bytes2str(file_entry.name))) + else: + self._emitline('\n%s/%s:' % ( + bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]), + bytes2str(file_entry.name))) + elif entry.command == DW_LNE_define_file: + self._emitline('%s:' % ( + bytes2str(lineprogram['include_directory'][entry.args[0].dir_index]))) + elif lineprogram['version'] < 4 or self.elffile['e_machine'] == 'EM_PPC64': + self._emitline('%-35s %11s %18s %s' % ( + bytes2str(lineprogram['file_entry'][state.file - 1].name), + state.line if not state.end_sequence else '-', + '0' if state.address == 0 else self._format_hex(state.address), + 'x' if state.is_stmt and not state.end_sequence else '')) + else: + # In readelf, on non-VLIW machines there is no op_index postfix after address. + # It used to be unconditional. + self._emitline('%-35s %s %18s%s %s' % ( + bytes2str(lineprogram['file_entry'][state.file - 1].name), + "%11d" % (state.line,) if not state.end_sequence else '-', + '0' if state.address == 0 else self._format_hex(state.address), + '' if lineprogram.header.maximum_operations_per_instruction == 1 else '[%d]' % (state.op_index,), + 'x' if state.is_stmt and not state.end_sequence else '')) + if entry.command == DW_LNS_copy: + # Another readelf oddity... + self._emitline() + + def _dump_frames_info(self, section, cfi_entries): + """ Dump the raw call frame info in a section. + + `section` is the Section instance that contains the call frame info + while `cfi_entries` must be an iterable that yields the sequence of + CIE or FDE instances. + """ + self._emitline('Contents of the %s section:' % section.name) + + for entry in cfi_entries: + if isinstance(entry, CIE): + self._emitline('\n%08x %s %s CIE' % ( + entry.offset, + self._format_hex(entry['length'], fullhex=True, lead0x=False), + self._format_hex(entry['CIE_id'], fieldsize=8, lead0x=False))) + self._emitline(' Version: %d' % entry['version']) + self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation'])) + if(entry['version'] >= 4): + self._emitline(' Pointer Size: %d' % entry['address_size']) + self._emitline(' Segment Size: %d' % entry['segment_size']) + self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor']) + self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor']) + self._emitline(' Return address column: %d' % entry['return_address_register']) + if entry.augmentation_bytes: + self._emitline(' Augmentation data: {}'.format(' '.join( + '{:02x}'.format(ord(b)) + for b in iterbytes(entry.augmentation_bytes) + ))) + self._emitline() + + elif isinstance(entry, FDE): + # Readelf bug #31973 + length = entry['length'] if entry.cie.offset < entry.offset else entry.cie['length'] + self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % ( + entry.offset, + self._format_hex(length, fullhex=True, lead0x=False), + self._format_hex(entry['CIE_pointer'], fieldsize=8, lead0x=False), + entry.cie.offset, + self._format_hex(entry['initial_location'], fullhex=True, lead0x=False), + self._format_hex( + entry['initial_location'] + entry['address_range'], + fullhex=True, lead0x=False))) + if entry.augmentation_bytes: + self._emitline(' Augmentation data: {}'.format(' '.join( + '{:02x}'.format(ord(b)) + for b in iterbytes(entry.augmentation_bytes) + ))) + + else: # ZERO terminator + assert isinstance(entry, ZERO) + self._emitline('\n%08x ZERO terminator' % entry.offset) + continue + + self._emit(describe_CFI_instructions(entry)) + self._emitline() + + def _dump_debug_frames(self): + """ Dump the raw frame info from .debug_frame and .eh_frame sections. + """ + if self._dwarfinfo.has_EH_CFI(): + self._dump_frames_info( + self._dwarfinfo.eh_frame_sec, + self._dwarfinfo.EH_CFI_entries()) + self._emitline() + + if self._dwarfinfo.has_CFI(): + self._dump_frames_info( + self._dwarfinfo.debug_frame_sec, + self._dwarfinfo.CFI_entries()) + + def _dump_debug_namelut(self, what): + """ + Dump the debug pubnames section. + """ + if what == 'pubnames': + namelut = self._dwarfinfo.get_pubnames() + section = self._dwarfinfo.debug_pubnames_sec + else: + namelut = self._dwarfinfo.get_pubtypes() + section = self._dwarfinfo.debug_pubtypes_sec + + # readelf prints nothing if the section is not present. + if namelut is None or len(namelut) == 0: + return + + self._emitline('Contents of the %s section:' % section.name) + self._emitline() + + cu_headers = namelut.get_cu_headers() + + # go over CU-by-CU first and item-by-item next. + for (cu_hdr, (cu_ofs, items)) in izip(cu_headers, itertools.groupby( + namelut.items(), key = lambda x: x[1].cu_ofs)): + + self._emitline(' Length: %d' % cu_hdr.unit_length) + self._emitline(' Version: %d' % cu_hdr.version) + self._emitline(' Offset into .debug_info section: 0x%x' % cu_hdr.debug_info_offset) + self._emitline(' Size of area in .debug_info section: %d' % cu_hdr.debug_info_length) + self._emitline() + self._emitline(' Offset Name') + for item in items: + self._emitline(' %x %s' % (item[1].die_ofs - cu_ofs, item[0])) + self._emitline() + + def _dump_debug_aranges(self): + """ Dump the aranges table + """ + aranges_table = self._dwarfinfo.get_aranges() + if aranges_table == None: + return + # Seems redundant, but we need to get the unsorted set of entries + # to match system readelf. + # Also, sometimes there are blank sections in aranges, but readelf + # dumps them, so we should too. + unordered_entries = aranges_table._get_entries(need_empty=True) + + if len(unordered_entries) == 0: + self._emitline() + self._emitline("Section '.debug_aranges' has no debugging data.") + return + + self._emitline('Contents of the %s section:' % self._dwarfinfo.debug_aranges_sec.name) + self._emitline() + prev_offset = None + for entry in unordered_entries: + if prev_offset != entry.info_offset: + if entry != unordered_entries[0]: + self._emitline(' %s %s' % ( + self._format_hex(0, fullhex=True, lead0x=False), + self._format_hex(0, fullhex=True, lead0x=False))) + self._emitline(' Length: %d' % (entry.unit_length)) + self._emitline(' Version: %d' % (entry.version)) + self._emitline(' Offset into .debug_info: 0x%x' % (entry.info_offset)) + self._emitline(' Pointer Size: %d' % (entry.address_size)) + self._emitline(' Segment Size: %d' % (entry.segment_size)) + self._emitline() + self._emitline(' Address Length') + if entry.begin_addr != 0 or entry.length != 0: + self._emitline(' %s %s' % ( + self._format_hex(entry.begin_addr, fullhex=True, lead0x=False), + self._format_hex(entry.length, fullhex=True, lead0x=False))) + prev_offset = entry.info_offset + self._emitline(' %s %s' % ( + self._format_hex(0, fullhex=True, lead0x=False), + self._format_hex(0, fullhex=True, lead0x=False))) + + def _dump_frames_interp_info(self, section, cfi_entries): + """ Dump interpreted (decoded) frame information in a section. + + `section` is the Section instance that contains the call frame info + while `cfi_entries` must be an iterable that yields the sequence of + CIE or FDE instances. + """ + self._emitline('Contents of the %s section:' % section.name) + + for entry in cfi_entries: + if isinstance(entry, CIE): + self._emitline('\n%08x %s %s CIE "%s" cf=%d df=%d ra=%d' % ( + entry.offset, + self._format_hex(entry['length'], fullhex=True, lead0x=False), + self._format_hex(entry['CIE_id'], fieldsize=8, lead0x=False), + bytes2str(entry['augmentation']), + entry['code_alignment_factor'], + entry['data_alignment_factor'], + entry['return_address_register'])) + ra_regnum = entry['return_address_register'] + + elif isinstance(entry, FDE): + # Readelf bug #31973 - FDE length misreported if FDE precedes its CIE + length = entry['length'] if entry.cie.offset < entry.offset else entry.cie['length'] + self._emitline('\n%08x %s %s FDE cie=%08x pc=%s..%s' % ( + entry.offset, + self._format_hex(length, fullhex=True, lead0x=False), + self._format_hex(entry['CIE_pointer'], fieldsize=8, lead0x=False), + entry.cie.offset, + self._format_hex(entry['initial_location'], fullhex=True, lead0x=False), + self._format_hex(entry['initial_location'] + entry['address_range'], + fullhex=True, lead0x=False))) + ra_regnum = entry.cie['return_address_register'] + + # If the FDE brings adds no unwinding information compared to + # its CIE, omit its table. + if (len(entry.get_decoded().table) == + len(entry.cie.get_decoded().table)): + continue + + else: # ZERO terminator + assert isinstance(entry, ZERO) + self._emitline('\n%08x ZERO terminator' % entry.offset) + continue + + # Decode the table. + decoded_table = entry.get_decoded() + if len(decoded_table.table) == 0: + continue + + # Print the heading row for the decoded table + self._emit(' LOC') + self._emit(' ' if entry.structs.address_size == 4 else ' ') + self._emit(' CFA ') + + # Look at the registers the decoded table describes. + # We build reg_order here to match readelf's order. In particular, + # registers are sorted by their number, so that the register + # matching ra_regnum is usually listed last with a special heading. + # (LoongArch is a notable exception in that its return register's + # DWARF register number is not greater than other GPRs.) + decoded_table = entry.get_decoded() + reg_order = sorted(decoded_table.reg_order) + if len(decoded_table.reg_order): + # Headings for the registers + for regnum in reg_order: + if regnum == ra_regnum: + self._emit('ra ') + continue + self._emit('%-6s' % describe_reg_name(regnum)) + self._emitline() + + for line in decoded_table.table: + self._emit(self._format_hex( + line['pc'], fullhex=True, lead0x=False)) + + if line['cfa'] is not None: + s = describe_CFI_CFA_rule(line['cfa']) + else: + s = 'u' + self._emit(' %-9s' % s) + + for regnum in reg_order: + if regnum in line: + s = describe_CFI_register_rule(line[regnum]) + else: + s = 'u' + self._emit('%-6s' % s) + self._emitline() + self._emitline() + + def _dump_debug_frames_interp(self): + """ Dump the interpreted (decoded) frame information from .debug_frame + and .eh_frame sections. + """ + if self._dwarfinfo.has_EH_CFI(): + self._dump_frames_interp_info( + self._dwarfinfo.eh_frame_sec, + self._dwarfinfo.EH_CFI_entries()) + self._emitline() + + if self._dwarfinfo.has_CFI(): + self._dump_frames_interp_info( + self._dwarfinfo.debug_frame_sec, + self._dwarfinfo.CFI_entries()) + + def _dump_debug_locations(self): + """ Dump the location lists from .debug_loc/.debug_loclists section + """ + di = self._dwarfinfo + loc_lists_sec = di.location_lists() + if not loc_lists_sec: # No locations section - readelf outputs nothing + return + + if isinstance(loc_lists_sec, LocationListsPair): + self._dump_debug_locsection(di, loc_lists_sec._loc) + self._dump_debug_locsection(di, loc_lists_sec._loclists) + else: + self._dump_debug_locsection(di, loc_lists_sec) + + def _dump_debug_locsection(self, di, loc_lists_sec): + """ Dump the location lists from .debug_loc/.debug_loclists section + """ + ver5 = loc_lists_sec.version >= 5 + section_name = (di.debug_loclists_sec if ver5 else di.debug_loc_sec).name + + # To dump a location list, one needs to know the CU. + # Scroll through DIEs once, list the known location list offsets. + # Don't need this CU/DIE scan if all entries are absolute or prefixed by base, + # but let's not optimize for that yet. + cu_map = dict() # Loc list offset => CU + for cu in di.iter_CUs(): + for die in cu.iter_DIEs(): + for key in die.attributes: + attr = die.attributes[key] + if (LocationParser.attribute_has_location(attr, cu['version']) and + LocationParser._attribute_has_loc_list(attr, cu['version'])): + cu_map[attr.value] = cu + + addr_size = di.config.default_address_size # In bytes, 4 or 8 + addr_width = addr_size * 2 # In hex digits, 8 or 16 + line_template = " %%08x %%0%dx %%0%dx %%s%%s" % (addr_width, addr_width) + + loc_lists = list(loc_lists_sec.iter_location_lists()) + if len(loc_lists) == 0: + # Present but empty locations section - readelf outputs a message + self._emitline("\nSection '%s' has no debugging data." % (section_name,)) + return + + # The v5 loclists section consists of CUs - small header, and + # an optional loclist offset table. Readelf prints out the header data dump + # on top of every CU, so we should too. But we don't scroll through + # the loclists section, we are effectively scrolling through the info + # section (as to not stumble upon gaps in the secion, and not miss the + # GNU locviews, so we have to keep track which loclists-CU we are in. + # Same logic in v5 rnglists section dump. + lcus = list(loc_lists_sec.iter_CUs()) if ver5 else None + lcu_index = 0 + next_lcu_offset = 0 + + self._emitline('Contents of the %s section:\n' % (section_name,)) + if not ver5: + self._emitline(' Offset Begin End Expression') + + for loc_list in loc_lists: + # Emit CU headers before the current loclist, if we've moved to the next CU + if ver5 and loc_list[0].entry_offset > next_lcu_offset: + while loc_list[0].entry_offset > next_lcu_offset: + lcu = lcus[lcu_index] + self._dump_debug_loclists_CU_header(lcu) + next_lcu_offset = lcu.offset_after_length + lcu.unit_length + lcu_index += 1 + self._emitline(' Offset Begin End Expression') + self._dump_loclist(loc_list, line_template, cu_map) + + def _dump_loclist(self, loc_list, line_template, cu_map): + in_views = False + has_views = False + base_ip = None + loc_entry_count = 0 + cu = None + for entry in loc_list: + if isinstance(entry, LocationViewPair): + has_views = in_views = True + # The "v" before address is conditional in binutils, haven't figured out how + self._emitline(" %08x v%015x v%015x location view pair" % (entry.entry_offset, entry.begin, entry.end)) + else: + if in_views: + in_views = False + self._emitline("") + + # Readelf quirk: indexed loclists don't show the real base IP + if cu_map is None: + base_ip = 0 + elif cu is None: + cu = cu_map.get(entry.entry_offset, False) + if not cu: + raise ValueError("Location list can't be tracked to a CU") + + if isinstance(entry, LocationEntry): + if base_ip is None and not entry.is_absolute: + base_ip = _get_cu_base(cu) + + begin_offset = (0 if entry.is_absolute else base_ip) + entry.begin_offset + end_offset = (0 if entry.is_absolute else base_ip) + entry.end_offset + expr = describe_DWARF_expr(entry.loc_expr, cu.structs, cu.cu_offset) + if has_views: + view = loc_list[loc_entry_count] + postfix = ' (start == end)' if entry.begin_offset == entry.end_offset and view.begin == view.end else '' + self._emitline(' %08x v%015x v%015x views at %08x for:' %( + entry.entry_offset, + view.begin, + view.end, + view.entry_offset)) + self._emitline(' %016x %016x %s%s' %( + begin_offset, + end_offset, + expr, + postfix)) + loc_entry_count += 1 + else: + postfix = ' (start == end)' if entry.begin_offset == entry.end_offset else '' + self._emitline(line_template % ( + entry.entry_offset, + begin_offset, + end_offset, + expr, + postfix)) + elif isinstance(entry, LocBaseAddressEntry): + base_ip = entry.base_address + self._emitline(" %08x %016x (base address)" % (entry.entry_offset, entry.base_address)) + + # Pyelftools doesn't store the terminating entry, + # but readelf emits its offset, so this should too. + last = loc_list[-1] + self._emitline(" %08x " % (last.entry_offset + last.entry_length)) + + def _dump_debug_loclists_CU_header(self, cu): + # Header slightly different from that of v5 rangelist in-section CU header dump + self._emitline('Table at Offset %s' % self._format_hex(cu.cu_offset, alternate=True)) + self._emitline(' Length: %s' % self._format_hex(cu.unit_length, alternate=True)) + self._emitline(' DWARF version: %d' % cu.version) + self._emitline(' Address size: %d' % cu.address_size) + self._emitline(' Segment size: %d' % cu.segment_selector_size) + self._emitline(' Offset entries: %d\n' % cu.offset_count) + if cu.offsets and len(cu.offsets): + self._emitline(' Offsets starting at 0x%x:' % cu.offset_table_offset) + for i_offset in enumerate(cu.offsets): + self._emitline(' [%6d] 0x%x' % i_offset) + + def _dump_debug_ranges(self): + # TODO: GNU readelf format doesn't need entry_length? + di = self._dwarfinfo + range_lists_sec = di.range_lists() + if not range_lists_sec: # No ranges section - readelf outputs nothing + return + + if isinstance(range_lists_sec, RangeListsPair): + self._dump_debug_rangesection(di, range_lists_sec._ranges) + self._dump_debug_rangesection(di, range_lists_sec._rnglists) + else: + self._dump_debug_rangesection(di, range_lists_sec) + + def _dump_debug_rnglists_CU_header(self, cu): + self._emitline(' Table at Offset: %s:' % self._format_hex(cu.cu_offset, alternate=True)) + self._emitline(' Length: %s' % self._format_hex(cu.unit_length, alternate=True)) + self._emitline(' DWARF version: %d' % cu.version) + self._emitline(' Address size: %d' % cu.address_size) + self._emitline(' Segment size: %d' % cu.segment_selector_size) + self._emitline(' Offset entries: %d\n' % cu.offset_count) + if cu.offsets and len(cu.offsets): + self._emitline(' Offsets starting at 0x%x:' % cu.offset_table_offset) + for i_offset in enumerate(cu.offsets): + self._emitline(' [%6d] 0x%x' % i_offset) + + def _dump_debug_rangesection(self, di, range_lists_sec): + # Last amended to match readelf 2.41 + ver5 = range_lists_sec.version >= 5 + section_name = (di.debug_rnglists_sec if ver5 else di.debug_ranges_sec).name + addr_size = di.config.default_address_size # In bytes, 4 or 8 + addr_width = addr_size * 2 # In hex digits, 8 or 16 + line_template = " %%08x %%0%dx %%0%dx %%s" % (addr_width, addr_width) + base_template = " %%08x %%0%dx (base address)" % (addr_width) + base_template_indexed = " %%08x %%0%dx (base address index) %%0%dx (base address)" % (addr_width, addr_width) + + # In order to determine the base address of the range + # We need to know the corresponding CU. + cu_map = {die.attributes['DW_AT_ranges'].value : cu # Range list offset => CU + for cu in di.iter_CUs() + for die in cu.iter_DIEs() + if 'DW_AT_ranges' in die.attributes} + + rcus = list(range_lists_sec.iter_CUs()) if ver5 else None + rcu_index = 0 + next_rcu_offset = 0 + + range_lists = list(range_lists_sec.iter_range_lists()) + if len(range_lists) == 0: + # Present but empty ranges section - readelf outputs a message + self._emitline("\nSection '%s' has no debugging data." % section_name) + return + + self._emitline('Contents of the %s section:\n\n\n' % section_name) + if not ver5: + self._emitline(' Offset Begin End') + + for range_list in range_lists: + # Emit CU headers before the curernt rangelist + if ver5 and range_list[0].entry_offset > next_rcu_offset: + while range_list[0].entry_offset > next_rcu_offset: + rcu = rcus[rcu_index] + self._dump_debug_rnglists_CU_header(rcu) + next_rcu_offset = rcu.offset_after_length + rcu.unit_length + rcu_index += 1 + self._emitline(' Offset Begin End') + self._dump_rangelist(range_list, cu_map, ver5, line_template, base_template, base_template_indexed, range_lists_sec) + + # TODO: trailing empty CUs, if any? + + def _dump_rangelist(self, range_list, cu_map, ver5, line_template, base_template, base_template_indexed, range_lists_sec): + # Weird discrepancy in binutils: for DWARFv5 it outputs entry offset, + # for DWARF<=4 list offset. + first = range_list[0] + base_ip = _get_cu_base(cu_map[first.entry_offset]) + raw_v5_rangelist = None + for entry in range_list: + if isinstance(entry, RangeEntry): + postfix = ' (start == end)' if entry.begin_offset == entry.end_offset else '' + self._emitline(line_template % ( + entry.entry_offset if ver5 else first.entry_offset, + (0 if entry.is_absolute else base_ip) + entry.begin_offset, + (0 if entry.is_absolute else base_ip) + entry.end_offset, + postfix)) + elif isinstance(entry,RangeBaseAddressEntry): + base_ip = entry.base_address + # V5 base entries with index are reported differently in readelf - need to go back to the raw V5 format + # Maybe other subtypes too, but no such cases in the test corpus + raw_v5_entry = None + if ver5: + if not raw_v5_rangelist: + raw_v5_rangelist = range_lists_sec.get_range_list_at_offset_ex(range_list[0].entry_offset) + raw_v5_entry = next(re for re in raw_v5_rangelist if re.entry_offset == entry.entry_offset) + if raw_v5_entry and raw_v5_entry.entry_type == 'DW_RLE_base_addressx': + self._emitline(base_template_indexed % ( + entry.entry_offset, + raw_v5_entry.index, + entry.base_address)) + else: + self._emitline(base_template % ( + entry.entry_offset if ver5 else first.entry_offset, + entry.base_address)) + else: + raise NotImplementedError("Unknown object in a range list") + last = range_list[-1] + self._emitline(' %08x ' % (last.entry_offset + last.entry_length if ver5 else first.entry_offset)) + + def _display_attributes(self, attr_sec, descriptor): + """ Display the attributes contained in the section. + """ + for s in attr_sec.iter_subsections(): + self._emitline("Attribute Section: %s" % s.header['vendor_name']) + for ss in s.iter_subsubsections(): + h_val = "" if ss.header.extra is None else " ".join("%d" % x for x in ss.header.extra) + self._emitline(descriptor(ss.header.tag, h_val, None)) + + for attr in ss.iter_attributes(): + self._emit(' ') + self._emitline(descriptor(attr.tag, attr.value, attr.extra)) + + def _display_arch_specific_arm(self): + """ Display the ARM architecture-specific info contained in the file. + """ + attr_sec = self.elffile.get_section_by_name('.ARM.attributes') + self._display_attributes(attr_sec, describe_attr_tag_arm) + + def _display_arch_specific_riscv(self): + """ Display the RISC-V architecture-specific info contained in the file. + """ + attr_sec = self.elffile.get_section_by_name('.riscv.attributes') + self._display_attributes(attr_sec, describe_attr_tag_riscv) + + def _emit(self, s=''): + """ Emit an object to output + """ + self.output.write(str(s)) + + def _emitline(self, s=''): + """ Emit an object to output, followed by a newline + """ + self.output.write(str(s).rstrip() + '\n') + + +SCRIPT_DESCRIPTION = 'Display information about the contents of ELF format files' +VERSION_STRING = '%%(prog)s: based on pyelftools %s' % __version__ + + +def main(stream=None): + # parse the command-line arguments and invoke ReadElf + argparser = argparse.ArgumentParser( + usage='usage: %(prog)s [options] ', + description=SCRIPT_DESCRIPTION, + add_help=False, # -h is a real option of readelf + prog='readelf.py') + argparser.add_argument('file', + nargs='?', default=None, + help='ELF file to parse') + argparser.add_argument('-v', '--version', + action='version', version=VERSION_STRING) + argparser.add_argument('-d', '--dynamic', + action='store_true', dest='show_dynamic_tags', + help='Display the dynamic section') + argparser.add_argument('-H', '--help', + action='store_true', dest='help', + help='Display this information') + argparser.add_argument('-h', '--file-header', + action='store_true', dest='show_file_header', + help='Display the ELF file header') + argparser.add_argument('-l', '--program-headers', '--segments', + action='store_true', dest='show_program_header', + help='Display the program headers') + argparser.add_argument('-S', '--section-headers', '--sections', + action='store_true', dest='show_section_header', + help="Display the sections' headers") + argparser.add_argument('-e', '--headers', + action='store_true', dest='show_all_headers', + help='Equivalent to: -h -l -S') + argparser.add_argument('-s', '--symbols', '--syms', + action='store_true', dest='show_symbols', + help='Display the symbol table') + argparser.add_argument('-n', '--notes', + action='store_true', dest='show_notes', + help='Display the core notes (if present)') + argparser.add_argument('-r', '--relocs', + action='store_true', dest='show_relocs', + help='Display the relocations (if present)') + argparser.add_argument('-au', '--arm-unwind', + action='store_true', dest='show_arm_unwind', + help='Display the armeabi unwind information (if present)') + argparser.add_argument('-x', '--hex-dump', + action='store', dest='show_hex_dump', metavar='', + help='Dump the contents of section as bytes') + argparser.add_argument('-p', '--string-dump', + action='store', dest='show_string_dump', metavar='', + help='Dump the contents of section as strings') + argparser.add_argument('-V', '--version-info', + action='store_true', dest='show_version_info', + help='Display the version sections (if present)') + argparser.add_argument('-A', '--arch-specific', + action='store_true', dest='show_arch_specific', + help='Display the architecture-specific information (if present)') + argparser.add_argument('--debug-dump', + action='store', dest='debug_dump_what', metavar='', + help=( + 'Display the contents of DWARF debug sections. can ' + + 'one of {info,decodedline,frames,frames-interp,aranges,pubtypes,pubnames,loc,Ranges}')) + argparser.add_argument('--traceback', + action='store_true', dest='show_traceback', + help='Dump the Python traceback on ELFError' + ' exceptions from elftools') + + args = argparser.parse_args() + + if args.help or not args.file: + argparser.print_help() + sys.exit(0) + + if args.show_all_headers: + do_file_header = do_section_header = do_program_header = True + else: + do_file_header = args.show_file_header + do_section_header = args.show_section_header + do_program_header = args.show_program_header + + with open(args.file, 'rb') as file: + try: + readelf = ReadElf(file, stream or sys.stdout) + if do_file_header: + readelf.display_file_header() + if do_section_header: + readelf.display_section_headers( + show_heading=not do_file_header) + if do_program_header: + readelf.display_program_headers( + show_heading=not do_file_header) + if args.show_dynamic_tags: + readelf.display_dynamic_tags() + if args.show_symbols: + readelf.display_symbol_tables() + if args.show_notes: + readelf.display_notes() + if args.show_relocs: + readelf.display_relocations() + if args.show_arm_unwind: + readelf.display_arm_unwind() + if args.show_version_info: + readelf.display_version_info() + if args.show_arch_specific: + readelf.display_arch_specific() + if args.show_hex_dump: + readelf.display_hex_dump(args.show_hex_dump) + if args.show_string_dump: + readelf.display_string_dump(args.show_string_dump) + if args.debug_dump_what: + readelf.display_debug_dump(args.debug_dump_what) + except ELFError as ex: + sys.stdout.flush() + sys.stderr.write('ELF error: %s\n' % ex) + if args.show_traceback: + traceback.print_exc() + sys.exit(1) + + +def profile_main(): + # Run 'main' redirecting its output to readelfout.txt + # Saves profiling information in readelf.profile + PROFFILE = 'readelf.profile' + import cProfile + cProfile.run('main(open("readelfout.txt", "w"))', PROFFILE) + + # Dig in some profiling stats + import pstats + p = pstats.Stats(PROFFILE) + p.sort_stats('cumulative').print_stats(25) + + +#------------------------------------------------------------------------------- +if __name__ == '__main__': + main() + #profile_main() diff --git a/.venv312/Scripts/regen-package-docs.exe b/.venv312/Scripts/regen-package-docs.exe new file mode 100644 index 0000000000..65ed5aaf45 Binary files /dev/null and b/.venv312/Scripts/regen-package-docs.exe differ diff --git a/.venv312/Scripts/rehttpfs.exe b/.venv312/Scripts/rehttpfs.exe new file mode 100644 index 0000000000..642cab48f2 Binary files /dev/null and b/.venv312/Scripts/rehttpfs.exe differ diff --git a/.venv312/Scripts/rq.exe b/.venv312/Scripts/rq.exe new file mode 100644 index 0000000000..4246f5dec1 Binary files /dev/null and b/.venv312/Scripts/rq.exe differ diff --git a/.venv312/Scripts/rqinfo.exe b/.venv312/Scripts/rqinfo.exe new file mode 100644 index 0000000000..75b9df79bc Binary files /dev/null and b/.venv312/Scripts/rqinfo.exe differ diff --git a/.venv312/Scripts/rqworker.exe b/.venv312/Scripts/rqworker.exe new file mode 100644 index 0000000000..1fd61b6602 Binary files /dev/null and b/.venv312/Scripts/rqworker.exe differ diff --git a/.venv312/Scripts/run.exe b/.venv312/Scripts/run.exe new file mode 100644 index 0000000000..0842fb8170 Binary files /dev/null and b/.venv312/Scripts/run.exe differ diff --git a/.venv312/Scripts/sbom4bids.exe b/.venv312/Scripts/sbom4bids.exe new file mode 100644 index 0000000000..88d782e220 Binary files /dev/null and b/.venv312/Scripts/sbom4bids.exe differ diff --git a/.venv312/Scripts/scancode-license-data.exe b/.venv312/Scripts/scancode-license-data.exe new file mode 100644 index 0000000000..575f86f62f Binary files /dev/null and b/.venv312/Scripts/scancode-license-data.exe differ diff --git a/.venv312/Scripts/scancode-reindex-licenses.exe b/.venv312/Scripts/scancode-reindex-licenses.exe new file mode 100644 index 0000000000..74e23f93e4 Binary files /dev/null and b/.venv312/Scripts/scancode-reindex-licenses.exe differ diff --git a/.venv312/Scripts/scancode-reindex-package-patterns.exe b/.venv312/Scripts/scancode-reindex-package-patterns.exe new file mode 100644 index 0000000000..935cef88ba Binary files /dev/null and b/.venv312/Scripts/scancode-reindex-package-patterns.exe differ diff --git a/.venv312/Scripts/scancode-train-gibberish-model.exe b/.venv312/Scripts/scancode-train-gibberish-model.exe new file mode 100644 index 0000000000..a1ca54fc54 Binary files /dev/null and b/.venv312/Scripts/scancode-train-gibberish-model.exe differ diff --git a/.venv312/Scripts/scancode.exe b/.venv312/Scripts/scancode.exe new file mode 100644 index 0000000000..232f70fc5b Binary files /dev/null and b/.venv312/Scripts/scancode.exe differ diff --git a/.venv312/Scripts/scanpipe.exe b/.venv312/Scripts/scanpipe.exe new file mode 100644 index 0000000000..4205369bda Binary files /dev/null and b/.venv312/Scripts/scanpipe.exe differ diff --git a/.venv312/Scripts/sparqlquery.exe b/.venv312/Scripts/sparqlquery.exe new file mode 100644 index 0000000000..90994eb1c9 Binary files /dev/null and b/.venv312/Scripts/sparqlquery.exe differ diff --git a/.venv312/Scripts/sqlformat.exe b/.venv312/Scripts/sqlformat.exe new file mode 100644 index 0000000000..44f21833ff Binary files /dev/null and b/.venv312/Scripts/sqlformat.exe differ diff --git a/.venv312/Scripts/vba_extract.py b/.venv312/Scripts/vba_extract.py new file mode 100644 index 0000000000..6cfc0c57d8 --- /dev/null +++ b/.venv312/Scripts/vba_extract.py @@ -0,0 +1,79 @@ +#!E:\hell\scancode.io\.venv312\Scripts\python.exe + +############################################################################## +# +# vba_extract - A simple utility to extract a vbaProject.bin binary from an +# Excel 2007+ xlsm file for insertion into an XlsxWriter file. +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org +# + +import sys +from zipfile import BadZipFile, ZipFile + + +def extract_file(xlsm_zip, filename): + # Extract a single file from an Excel xlsm macro file. + data = xlsm_zip.read("xl/" + filename) + + # Write the data to a local file. + file = open(filename, "wb") + file.write(data) + file.close() + + +# The VBA project file and project signature file we want to extract. +vba_filename = "vbaProject.bin" +vba_signature_filename = "vbaProjectSignature.bin" + +# Get the xlsm file name from the commandline. +if len(sys.argv) > 1: + xlsm_file = sys.argv[1] +else: + print( + "\nUtility to extract a vbaProject.bin binary from an Excel 2007+ " + "xlsm macro file for insertion into an XlsxWriter file.\n" + "If the macros are digitally signed, extracts also a vbaProjectSignature.bin " + "file.\n" + "\n" + "See: https://xlsxwriter.readthedocs.io/working_with_macros.html\n" + "\n" + "Usage: vba_extract file.xlsm\n" + ) + sys.exit() + +try: + # Open the Excel xlsm file as a zip file. + xlsm_zip = ZipFile(xlsm_file, "r") + + # Read the xl/vbaProject.bin file. + extract_file(xlsm_zip, vba_filename) + print(f"Extracted: {vba_filename}") + + if "xl/" + vba_signature_filename in xlsm_zip.namelist(): + extract_file(xlsm_zip, vba_signature_filename) + print(f"Extracted: {vba_signature_filename}") + + +except IOError as e: + print(f"File error: {str(e)}") + sys.exit() + +except KeyError as e: + # Usually when there isn't a xl/vbaProject.bin member in the file. + print(f"File error: {str(e)}") + print(f"File may not be an Excel xlsm macro file: '{xlsm_file}'") + sys.exit() + +except BadZipFile as e: + # Usually if the file is an xls file and not an xlsm file. + print(f"File error: {str(e)}: '{xlsm_file}'") + print("File may not be an Excel xlsm macro file.") + sys.exit() + +except Exception as e: + # Catch any other exceptions. + print(f"File error: {str(e)}") + sys.exit() diff --git a/.venv312/Scripts/xmlschema-json2xml.exe b/.venv312/Scripts/xmlschema-json2xml.exe new file mode 100644 index 0000000000..990f753f67 Binary files /dev/null and b/.venv312/Scripts/xmlschema-json2xml.exe differ diff --git a/.venv312/Scripts/xmlschema-validate.exe b/.venv312/Scripts/xmlschema-validate.exe new file mode 100644 index 0000000000..7eafcedf59 Binary files /dev/null and b/.venv312/Scripts/xmlschema-validate.exe differ diff --git a/.venv312/Scripts/xmlschema-xml2json.exe b/.venv312/Scripts/xmlschema-xml2json.exe new file mode 100644 index 0000000000..c9a71b5580 Binary files /dev/null and b/.venv312/Scripts/xmlschema-xml2json.exe differ diff --git a/docs/images/tutorial-web-ui-messages-list.png b/docs/images/tutorial-web-ui-messages-list.png new file mode 100644 index 0000000000..8e71ef69f9 Binary files /dev/null and b/docs/images/tutorial-web-ui-messages-list.png differ diff --git a/docs/tutorial_web_ui_review_scan_results.rst b/docs/tutorial_web_ui_review_scan_results.rst index 790401bb47..7a5ff25060 100644 --- a/docs/tutorial_web_ui_review_scan_results.rst +++ b/docs/tutorial_web_ui_review_scan_results.rst @@ -17,7 +17,7 @@ results using the ScanCode.io web interface. On the homepage, you can click on the project name in the summary table to access a detailed project output page. You can also click any of the numbers -underneath the **Packages**, **Resources**, or **Errors** fields to be directed +underneath the **Packages**, **Resources**, or **Messages** fields to be directed to the field's corresponding information. Further, clicking on the pipeline's execution status —**Success** in this case— expands some extra pipeline details, Resources status, and Run log. @@ -68,13 +68,23 @@ resources by **Programming Language**, **Mime Type**, **Holder**, **Copyright**, .. image:: images/tutorial-web-ui-resources-filter.png -Errors ------- +Messages +-------- In addition to discovered packages and codebase resources, the ScanCode.io -homepage shows the number of existing errors, which you can click for detailed -description of each error. +homepage shows the number of project messages. These messages may include +different severity levels such as **INFO**, **WARNING**, and **ERROR**. + +Clicking on the **Messages** count will display a detailed list of all +project messages along with their severity and description. + +.. note:: + + In earlier versions of ScanCode.io, project issues were displayed under + an **Errors** section. In recent versions (v36.x and later), this has been + generalized into a **Messages** section that includes INFO, WARNING, + and ERROR severities. -.. image:: images/tutorial-web-ui-errors-list.png +.. image:: images/tutorial-web-ui-messages-list.png Other Information -----------------