Full Code of saferwall/pe for AI

main 984afb23943d cached
91 files
765.7 KB
233.6k tokens
1452 symbols
1 requests
Download .txt
Showing preview only (797K chars total). Download the full file or copy to clipboard to get everything.
Repository: saferwall/pe
Branch: main
Commit: 984afb23943d
Files: 91
Total size: 765.7 KB

Directory structure:
gitextract_so1rfj4w/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.YML
│   └── workflows/
│       └── ci.yaml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── anomaly.go
├── anomaly_test.go
├── arch.go
├── boundimports.go
├── boundimports_test.go
├── cmd/
│   ├── dump.go
│   ├── main.go
│   ├── size.go
│   └── size_test.go
├── debug.go
├── debug_test.go
├── delayimports.go
├── delayimports_test.go
├── dosheader.go
├── dosheader_test.go
├── dotnet.go
├── dotnet_helper.go
├── dotnet_metadata_tables.go
├── dotnet_test.go
├── exception.go
├── exception_test.go
├── exports.go
├── exports_test.go
├── file.go
├── file_test.go
├── globalptr.go
├── go.mod
├── go.sum
├── helper.go
├── helper_test.go
├── iat.go
├── imports.go
├── imports_test.go
├── loadconfig.go
├── loadconfig_test.go
├── log/
│   ├── README.md
│   ├── filter.go
│   ├── filter_test.go
│   ├── global.go
│   ├── global_test.go
│   ├── helper.go
│   ├── helper_test.go
│   ├── level.go
│   ├── level_test.go
│   ├── log.go
│   ├── log_test.go
│   ├── std.go
│   ├── std_test.go
│   ├── value.go
│   └── value_test.go
├── ntheader.go
├── ntheader_test.go
├── ordlookup.go
├── overlay.go
├── overlay_test.go
├── pe.go
├── reloc.go
├── reloc_test.go
├── resource.go
├── resource_test.go
├── richheader.go
├── richheader_test.go
├── scripts/
│   ├── extract-rsrc-lang.py
│   └── ms-lcid.txt
├── section.go
├── section_test.go
├── security.go
├── security_linux_mac.go
├── security_test.go
├── security_windows.go
├── staticcheck.conf
├── symbol.go
├── symbol_test.go
├── test/
│   ├── WdBoot.sys
│   ├── acpi.sys
│   ├── amdi2c.sys
│   ├── amdxata.sys
│   └── look
├── tls.go
├── tls_test.go
├── version.go
└── version_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
; https://editorconfig.org/

root = true

[*]
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4

[*.md]
indent_size = 4
trim_trailing_whitespace = false

eclint_indent_style = unset

[Dockerfile]
indent_size = 4

================================================
FILE: .gitattributes
================================================
# Treat all files in the Go repo as binary, with no git magic updating
# line endings. This produces predictable results in different environments.
#
# Windows users contributing to Go will need to use a modern version
# of git and editors capable of LF line endings.
#
# Windows .bat files are known to have multiple bugs when run with LF
# endings, and so they are checked in with CRLF endings, with a test
# in test/winbatch.go to catch problems. (See golang.org/issue/37791.)
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-codereview gofmt checks and tests.
#
# See golang.org/issue/9281.

* -text


================================================
FILE: .github/FUNDING.YML
================================================
github: LordNoteworthy

================================================
FILE: .github/workflows/ci.yaml
================================================
name: Build & Test

on: [push]

jobs:
  test:
    name: Build & Test
    strategy:
      fail-fast: false
      matrix:
        go-version: [1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x, 1.25.x, 1.26.x]
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ matrix.go-version }}

      - name: Build
        run: |
          go env -w GOFLAGS=-mod=mod
          go build -v ./...

      - name: Extract test data
        run: |
          cd test
          7z x "*.7z" -pinfected

      - name: Test With Coverage
        run: go test -race -coverprofile=coverage -covermode=atomic

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v2
        with:
          files: ./coverage
        if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'

      - name: Go vet
        run: |
          go vet .
        if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'

      - name: Staticcheck
        uses: dominikh/staticcheck-action@v1.3.1
        with:
          version: "2024.1"
          install-go: false
          cache-key: ${{ matrix.go }}
        if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage

# Dependency directories (remove the comment below to include it)
vendor/

# Code editors configs
.idea/
.vscode/launch.json

# Go fuzz artefact
crashers/
suppressions/

# Log files
*.log

test/testdata/

================================================
FILE: CHANGELOG.md
================================================
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.0] - Unreleased

### Added

- Permit more granular control over which data directories are parsed by [rabbitstack](https://github.com/rabbitstack) [#72](https://github.com/saferwall/pe/pull/72).
- Support parsing the different `retpoline` types: Imported Address, Indirect Branch and Switchable retpoline [#70](https://github.com/saferwall/pe/pull/70).
- Unit tests for load config directory [#70](https://github.com/saferwall/pe/pull/69).
- Unit tests for TLS directory [#69](https://github.com/saferwall/pe/pull/69).
- Unit tests for debug directory [#68](https://github.com/saferwall/pe/pull/68).
- Unit tests for resource directory and add functions to prettify resource (sub)languages [#66](https://github.com/saferwall/pe/pull/66).
- Annotate PE structures with JSON tags during JSON encoding [#64](https://github.com/saferwall/pe/pull/64), [#65](https://github.com/saferwall/pe/pull/65)  and [#67](https://github.com/saferwall/pe/pull/67).
- Improve PE dumper to print imports and unit test parsing imports data directory[#63](https://github.com/saferwall/pe/pull/63).
- Improve PE dumper to print section headers [#62](https://github.com/saferwall/pe/pull/62).
- Improve PE dumper to print PE headers [#61](https://github.com/saferwall/pe/pull/61).
- Add `SerialNumber`, `SignatureAlgorithm` and `PubKeyAlgorithm` to the `CertInfo` [#60](https://github.com/saferwall/pe/pull/60).
- Option to disable certificate validation [#59](https://github.com/saferwall/pe/pull/59).
- Improve PE dumper to print exceptions [#57](https://github.com/saferwall/pe/pull/57).
- Unit tests for debug directory [#49](https://github.com/saferwall/pe/pull/49).

### Fixed

- Bug while iterating over VolatileInfoRangeTable entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while iterating  (additional padding and loop condition) over DVRT relocation block entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while appending (twice) Control Flow Guard IAT entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while parsing `POGO` debug entry types [#68](https://github.com/saferwall/pe/pull/68).
- `Authentihash()` for instances w/o fd thanks to [flanfly](https://github.com/flanfly) [#47](https://github.com/saferwall/pe/pull/47).

### Changed

- Some fields has been renamed for consistency:
  - `RichHeader.XorKey` -> `RichHeader.XORKey`.
  - Any `Rva` substring -> `RVA` and any `Iat` substring -> `IAT`.
  - And many more.
- Some fields used internally in imports parsing were changed from a slice of pointers to a simple slice.
- Certificate.Content changed from `*pkcs7.PKCS7` to `pkcs7.PKCS7`.
- `Section.Entropy` changed from `float64` to `float64*` to distinguish between the case when the section entropy is equal to zero and the case when the entropy is equal to nil - meaning that it was never calculated.
- Remove `cobra` dependency from `cmd/pedumper` [#56](https://github.com/saferwall/pe/pull/56).

## [1.3.0] - 2022-08-04

## Added

- Authenticode signature validation in Windows [#43](https://github.com/saferwall/pe/pull/43).
- File information structure that helps to identify what parts of the PE file we have, such as `HasImports()` [#42](https://github.com/saferwall/pe/pull/42)..
- Calculate Rich header hash thanks to [wanglei-coder](https://github.com/wanglei-coder) [#38](https://github.com/saferwall/pe/pull/38).
- PE Overlay thanks to [wanglei-coder](https://github.com/wanglei-coder) [#37](https://github.com/saferwall/pe/pull/37).
- Unit tests for DOS header parsing.
- Unit tests for CLR directory [#34](https://github.com/saferwall/pe/pull/28).
- Unit tests for Rich header [#33](https://github.com/saferwall/pe/pull/33).

## Changed

- Do not return an error when parsing a data directory fails [#45](https://github.com/saferwall/pe/pull/45).
- Remove pointers from fields in the main `File` structure [#44](https://github.com/saferwall/pe/pull/44).

### Fixed

- Fix getting section data repeatedly thanks to [wanglei-coder](https://github.com/wanglei-coder) [#41](https://github.com/saferwall/pe/pull/41).
- Fix `adjustSectionAlignment()` thanks to [wanglei-coder](https://github.com/wanglei-coder) [#40](https://github.com/saferwall/pe/pull/40).
- Fix authentihash calculation thanks to [wanglei-coder](https://github.com/wanglei-coder) [#38](https://github.com/saferwall/pe/pull/38).
- Memory leak in `Close()` function that missed a call to `unmap()` thanks to [Mamba24L8](https://github.com/Mamba24L8).

## [1.2.0] - 2022-06-12

## Added

- Unit tests for export directory [#28](https://github.com/saferwall/pe/pull/28).
- Add a new option to allow usage of a custom logger [#24](https://github.com/saferwall/pe/pull/24).
- Unit tests for delay imports directory [#23](https://github.com/saferwall/pe/pull/23).
- Allow access to the raw certificates content [#22](https://github.com/saferwall/pe/pull/22).
- Unit tests for security directory [#19](https://github.com/saferwall/pe/pull/19).
- Unit tests for bound imports directory [#18](https://github.com/saferwall/pe/pull/18).

## Changed

- Make `GetData()` and `GetRVAFromOffset()` and `GetOffsetFromRva()` helper routines public.
- Keep parsing in exports directories even when anomalies are found [#26](https://github.com/saferwall/pe/pull/26).

## Fixed

- Incorrect check for `skipCertVerification` in security directory.
- Null pointer dereference in `GetExportFunctionByRVA()` and out of bounds when calculating `symbolAddress` in export directory [#28](https://github.com/saferwall/pe/pull/28).
- Reading unicode string from resource directory `readUnicodeStringAtRVA()` [#26](https://github.com/saferwall/pe/pull/26).
- Null pointer dereference in resource directory parsing [#25](https://github.com/saferwall/pe/pull/25).
- Imphash calculation [#17](https://github.com/saferwall/pe/pull/17) thanks to [@secDre4mer](https://github.com/secDre4mer).
- Null certificate header in security directory [#19](https://github.com/saferwall/pe/pull/19)

## [1.1.0] - 2021-12-20

### Added

- Add .editorconfig and .vscode config.
- Add github action CI workflow to test the package.
- Add few badges for the README.md to track build status, coverage and code quality.
- Introduce a new API to parse a file from a byte array.
- Parse .net metadata Module table.
- Parse .net metadata stream headers and metadata tables stream header.
- Add cmd/pedumper to illustrate how to use the library.
- Add unit test for relocation, exception, security, symbol, file, nt header, section and helper files.
- Add an option `New()` to customize max of relocations entries and COFF symbols to parse.

### Changed

- Remove uneeded break statements & lowercase error messages and anomalies.
- Make COFF entry in File struct a pointer.
- Remove unsafe pointer usage from resource directory.
- Do not return an error when COFF symbol table is not found.
- License from Apache 2 to MIT.

### Fixed

- Probe for invalid Nt Header offset.
- Fix authenticode hash calculation.
- Compile correctly on 32 bit thnkas to @Max Altgelt.
- COFF symbol table `readASCIIStringAtOffset()` out of bounds exception.
- Probe for optional header section alignment != 0.
- Fix infinite loop in exception unwind code parsing.
- Fix last data directory entry is reserved and must be zero.
- Safe ready of global pointer register

## [1.0.0] - 2021-03-04 (Initial Release)

- Works with PE32/PE32+ file fomat.
- Supports Intel x86/AMD64/ARM7ARM7 Thumb/ARM8-64/IA64/CHPE architectures.
- MS DOS header.
- Rich Header (calculate checksum).
- NT Header (file header + optional header).
- COFF symbol table and string table.
- Sections headers + entropy calculation.
- Data directories:
  - Import Table + ImpHash calculation.
  - Export Table.
  - Resource Table.
  - Exceptions Table.
  - Security Table + Authentihash calculation.
  - Relocations Table.
  - Debug Table (CODEVIEW, POGO, VC FEATURE, REPRO, FPO, EXDLL CHARACTERISTICS debug types).
  - TLS Table.
  - Load Config Directory (SEH, GFID, GIAT, Guard LongJumps, CHPE, Dynamic Value Reloc Table, Enclave Configuration, Volatile Metadata tables).
  - Bound Import Table.
  - Delay Import Table.
  - COM Table (CLR Metadata Header, Metadata Table Streams).
  - Report several anomalies.


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at report@saferwall.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Saferwall

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
<a href="https://saferwall.com" target="_blank" rel="noopener noreferrer"><img align="right" width="300" src=".github/assets/logo.png" alt="Saferwall logo"></a>

# Portable Executable Parser

[![GoDoc](http://godoc.org/github.com/saferwall/pe?status.svg)](https://pkg.go.dev/github.com/saferwall/pe) ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.15-61CFDD.svg) [![Report Card](https://goreportcard.com/badge/github.com/saferwall/pe)](https://goreportcard.com/report/github.com/saferwall/pe) [![codecov](https://codecov.io/gh/saferwall/pe/branch/main/graph/badge.svg?token=W7WTOUZLRY)](https://codecov.io/gh/saferwall/pe) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/saferwall/pe/ci.yaml?branch=main)


**pe** is a go package for parsing the [portable executable](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format) file format. This package was designed with malware analysis in mind, and being resistent to PE malformations.

## Table of content

- [Portable Executable Parser](#portable-executable-parser)
  - [Table of content](#table-of-content)
  - [Features](#features)
  - [Installing](#installing)
  - [Using the library](#using-the-library)
    - [PE Header](#pe-header)
    - [Rich Header](#rich-header)
    - [Iterating over sections](#iterating-over-sections)
  - [Roadmap](#roadmap)
  - [Fuzz Testing](#fuzz-testing)
  - [Projects Using This Library](#projects-using-this-library)
  - [References](#references)

## Features

-   Works with PE32/PE32+ file format.
-   Supports Intel x86/AMD64/ARM7ARM7 Thumb/ARM8-64/IA64/CHPE architectures.
-   MS DOS header.
-   Rich Header (calculate checksum and hash).
-   NT Header (file header + optional header).
-   COFF symbol table and string table.
-   Sections headers + entropy calculation.
-   Data directories
    -   Import Table + ImpHash calculation.
    -   Export Table
    -   Resource Table
    -   Exceptions Table
    -   Security Table + Authentihash calculation.
    -   Relocations Table
    -   Debug Table (CODEVIEW, POGO, VC FEATURE, REPRO, FPO, EXDLL CHARACTERISTICS debug types).
    -   TLS Table
    -   Load Config Directory (SEH, GFID, GIAT, Guard LongJumps, CHPE, Dynamic Value Reloc Table, Enclave Configuration, Volatile Metadata tables).
    -   Bound Import Table
    -   Delay Import Table
    -   COM Table (CLR Metadata Header, Metadata Table Streams)
-   Report several anomalies

## Installing

Using this go package is easy. First, use `go get` to install the latest version of the library. This command will install the `pedumper` executable along with the library and its dependencies:

    go get -u github.com/saferwall/pe

Next, include `pe` package in your application:

```go
import "github.com/saferwall/pe"
```

## Using the library

```go
package main

import (
	peparser "github.com/saferwall/pe"
)

func main() {
    filename := "C:\\Binaries\\notepad.exe"
    pe, err := peparser.New(filename, &peparser.Options{})
	if err != nil {
		log.Fatalf("Error while opening file: %s, reason: %v", filename, err)
    }

    err = pe.Parse()
    if err != nil {
        log.Fatalf("Error while parsing file: %s, reason: %v", filename, err)
    }
}
```

Start by instantiating a pe object by called the `New()` method, which takes the file path to the file to be parsed and some optional options.

Afterwards, a call to the `Parse()` method will give you access to all the different part of the PE format, directly accessible to be used. Here is the definition of the struct:

```go
type File struct {
	DOSHeader    ImageDOSHeader              `json:"dos_header,omitempty"`
	RichHeader   RichHeader                  `json:"rich_header,omitempty"`
	NtHeader     ImageNtHeader               `json:"nt_header,omitempty"`
	COFF         COFF                        `json:"coff,omitempty"`
	Sections     []Section                   `json:"sections,omitempty"`
	Imports      []Import                    `json:"imports,omitempty"`
	Export       Export                      `json:"export,omitempty"`
	Debugs       []DebugEntry                `json:"debugs,omitempty"`
	Relocations  []Relocation                `json:"relocations,omitempty"`
	Resources    ResourceDirectory           `json:"resources,omitempty"`
	TLS          TLSDirectory                `json:"tls,omitempty"`
	LoadConfig   LoadConfig                  `json:"load_config,omitempty"`
	Exceptions   []Exception                 `json:"exceptions,omitempty"`
	Certificates CertificateSection          `json:"certificates,omitempty"`
	DelayImports []DelayImport               `json:"delay_imports,omitempty"`
	BoundImports []BoundImportDescriptorData `json:"bound_imports,omitempty"`
	GlobalPtr    uint32                      `json:"global_ptr,omitempty"`
	CLR          CLRData                     `json:"clr,omitempty"`
	IAT          []IATEntry                  `json:"iat,omitempty"`
	Anomalies    []string                    `json:"anomalies,omitempty"`
	Header       []byte
	data         mmap.MMap
	FileInfo
	size          uint32
	OverlayOffset int64
	f             *os.File
	opts          *Options
	logger        *log.Helper
}
```

### PE Header

As mentioned before, all members of the struct are directly (no getters) accessible, additionally, the fields types has been preserved as the spec defines them, that means if you need to show the prettified version of an `int` type, you have to call the corresponding helper function.

```go
fmt.Printf("Magic is: 0x%x\n", pe.DOSHeader.Magic)
fmt.Printf("Signature is: 0x%x\n", pe.NtHeader.Signature)
fmt.Printf("Machine is: 0x%x, Meaning: %s\n", pe.NtHeader.FileHeader.Machine, pe.NtHeader.FileHeader.Machine.String())
```

Output:
```
Magic is: 0x5a4d
Signature is: 0x4550
Machine is: 0x8664, Meaning: x64
```

### Rich Header

Example:
```go
richHeader, _ := json.Marshal(pe.RichHeader)
fmt.Print(prettyPrint(richHeader))
```

Output:
```json
{
    "XorKey": 2796214951,
    "CompIDs": [
        {
            "MinorCV": 27412,
            "ProdID": 257,
            "Count": 4,
            "Unmasked": 16870164
        },
        {
            "MinorCV": 30729,
            "ProdID": 147,
            "Count": 193,
            "Unmasked": 9664521
        },
        {
            "MinorCV": 0,
            "ProdID": 1,
            "Count": 1325,
            "Unmasked": 65536
        },
        {
            "MinorCV": 27412,
            "ProdID": 260,
            "Count": 9,
            "Unmasked": 17066772
        },
        {
            "MinorCV": 27412,
            "ProdID": 259,
            "Count": 3,
            "Unmasked": 17001236
        },
        {
            "MinorCV": 27412,
            "ProdID": 256,
            "Count": 1,
            "Unmasked": 16804628
        },
        {
            "MinorCV": 27412,
            "ProdID": 269,
            "Count": 209,
            "Unmasked": 17656596
        },
        {
            "MinorCV": 27412,
            "ProdID": 255,
            "Count": 1,
            "Unmasked": 16739092
        },
        {
            "MinorCV": 27412,
            "ProdID": 258,
            "Count": 1,
            "Unmasked": 16935700
        }
    ],
    "DansOffset": 128,
    "Raw": "47vE9afaqqan2qqmp9qqprOxq6ej2qqmrqI5pmbaqqan2qumit+qprOxrqeu2qqms7Gpp6TaqqazsaqnptqqprOxp6d22qqms7FVpqbaqqazsainptqqplJpY2in2qqm"
}

```

### Iterating over sections

```go
for _, sec := range pe.Sections {
    fmt.Printf("Section Name : %s\n", sec.NameString())
    fmt.Printf("Section VirtualSize : %x\n", sec.Header.VirtualSize)
    fmt.Printf("Section Flags : %x, Meaning: %v\n\n",
        sec.Header.Characteristics, sec.PrettySectionFlags())
}
```

Output:

```
Section Name : .text
Section VirtualSize : 2ea58
Section Flags : 60500060, Meaning: [Align8Bytes Readable Align16Bytes Executable Contains Code Initialized Data Align1Bytes]

Section Name : .data
Section VirtualSize : 58
Section Flags : c0500040, Meaning: [Readable Initialized Data Writable Align1Bytes Align16Bytes Align8Bytes]

Section Name : .rdata
Section VirtualSize : 18d0
Section Flags : 40600040, Meaning: [Align2Bytes Align8Bytes Readable Initialized Data Align32Bytes]

...
```

## Roadmap

- imports MS-styled names demangling
- PE: VB5 and VB6 typical structures: project info, DLLCall-imports, referenced modules, object table

## Fuzz Testing

To validate the parser we use the [go-fuzz](https://github.com/dvyukov/go-fuzz) and a corpus of known malformed and tricky PE files from [corkami](https://github.com/corkami/pocs/tree/master/PE).

## Projects Using This Library

  <a href="https://www.fibratus.io" >
    <img src="https://github.com/rabbitstack/fibratus/raw/master/logo.png" alt="Fibratus" width="50px">
  </a>

[Fibratus](https://github.com/rabbitstack/fibratus) A modern tool for Windows kernel exploration and tracing with a focus on security.

## References

- [Peering Inside the PE: A Tour of the Win32 Portable Executable File Format by Matt Pietrek](http://bytepointer.com/resources/pietrek_peering_inside_pe.htm)
- [An In-Depth Look into the Win32 Portable Executable File Format - Part 1 by Matt Pietrek](http://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part1)
- [An In-Depth Look into the Win32 Portable Executable File Format - Part 2 by Matt Pietrek](http://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part2)
- [Portable Executable File Format](https://blog.kowalczyk.info/articles/pefileformat.html)
- [PE Format MSDN spec](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format)
- [DotNET format](https://www.ntcore.com/files/dotnetformat.htm)
- [BlackHat 2011 - CONSTANT INSECURITY: (PECOFF) Portable Executable FIle Format](https://www.youtube.com/watch?v=uoQL3CE24ls)


================================================
FILE: anomaly.go
================================================
// Copyright 2021 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
	"time"
)

// Anomalies found in a PE
var (

	// AnoPEHeaderOverlapDOSHeader is reported when the PE headers overlaps with the DOS header.
	AnoPEHeaderOverlapDOSHeader = "PE header overlaps with DOS header"

	// AnoPETimeStampNull is reported when the file header timestamp is 0.
	AnoPETimeStampNull = "file header timestamp set to 0"

	// AnoPETimeStampFuture is reported when the file header timestamp is more
	// than one day ahead of the current date timestamp.
	AnoPETimeStampFuture = "file header timestamp set to 0"

	// NumberOfSections is reported when number of sections is larger or equal than 10.
	AnoNumberOfSections10Plus = "number of sections is 10+"

	// AnoNumberOfSectionsNull is reported when sections count's is 0.
	AnoNumberOfSectionsNull = "number of sections is 0"

	// AnoSizeOfOptionalHeaderNull is reported when size of optional header is 0.
	AnoSizeOfOptionalHeaderNull = "size of optional header is 0"

	// AnoUncommonSizeOfOptionalHeader32 is reported when size of optional
	// header for PE32 is larger than 0xE0.
	AnoUncommonSizeOfOptionalHeader32 = "size of optional header is larger than 0xE0 (PE32)"

	// AnoUncommonSizeOfOptionalHeader64 is reported when size of optional
	// header for PE32+ is larger than 0xF0.
	AnoUncommonSizeOfOptionalHeader64 = "size of optional header is larger than 0xF0 (PE32+)"

	// AnoAddressOfEntryPointNull is reported when address of entry point is 0.
	AnoAddressOfEntryPointNull = "address of entry point is 0"

	// AnoAddressOfEPLessSizeOfHeaders is reported when address of entry point
	// is smaller than size of headers, the file cannot run under Windows.
	AnoAddressOfEPLessSizeOfHeaders = "address of entry point is smaller than size of headers, " +
		"the file cannot run under Windows 8"

	// AnoImageBaseNull is reported when the image base is null.
	AnoImageBaseNull = "image base is 0"

	// AnoDanSMagicOffset is reported when the `DanS` magic offset is different than 0x80.
	AnoDanSMagicOffset = "`DanS` magic offset is different than 0x80"

	// ErrInvalidFileAlignment is reported when file alignment is larger than
	//  0x200 and not a power of 2.
	ErrInvalidFileAlignment = "FileAlignment larger than 0x200 and not a power of 2"

	// ErrInvalidSectionAlignment is reported when file alignment is lesser
	// than 0x200 and different from section alignment.
	ErrInvalidSectionAlignment = "FileAlignment lesser than 0x200 and different from section alignment"

	// AnoMajorSubsystemVersion is reported when MajorSubsystemVersion has a
	// value different than the standard 3 --> 6.
	AnoMajorSubsystemVersion = "MajorSubsystemVersion is outside 3<-->6 boundary"

	// AnonWin32VersionValue is reported when Win32VersionValue is different than 0
	AnonWin32VersionValue = "Win32VersionValue is a reserved field, must be set to zero"

	// AnoInvalidPEChecksum is reported when the optional header checksum field
	// is different from what it should normally be.
	AnoInvalidPEChecksum = "optional header checksum is invalid"

	// AnoNumberOfRvaAndSizes is reported when NumberOfRvaAndSizes is different than 16.
	AnoNumberOfRvaAndSizes = "optional header NumberOfRvaAndSizes != 16"

	// AnoReservedDataDirectoryEntry is reported when the last data directory entry is not zero.
	AnoReservedDataDirectoryEntry = "last data directory entry is a reserved field, must be set to zero"

	// AnoCOFFSymbolsCount is reported when the number of COFF symbols is absurdly high.
	AnoCOFFSymbolsCount = "COFF symbols count is absurdly high"

	// AnoRelocationEntriesCount is reported when the number of relocation entries is absurdly high.
	AnoRelocationEntriesCount = "relocation entries count is absurdly high"
)

// GetAnomalies reportes anomalies found in a PE binary.
// These nomalies does prevent the Windows loader from loading the files but
// is an interesting features for malware analysis.
func (pe *File) GetAnomalies() error {

	// ******************** Anomalies in File header ************************
	// An application for Windows NT typically has the nine predefined sections
	// named: .text, .bss, .rdata, .data, .rsrc, .edata, .idata, .pdata, and
	// .debug. Some applications do not need all of these sections, while
	// others may define still more sections to suit their specific needs.
	// NumberOfSections can be up to 96 under XP.
	// NumberOfSections can be up to 65535 under Vista and later.
	if pe.NtHeader.FileHeader.NumberOfSections >= 10 {
		pe.Anomalies = append(pe.Anomalies, AnoNumberOfSections10Plus)
	}

	// File header timestamp set to 0.
	if pe.NtHeader.FileHeader.TimeDateStamp == 0 {
		pe.Anomalies = append(pe.Anomalies, AnoPETimeStampNull)
	}

	// File header timestamp set to the future.
	now := time.Now()
	future := uint32(now.Add(24 * time.Hour).Unix())
	if pe.NtHeader.FileHeader.TimeDateStamp > future {
		pe.Anomalies = append(pe.Anomalies, AnoPETimeStampFuture)
	}

	// NumberOfSections can be null with low alignment PEs
	// and in this case, the values are just checked but not really used (under XP)
	if pe.NtHeader.FileHeader.NumberOfSections == 0 {
		pe.Anomalies = append(pe.Anomalies, AnoNumberOfSectionsNull)
	}

	// SizeOfOptionalHeader is not the size of the optional header, but the delta
	// between the top of the Optional header and the start of the section table.
	// Thus, it can be null (the section table will overlap the Optional Header,
	// or can be null when no sections are present)
	if pe.NtHeader.FileHeader.SizeOfOptionalHeader == 0 {
		pe.Anomalies = append(pe.Anomalies, AnoSizeOfOptionalHeaderNull)
	}

	// SizeOfOptionalHeader can be bigger than the file
	// (the section table will be in virtual space, full of zeroes), but can't be negative.
	// Do some check here.
	oh32 := ImageOptionalHeader32{}
	oh64 := ImageOptionalHeader64{}

	// SizeOfOptionalHeader standard value is 0xE0 for PE32.
	if pe.Is32 &&
		pe.NtHeader.FileHeader.SizeOfOptionalHeader > uint16(binary.Size(oh32)) {
		pe.Anomalies = append(pe.Anomalies, AnoUncommonSizeOfOptionalHeader32)
	}

	// SizeOfOptionalHeader standard value is 0xF0 for PE32+.
	if pe.Is64 &&
		pe.NtHeader.FileHeader.SizeOfOptionalHeader > uint16(binary.Size(oh64)) {
		pe.Anomalies = append(pe.Anomalies, AnoUncommonSizeOfOptionalHeader64)
	}

	// ***************** Anomalies in Optional header *********************
	// Under Windows 8, AddressOfEntryPoint is not allowed to be smaller than
	// SizeOfHeaders, except if it's null.
	switch pe.Is64 {
	case true:
		oh64 = pe.NtHeader.OptionalHeader.(ImageOptionalHeader64)
	case false:
		oh32 = pe.NtHeader.OptionalHeader.(ImageOptionalHeader32)
	}

	// Use oh for fields which are common for both structures.
	oh := oh32
	if oh.AddressOfEntryPoint != 0 && oh.AddressOfEntryPoint < oh.SizeOfHeaders {
		pe.Anomalies = append(pe.Anomalies, AnoAddressOfEPLessSizeOfHeaders)
	}

	// AddressOfEntryPoint can be null in DLLs: in this case,
	// DllMain is just not called. can be null
	if oh.AddressOfEntryPoint == 0 {
		pe.Anomalies = append(pe.Anomalies, AnoAddressOfEntryPointNull)
	}

	// ImageBase can be null, under XP.
	// In this case, the binary will be relocated to 10000h
	if (pe.Is64 && oh64.ImageBase == 0) ||
		(pe.Is32 && oh32.ImageBase == 0) {
		pe.Anomalies = append(pe.Anomalies, AnoImageBaseNull)
	}

	// The msdn states that SizeOfImage must be a multiple of the section
	// alignment. This is not a requirement though. Adding it as anomaly.
	// Todo: raise an anomaly when SectionAlignment is NULL ?
	if oh.SectionAlignment != 0 && oh.SizeOfImage%oh.SectionAlignment != 0 {
		pe.Anomalies = append(pe.Anomalies, AnoInvalidSizeOfImage)
	}

	// For DLLs, MajorSubsystemVersion is ignored until Windows 8. It can have
	// any value. Under Windows 8, it needs a standard value (3.10 < 6.30).
	if oh.MajorSubsystemVersion < 3 || oh.MajorSubsystemVersion > 6 {
		pe.Anomalies = append(pe.Anomalies, AnoMajorSubsystemVersion)
	}

	// Win32VersionValue officially defined as `reserved` and should be null
	// if non null, it overrides MajorVersion/MinorVersion/BuildNumber/PlatformId
	// OperatingSystem Versions values located in the PEB, after loading.
	if oh.Win32VersionValue != 0 {
		pe.Anomalies = append(pe.Anomalies, AnonWin32VersionValue)
	}

	// Checksums are required for kernel-mode drivers and some system DLLs.
	// Otherwise, this field can be 0.
	if pe.Checksum() != oh.CheckSum && oh.CheckSum != 0 {
		pe.Anomalies = append(pe.Anomalies, AnoInvalidPEChecksum)
	}

	// This field contains the number of IMAGE_DATA_DIRECTORY entries.
	//  This field has been 16 since the earliest releases of Windows NT.
	if (pe.Is64 && oh64.NumberOfRvaAndSizes == 0xA) ||
		(pe.Is32 && oh32.NumberOfRvaAndSizes == 0xA) {
		pe.Anomalies = append(pe.Anomalies, AnoNumberOfRvaAndSizes)
	}

	return nil
}

// addAnomaly appends the given anomaly to the list of anomalies.
func (pe *File) addAnomaly(anomaly string) {
	if !stringInSlice(anomaly, pe.Anomalies) {
		pe.Anomalies = append(pe.Anomalies, anomaly)
	}
}


================================================
FILE: anomaly_test.go
================================================
// Copyright 2021 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"testing"
)

func TestGetAnomalies(t *testing.T) {

	tests := []struct {
		in      string
		out []string
	}{
		{
			getAbsoluteFilePath(
			"test/050708404553416d103652a7ca1f887ab81f533a019a0eeff0e6bb460a202cde"),
			[]string{AnoReservedDataDirectoryEntry},
		},
		{
			getAbsoluteFilePath(
			"test/0585495341e0ffaae1734acb78708ff55cd3612d844672d37226ef63d12652d0"),
			[]string{AnoAddressOfEntryPointNull, AnoMajorSubsystemVersion},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in, func(t *testing.T) {
			file, err := New(tt.in, &Options{})
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
			}
			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
			}

			err = file.GetAnomalies()
			if err != nil {
				t.Fatalf("GetAnomalies(%s) failed, reason: %v", tt.in, err)
			}

			for _, ano := range tt.out {
				if !stringInSlice(ano, file.Anomalies) {
					t.Errorf("anomaly(%s) not found in anomalies, got: %v", ano, file.Anomalies)
				}
			}

		})
	}
}


================================================
FILE: arch.go
================================================
// Copyright 2022 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

// Architecture-specific data. This data directory is not used
// (set to all zeros) for I386, IA64, or AMD64 architecture.
func (pe *File) parseArchitectureDirectory(rva, size uint32) error {
	return nil
}


================================================
FILE: boundimports.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
)

const (
	// MaxStringLength represents the maximum length of a string to be retrieved
	// from the file. It's there to prevent loading massive amounts of data from
	// memory mapped files. Strings longer than 0x100B should be rather rare.
	MaxStringLength = uint32(0x100)
)

// ImageBoundImportDescriptor represents the IMAGE_BOUND_IMPORT_DESCRIPTOR.
type ImageBoundImportDescriptor struct {
	// TimeDateStamp is just the value from the Exports information of the DLL
	// which is being imported from.
	TimeDateStamp uint32 `json:"time_date_stamp"`
	// Offset of the DLL name counted from the beginning of the BOUND_IMPORT table.
	OffsetModuleName uint16 `json:"offset_module_name"`
	// Number of forwards,
	NumberOfModuleForwarderRefs uint16 `json:"number_of_module_forwarder_refs"`
	// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows.
}

// ImageBoundForwardedRef represents the IMAGE_BOUND_FORWARDER_REF.
type ImageBoundForwardedRef struct {
	TimeDateStamp    uint32 `json:"time_date_stamp"`
	OffsetModuleName uint16 `json:"offset_module_name"`
	Reserved         uint16 `json:"reserved"`
}

// BoundImportDescriptorData represents the descriptor in addition to forwarded refs.
type BoundImportDescriptorData struct {
	Struct        ImageBoundImportDescriptor `json:"struct"`
	Name          string                     `json:"name"`
	ForwardedRefs []BoundForwardedRefData    `json:"forwarded_refs"`
}

// BoundForwardedRefData represents the struct in addition to the dll name.
type BoundForwardedRefData struct {
	Struct ImageBoundForwardedRef `json:"struct"`
	Name   string                 `json:"name"`
}

// This table is an array of bound import descriptors, each of which describes
// a DLL this image was bound up with at the time of the image creation.
// The descriptors also carry the time stamps of the bindings, and if the
// bindings are up-to-date, the OS loader uses these bindings as a “shortcut”
// for API import. Otherwise, the loader ignores the bindings and resolves the
// imported APIs through the Import tables.
func (pe *File) parseBoundImportDirectory(rva, size uint32) (err error) {
	var sectionsAfterOffset []uint32
	var safetyBoundary uint32
	var start = rva

	for {
		bndDesc := ImageBoundImportDescriptor{}
		bndDescSize := uint32(binary.Size(bndDesc))
		err = pe.structUnpack(&bndDesc, rva, bndDescSize)
		// If the RVA is invalid all would blow up. Some EXEs seem to be
		// specially nasty and have an invalid RVA.
		if err != nil {
			return err
		}

		// If the structure is all zeros, we reached the end of the list.
		if bndDesc == (ImageBoundImportDescriptor{}) {
			break
		}

		rva += bndDescSize
		sectionsAfterOffset = nil

		fileOffset := pe.GetOffsetFromRva(rva)
		section := pe.getSectionByRva(rva)
		if section == nil {
			safetyBoundary = pe.size - fileOffset
			for _, section := range pe.Sections {
				if section.Header.PointerToRawData > fileOffset {
					sectionsAfterOffset = append(
						sectionsAfterOffset, section.Header.PointerToRawData)
				}
			}
			if len(sectionsAfterOffset) > 0 {
				// Find the first section starting at a later offset than that
				// specified by 'rva'
				firstSectionAfterOffset := Min(sectionsAfterOffset)
				section = pe.getSectionByOffset(firstSectionAfterOffset)
				if section != nil {
					safetyBoundary = section.Header.PointerToRawData - fileOffset
				}
			}
		} else {
			sectionLen := uint32(len(section.Data(0, 0, pe)))
			safetyBoundary = (section.Header.PointerToRawData + sectionLen) - fileOffset
		}

		if section == nil {
			pe.logger.Warnf("RVA of IMAGE_BOUND_IMPORT_DESCRIPTOR points to an invalid address: 0x%x", rva)
			return nil
		}

		bndFrwdRef := ImageBoundForwardedRef{}
		bndFrwdRefSize := uint32(binary.Size(bndFrwdRef))
		count := min(uint32(bndDesc.NumberOfModuleForwarderRefs), safetyBoundary/bndFrwdRefSize)

		forwarderRefs := make([]BoundForwardedRefData, 0)
		for i := uint32(0); i < count; i++ {
			err = pe.structUnpack(&bndFrwdRef, rva, bndFrwdRefSize)
			if err != nil {
				return err
			}

			rva += bndFrwdRefSize

			offset := start + uint32(bndFrwdRef.OffsetModuleName)
			DllNameBuff := string(pe.GetStringFromData(0, pe.data[offset:offset+MaxStringLength]))
			DllName := string(DllNameBuff)

			// OffsetModuleName points to a DLL name. These shouldn't be too long.
			// Anything longer than a safety length of 128 will be taken to indicate
			// a corrupt entry and abort the processing of these entries.
			// Names shorter than 4 characters will be taken as invalid as well.
			if DllName != "" && (len(DllName) > 256 || !IsPrintable(DllName)) {
				break
			}

			forwarderRefs = append(forwarderRefs, BoundForwardedRefData{
				Struct: bndFrwdRef, Name: DllName})
		}

		offset := start + uint32(bndDesc.OffsetModuleName)
		DllNameBuff := pe.GetStringFromData(0, pe.data[offset:offset+MaxStringLength])
		DllName := string(DllNameBuff)
		if DllName != "" && (len(DllName) > 256 || !IsPrintable(DllName)) {
			break
		}

		pe.BoundImports = append(pe.BoundImports, BoundImportDescriptorData{
			Struct:        bndDesc,
			Name:          DllName,
			ForwardedRefs: forwarderRefs})
	}

	if len(pe.BoundImports) > 0 {
		pe.HasBoundImp = true
	}
	return nil
}


================================================
FILE: boundimports_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"reflect"
	"testing"
)

type TestBoundImportEntry struct {
	entryCount     int
	entryIndex     int
	entry          BoundImportDescriptorData
	errOutOfBounds error
}

func TestBoundImportDirectory(t *testing.T) {

	tests := []struct {
		in  string
		out TestBoundImportEntry
	}{
		{
			getAbsoluteFilePath("test/mfc40u.dll"),
			TestBoundImportEntry{
				entryCount: 4,
				entryIndex: 0,
				entry: BoundImportDescriptorData{
					Struct: ImageBoundImportDescriptor{
						TimeDateStamp:               0x31CB50F3,
						OffsetModuleName:            0x38,
						NumberOfModuleForwarderRefs: 0x1,
					},
					Name: "MSVCRT40.dll",
					ForwardedRefs: []BoundForwardedRefData{
						{
							Struct: ImageBoundForwardedRef{
								TimeDateStamp:    0x3B7DFE0E,
								OffsetModuleName: 0x45,
								Reserved:         0x0,
							},
							Name: "msvcrt.DLL",
						},
					},
				},
				errOutOfBounds: nil,
			},
		},
		{
			// fake bound imports directory
			getAbsoluteFilePath("test/0044e1870806c048a7558082d4482d1650dcd3ea73152ed2218a554983130721"),
			TestBoundImportEntry{
				errOutOfBounds: ErrOutsideBoundary,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryBoundImport]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryBoundImport]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseBoundImportDirectory(va, size)
			if err != tt.out.errOutOfBounds {
				t.Fatalf("parseBoundImportDirectory(%s) failed, reason: %v", tt.in, err)
			}
			got := file.BoundImports
			if len(got) != tt.out.entryCount {
				t.Errorf("bound imports entry count assertion failed, got %v, want %v", len(got), tt.out.entryCount)
			}

			if len(file.BoundImports) > 0 {
				boundImportEntry := file.BoundImports[tt.out.entryIndex]
				if !reflect.DeepEqual(boundImportEntry, tt.out.entry) {
					t.Errorf("bound import entry assertion failed, got %v, want %v", boundImportEntry, tt.out.entry)
				}
			}
		})
	}
}


================================================
FILE: cmd/dump.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
	"text/tabwriter"
	"time"
	"unicode"
	"unsafe"

	peparser "github.com/saferwall/pe"
	"github.com/saferwall/pe/log"
)

var (
	wg   sync.WaitGroup
	jobs chan string = make(chan string)
)

func loopFilesWorker(cfg config) error {
	for path := range jobs {
		files, err := os.ReadDir(path)
		if err != nil {
			wg.Done()
			return err
		}

		for _, file := range files {
			if !file.IsDir() {
				fullpath := filepath.Join(path, file.Name())
				parsePE(fullpath, cfg)
			}
		}
		wg.Done()
	}
	return nil
}

func LoopDirsFiles(path string) error {
	files, err := os.ReadDir(path)
	if err != nil {
		return err
	}

	go func() {
		wg.Add(1)
		jobs <- path
	}()
	for _, file := range files {
		if file.IsDir() {
			LoopDirsFiles(filepath.Join(path, file.Name()))
		}
	}
	return nil
}

func prettyPrint(iface interface{}) string {
	var prettyJSON bytes.Buffer
	buff, _ := json.Marshal(iface)
	err := json.Indent(&prettyJSON, buff, "", "\t")
	if err != nil {
		log.Errorf("JSON parse error: %v", err)
		return string(buff)
	}

	return prettyJSON.String()
}

func humanizeTimestamp(ts uint32) string {
	unixTimeUTC := time.Unix(int64(ts), 0)
	return unixTimeUTC.String()
}

func hexDump(b []byte) {
	var a [16]byte
	n := (len(b) + 15) &^ 15
	for i := 0; i < n; i++ {
		if i%16 == 0 {
			fmt.Printf("%4d", i)
		}
		if i%8 == 0 {
			fmt.Print(" ")
		}
		if i < len(b) {
			fmt.Printf(" %02X", b[i])
		} else {
			fmt.Print("   ")
		}
		if i >= len(b) {
			a[i%16] = ' '
		} else if b[i] < 32 || b[i] > 126 {
			a[i%16] = '.'
		} else {
			a[i%16] = b[i]
		}
		if i%16 == 15 {
			fmt.Printf("  %s\n", string(a[:]))
		}
	}
}

func hexDumpSize(b []byte, size int) {
	var a [16]byte

	// Append null bytes when length of the buffer
	// is smaller than the requested size.
	if len(b) < size {
		temp := make([]byte, size)
		copy(temp, b)
		b = temp
	}

	n := (size + 15) &^ 15
	for i := 0; i < n; i++ {
		if i%16 == 0 {
			fmt.Printf("%4d", i)
		}
		if i%8 == 0 {
			fmt.Print(" ")
		}
		if i < len(b) {
			fmt.Printf(" %02X", b[i])
		} else {
			fmt.Print("   ")
		}
		if i >= len(b) {
			a[i%16] = ' '
		} else if b[i] < 32 || b[i] > 126 {
			a[i%16] = '.'
		} else {
			a[i%16] = b[i]
		}
		if i%16 == 15 {
			fmt.Printf("  %s\n", string(a[:]))
		}
	}
}

func IntToByteArray(num uint64) []byte {
	size := int(unsafe.Sizeof(num))
	arr := make([]byte, size)
	for i := 0; i < size; i++ {
		byt := *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&num)) + uintptr(i)))
		arr[i] = byt
	}
	return arr
}

func sentenceCase(s string) string {
	newString := string(s[0])
	for i, r := range s[1:] {
		if unicode.IsLower(r) && unicode.IsLetter(r) {
			newString += string(r)
		} else {
			if i < len(s)-2 {
				nextChar := rune(s[i+2])
				previousChar := rune(s[i])
				if unicode.IsLower(previousChar) && unicode.IsLetter(previousChar) {
					newString += " " + string(r)
				} else {
					if unicode.IsLower(nextChar) && unicode.IsLetter(nextChar) {
						newString += " " + string(r)
					} else {
						newString += string(r)
					}
				}
			}
		}
	}

	return newString
}

func isDirectory(path string) bool {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

func parse(filePath string, cfg config) {

	// filePath points to a file.
	if !isDirectory(filePath) {
		parsePE(filePath, cfg)

	} else {
		// filePath points to a directory,
		// walk recursively through all files.
		fileList := []string{}
		filepath.Walk(filePath, func(path string, f os.FileInfo, err error) error {
			if !isDirectory(path) {
				fileList = append(fileList, path)
			}
			return nil
		})

		for _, file := range fileList {
			parsePE(file, cfg)
		}
	}
}

func parsePE(filename string, cfg config) {

	logger := log.NewStdLogger(os.Stdout)
	logger = log.NewFilter(logger, log.FilterLevel(log.LevelInfo))
	log := log.NewHelper(logger)

	log.Infof("parsing filename %s", filename)

	data, _ := os.ReadFile(filename)
	pe, err := peparser.NewBytes(data, &peparser.Options{
		Logger:                logger,
		DisableCertValidation: false,
		Fast:                  false,
	})

	if err != nil {
		log.Infof("Error while opening file: %s, reason: %s", filename, err)
		return
	}
	defer pe.Close()

	err = pe.Parse()
	if err != nil {
		if err != peparser.ErrDOSMagicNotFound {
			log.Infof("Error while parsing file: %s, reason: %s", filename, err)
		}
		return
	}

	// Dump all results to disk in JSON format.
	// f, err := os.Create("out.json")
	// if err != nil {
	// 	return
	// }
	// defer f.Close()
	// f.WriteString(prettyPrint(pe))

	if cfg.wantDOSHeader {
		DOSHeader := pe.DOSHeader
		magic := string(IntToByteArray(uint64(DOSHeader.Magic)))
		signature := string(IntToByteArray(uint64(pe.NtHeader.Signature)))
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		fmt.Print("\n\t------[ DOS Header ]------\n\n")
		fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", DOSHeader.Magic, magic)
		fmt.Fprintf(w, "Bytes On Last Page Of File:\t 0x%x\n", DOSHeader.BytesOnLastPageOfFile)
		fmt.Fprintf(w, "Pages In File:\t 0x%x\n", DOSHeader.PagesInFile)
		fmt.Fprintf(w, "Relocations:\t 0x%x\n", DOSHeader.Relocations)
		fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", DOSHeader.SizeOfHeader)
		fmt.Fprintf(w, "Min Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MinExtraParagraphsNeeded)
		fmt.Fprintf(w, "Max Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MaxExtraParagraphsNeeded)
		fmt.Fprintf(w, "Initial SS:\t 0x%x\n", DOSHeader.InitialSS)
		fmt.Fprintf(w, "Initial SP:\t 0x%x\n", DOSHeader.InitialSP)
		fmt.Fprintf(w, "Checksum:\t 0x%x\n", DOSHeader.Checksum)
		fmt.Fprintf(w, "Initial IP:\t 0x%x\n", DOSHeader.InitialIP)
		fmt.Fprintf(w, "Initial CS:\t 0x%x\n", DOSHeader.InitialCS)
		fmt.Fprintf(w, "Address Of Relocation Table:\t 0x%x\n", DOSHeader.AddressOfRelocationTable)
		fmt.Fprintf(w, "Overlay Number:\t 0x%x\n", DOSHeader.OverlayNumber)
		fmt.Fprintf(w, "OEM Identifier:\t 0x%x\n", DOSHeader.OEMIdentifier)
		fmt.Fprintf(w, "OEM Information:\t 0x%x\n", DOSHeader.OEMInformation)
		fmt.Fprintf(w, "Address Of New EXE Header:\t 0x%x (%s)\n", DOSHeader.AddressOfNewEXEHeader, signature)
		w.Flush()
	}

	if cfg.wantRichHeader && pe.FileInfo.HasRichHdr {
		richHeader := pe.RichHeader
		fmt.Printf("\nRICH HEADER\n***********\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		fmt.Fprintf(w, "\t0x%x\t XOR Key\n", richHeader.XORKey)
		fmt.Fprintf(w, "\t0x%x\t DanS offset\n", richHeader.DansOffset)
		fmt.Fprintf(w, "\t0x%x\t Checksum\n\n", pe.RichHeaderChecksum())
		fmt.Fprintln(w, "ProductID\tMinorCV\tCount\tUnmasked\tMeaning\tVSVersion\t")
		for _, compID := range pe.RichHeader.CompIDs {
			fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t0x%x\t%s\t%s\t\n",
				compID.ProdID, compID.MinorCV, compID.Count, compID.Unmasked,
				peparser.ProdIDtoStr(compID.ProdID), peparser.ProdIDtoVSversion(compID.ProdID))
		}
		w.Flush()
		fmt.Print("\n   ---Raw header dump---\n")
		hexDump(richHeader.Raw)
	}

	if cfg.wantNTHeader {
		ntHeader := pe.NtHeader.FileHeader
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		characteristics := strings.Join(ntHeader.Characteristics.String(), " | ")

		fmt.Print("\n\t------[ File Header ]------\n\n")
		fmt.Fprintf(w, "Machine:\t 0x%x (%s)\n", int(ntHeader.Machine), ntHeader.Machine.String())
		fmt.Fprintf(w, "Number Of Sections:\t 0x%x\n", ntHeader.NumberOfSections)
		fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", ntHeader.TimeDateStamp, humanizeTimestamp(ntHeader.TimeDateStamp))
		fmt.Fprintf(w, "Pointer To Symbol Table:\t 0x%x\n", ntHeader.PointerToSymbolTable)
		fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols)
		fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols)
		fmt.Fprintf(w, "Size Of Optional Header:\t 0x%x\n", ntHeader.SizeOfOptionalHeader)
		fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", ntHeader.Characteristics, characteristics)
		w.Flush()

		fmt.Print("\n\t------[ Optional Header ]------\n\n")
		if pe.Is64 {
			oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader64)
			dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ")
			fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic())
			fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion)
			fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion)
			fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode)))
			fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData,
				BytesSize(float64(oh.SizeOfInitializedData)))
			fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData,
				BytesSize(float64(oh.SizeOfUninitializedData)))
			fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint)
			fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode)
			fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase)
			fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment,
				BytesSize(float64(oh.SectionAlignment)))
			fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment,
				BytesSize(float64(oh.FileAlignment)))
			fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion)
			fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion)
			fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion)
			fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion)
			fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion)
			fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion)
			fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue)
			fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage)))
			fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders)))
			fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum)
			fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String())
			fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics)
			fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve)))
			fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit)))
			fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve)))
			fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit)))
			fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags)
			fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes)
			fmt.Fprintf(w, "\n")
			for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ {
				rva := oh.DataDirectory[entry].VirtualAddress
				size := oh.DataDirectory[entry].Size
				fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size)
			}
		} else {
			oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader32)
			dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ")
			fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic())
			fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion)
			fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion)
			fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode)))
			fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData,
				BytesSize(float64(oh.SizeOfInitializedData)))
			fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData,
				BytesSize(float64(oh.SizeOfUninitializedData)))
			fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint)
			fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode)
			fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase)
			fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment,
				BytesSize(float64(oh.SectionAlignment)))
			fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment,
				BytesSize(float64(oh.FileAlignment)))
			fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion)
			fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion)
			fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion)
			fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion)
			fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion)
			fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion)
			fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue)
			fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage)))
			fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders)))
			fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum)
			fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String())
			fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics)
			fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve)))
			fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit)))
			fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve)))
			fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit)))
			fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags)
			fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes)
			fmt.Fprintf(w, "\n")
			for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ {
				rva := oh.DataDirectory[entry].VirtualAddress
				size := oh.DataDirectory[entry].Size
				fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size)
			}
		}
		w.Flush()
	}

	if cfg.wantCOFF && pe.FileInfo.HasCOFF {
		fmt.Printf("\nCOFF\n****\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		fmt.Fprintln(w, "Name\tValue\tSectionNumber\tType\tStorageClass\tNumberOfAuxSymbols\t")
		for _, sym := range pe.COFF.SymbolTable {
			symName, _ := sym.String(pe)
			fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
				symName, sym.Value, sym.SectionNumber,
				sym.Type, sym.StorageClass, sym.NumberOfAuxSymbols)
		}
		w.Flush()
	}

	if cfg.wantSections && pe.FileInfo.HasSections {
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		for i, sec := range pe.Sections {
			hdr := sec.Header
			fmt.Printf("\n\t------[ Section Header #%d ]------\n\n", i)
			fmt.Fprintf(w, "Name:\t %v (%s)\n", hdr.Name, sec.String())
			fmt.Fprintf(w, "Virtual Size:\t 0x%x (%s)\n", hdr.VirtualSize,
				BytesSize(float64(hdr.VirtualSize)))
			fmt.Fprintf(w, "Virtual Address:\t 0x%x\n", hdr.VirtualAddress)
			fmt.Fprintf(w, "Size Of Raw Data Size:\t 0x%x (%s)\n", hdr.SizeOfRawData,
				BytesSize(float64(hdr.SizeOfRawData)))
			fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", hdr.PointerToRawData)
			fmt.Fprintf(w, "Pointer To Relocations:\t 0x%x\n", hdr.PointerToRelocations)
			fmt.Fprintf(w, "Pointer To Line Numbers:\t 0x%x\n", hdr.PointerToLineNumbers)
			fmt.Fprintf(w, "Number Of Relocations:\t 0x%x\n", hdr.NumberOfRelocations)
			fmt.Fprintf(w, "Number Of Line Numbers:\t 0x%x\n", hdr.NumberOfLineNumbers)
			fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", hdr.Characteristics,
				strings.Join(sec.PrettySectionFlags(), " | "))
			fmt.Fprintf(w, "Entropy:\t %f\n", sec.CalculateEntropy(pe))
			w.Flush()

			fmt.Fprintf(w, "\n")
			hexDumpSize(sec.Data(0, hdr.PointerToRawData, pe), 128)
		}
	}

	if cfg.wantImport && pe.FileInfo.HasImport {
		fmt.Printf("\nIMPORTS\n********\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		for _, imp := range pe.Imports {
			desc := imp.Descriptor
			fmt.Printf("\n\t------[ %s ]------\n\n", imp.Name)
			fmt.Fprintf(w, "Name:\t 0x%x\n", desc.Name)
			fmt.Fprintf(w, "Original First Thunk:\t 0x%x\n", desc.OriginalFirstThunk)
			fmt.Fprintf(w, "First Thunk:\t 0x%x\n", desc.FirstThunk)
			fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s\n", desc.TimeDateStamp,
				humanizeTimestamp(desc.TimeDateStamp))
			fmt.Fprintf(w, "Forwarder Chain:\t 0x%x\n", desc.ForwarderChain)
			fmt.Fprintf(w, "\n")
			fmt.Fprintln(w, "Name\tThunkRVA\tThunkValue\tOriginalThunkRVA\tOriginalThunkValue\tHint\t")
			for _, impFunc := range imp.Functions {
				fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
					impFunc.Name, impFunc.ThunkRVA, impFunc.ThunkValue,
					impFunc.OriginalThunkRVA, impFunc.OriginalThunkValue, impFunc.Hint)
			}
			w.Flush()

		}
	}

	if cfg.wantExport && pe.FileInfo.HasExport {
		fmt.Printf("\nEXPORTS\n********\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)

		expDir := pe.Export.Struct
		fmt.Printf("\n\t------[ %s ]------\n\n", pe.Export.Name)
		fmt.Fprintf(w, "Characteristics:\t 0x%x\n", expDir.Characteristics)
		fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s\n", expDir.TimeDateStamp,
			humanizeTimestamp(expDir.TimeDateStamp))
		fmt.Fprintf(w, "Major Version:\t 0x%x\n", expDir.MajorVersion)
		fmt.Fprintf(w, "Minor Version:\t 0x%x\n", expDir.MinorVersion)
		fmt.Fprintf(w, "Name:\t 0x%x\n", expDir.Name)
		fmt.Fprintf(w, "Base:\t 0x%x\n", expDir.Base)
		fmt.Fprintf(w, "Number Of Functions:\t 0x%x\n", expDir.NumberOfFunctions)
		fmt.Fprintf(w, "Number Of Names:\t 0x%x\n", expDir.NumberOfNames)
		fmt.Fprintf(w, "Address Of Functions:\t 0x%x\n", expDir.AddressOfFunctions)
		fmt.Fprintf(w, "Address Of Names:\t 0x%x\n", expDir.AddressOfNames)
		fmt.Fprintf(w, "Address Of Name Ordinals:\t 0x%x\n", expDir.AddressOfNameOrdinals)
		fmt.Fprintf(w, "\n")

		fmt.Fprintln(w, "Name\tOrdinal\tNameRVA\tFunctionRVA\tForwardedTo\t")
		for _, exp := range pe.Export.Functions {
			fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t%s\t\n",
				exp.Name, exp.Ordinal, exp.NameRVA, exp.FunctionRVA, exp.ForwarderRVA, exp.Forwarder)
		}
		w.Flush()
	}

	if cfg.wantResource && pe.FileInfo.HasResource {
		var printRsrcDir func(rsrcDir peparser.ResourceDirectory)
		padding := 0

		printRsrcDataEntry := func(entry peparser.ResourceDataEntry) {
			padding++
			w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
			imgRsrcDataEntry := entry.Struct
			fmt.Fprintf(w, "\n\t\u27A1 Resource Data Entry\n\t")
			fmt.Fprintf(w, "|- Offset To Data: 0x%x\n\t", imgRsrcDataEntry.OffsetToData)
			fmt.Fprintf(w, "|- Size: 0x%x\n\t", imgRsrcDataEntry.Size)
			fmt.Fprintf(w, "|- Code Page: 0x%x\n\t", imgRsrcDataEntry.CodePage)
			fmt.Fprintf(w, "|- Reserved: 0x%x\n\t", imgRsrcDataEntry.Reserved)
			fmt.Fprintf(w, "|- Language: %d (%s)\n\t", entry.Lang, entry.Lang.String())
			fmt.Fprintf(w, "|- Sub-language: %s\n\t", peparser.PrettyResourceLang(entry.Lang, int(entry.SubLang)))
			w.Flush()
			padding--
		}

		printRsrcDir = func(rsrcDir peparser.ResourceDirectory) {
			padding++
			w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
			imgRsrcDir := rsrcDir.Struct
			fmt.Fprintf(w, "\n\t\u27A1 Resource Directory\n\t")
			fmt.Fprintf(w, "|- Characteristics: 0x%x\n\t", imgRsrcDir.Characteristics)
			fmt.Fprintf(w, "|- TimeDateStamp: 0x%x\n\t", imgRsrcDir.TimeDateStamp)
			fmt.Fprintf(w, "|- Major Version: 0x%x\n\t", imgRsrcDir.MajorVersion)
			fmt.Fprintf(w, "|- Minor Version: 0x%x\n\t", imgRsrcDir.MinorVersion)
			fmt.Fprintf(w, "|- Number Of Named Entries: 0x%x\n\t", imgRsrcDir.NumberOfNamedEntries)
			fmt.Fprintf(w, "|- Number Of ID Entries: 0x%x\n\t", imgRsrcDir.NumberOfIDEntries)
			fmt.Fprintf(w, "|----------------------------------\n\t")
			padding++
			w.Flush()
			w = tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
			for i, entry := range rsrcDir.Entries {
				fmt.Fprintf(w, "\t|- \u27A1 Resource Directory Entry %d, ID: %d", i+1, entry.ID)

				// Print the interpretation of a resource ID only in root node.
				if padding == 2 {
					if entry.ID <= peparser.RTManifest {
						fmt.Fprintf(w, " (%s)", peparser.ResourceType(entry.ID).String())
					}
				}
				fmt.Fprintf(w, "\n\t|- Name: 0x%x\n\t", entry.Struct.Name)
				if entry.Name != "" {
					fmt.Fprintf(w, " (%s)", entry.Name)
				}
				fmt.Fprintf(w, "|- Offset To Data: 0x%x\t", entry.Struct.OffsetToData)
				fmt.Fprintf(w, "\n\t|----------------------------------\t")
				w.Flush()
				if entry.IsResourceDir {
					printRsrcDir(entry.Directory)
				} else {
					printRsrcDataEntry(entry.Data)
				}

			}
			padding -= 2

		}

		fmt.Printf("\nRESOURCES\n**********\n")
		printRsrcDir(pe.Resources)

		versionInfo, err := pe.ParseVersionResources()
		if err != nil {
			log.Errorf("failed to parse version resources: %v", err)
		} else {
			fmt.Printf("\nVersion Info: %v", prettyPrint(versionInfo))
		}
	}

	if cfg.wantException && pe.FileInfo.HasException {
		fmt.Printf("\nEXCEPTIONS\n***********\n")
		for _, exception := range pe.Exceptions {
			entry := exception.RuntimeFunction
			fmt.Printf("\n\u27A1 BeginAddress: 0x%x EndAddress:0x%x UnwindInfoAddress:0x%x\t\n",
				entry.BeginAddress, entry.EndAddress, entry.UnwindInfoAddress)

			ui := exception.UnwindInfo
			handlerFlags := peparser.PrettyUnwindInfoHandlerFlags(ui.Flags)
			prettyFlags := strings.Join(handlerFlags, ",")
			fmt.Printf("|- Version: 0x%x\n", ui.Version)
			fmt.Printf("|- Flags: 0x%x", ui.Flags)
			if ui.Flags == 0 {
				fmt.Print(" (None)\n")
			} else {
				fmt.Printf(" (%s)\n", prettyFlags)
			}

			fmt.Printf("|- Size Of Prolog: 0x%x\n", ui.SizeOfProlog)
			fmt.Printf("|- Count Of Codes: 0x%x\n", ui.CountOfCodes)
			fmt.Printf("|- Exception Handler: 0x%x\n", ui.ExceptionHandler)
			fmt.Print("|- Unwind codes:\n")
			for _, uc := range ui.UnwindCodes {
				fmt.Printf("|-  * %.2x: %s, %s\n", uc.CodeOffset,
					uc.UnwindOp.String(), uc.Operand)
			}
		}
	}

	if cfg.wantCertificate && pe.FileInfo.HasCertificate {
		fmt.Printf("\nSECURITY\n*********\n")

		cert := pe.Certificates
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		fmt.Fprintln(w, "Length\tRevision\tCertificateType\t")
		fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t\n", cert.Header.Length, cert.Header.Revision,
			cert.Header.CertificateType)
		w.Flush()
		fmt.Print("\n   ---Raw Certificate dump---\n")
		hexDump(cert.Raw)
		for _, cert := range cert.Certificates {
			fmt.Print("\n---Certificate ---\n\n")
			fmt.Fprintf(w, "Issuer Name:\t %s\n", cert.Info.Issuer)
			fmt.Fprintf(w, "Subject Name:\t %s\n", cert.Info.Subject)
			fmt.Fprintf(w, "Serial Number:\t %x\n", cert.Info.SerialNumber)
			fmt.Fprintf(w, "Validity From:\t %s to %s\n", cert.Info.NotBefore.String(), cert.Info.NotAfter.String())
			fmt.Fprintf(w, "Signature Algorithm:\t %s\n", cert.Info.SignatureAlgorithm.String())
			fmt.Fprintf(w, "PublicKey Algorithm:\t %s\n", cert.Info.PublicKeyAlgorithm.String())
			fmt.Fprintf(w, "Certificate valid:\t %v\n", cert.Verified)
			fmt.Fprintf(w, "Signature valid:\t %v\n", cert.SignatureValid)
			w.Flush()
		}

		// Calculate the PE authentihash.
		pe.Authentihash()
	}

	if cfg.wantReloc && pe.FileInfo.HasReloc {
		fmt.Printf("\nRELOCATIONS\n***********\n")
		for _, reloc := range pe.Relocations {
			fmt.Printf("\n\u27A1 Virtual Address: 0x%x | Size Of Block:0x%x | Entries Count:0x%x\t\n",
				reloc.Data.VirtualAddress, reloc.Data.SizeOfBlock, len(reloc.Entries))
			fmt.Print("|- Entries:\n")
			for _, relocEntry := range reloc.Entries {
				fmt.Printf("|-  Data: 0x%x |  Offset: 0x%x | Type:0x%x (%s)\n", relocEntry.Data,
					relocEntry.Offset, relocEntry.Type, relocEntry.Type.String(pe))
			}
		}
	}

	if cfg.wantDebug && pe.FileInfo.HasDebug {
		fmt.Printf("\nDEBUGS\n*******\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		for _, debug := range pe.Debugs {
			imgDbgDir := debug.Struct
			fmt.Fprintf(w, "\n\t------[ %s ]------\n", debug.Type)
			fmt.Fprintf(w, "Characteristics:\t 0x%x\n", imgDbgDir.Characteristics)
			fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", imgDbgDir.TimeDateStamp,
				humanizeTimestamp(imgDbgDir.TimeDateStamp))
			fmt.Fprintf(w, "Major Version:\t 0x%x\n", imgDbgDir.MajorVersion)
			fmt.Fprintf(w, "Minor Version:\t 0x%x\n", imgDbgDir.MinorVersion)
			fmt.Fprintf(w, "Type:\t 0x%x\n", imgDbgDir.Type)
			fmt.Fprintf(w, "Size Of Data:\t 0x%x (%s)\n", imgDbgDir.SizeOfData,
				BytesSize(float64(imgDbgDir.SizeOfData)))
			fmt.Fprintf(w, "Address Of Raw Data:\t 0x%x\n", imgDbgDir.AddressOfRawData)
			fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", imgDbgDir.PointerToRawData)
			fmt.Fprintf(w, "\n")
			switch imgDbgDir.Type {
			case peparser.ImageDebugTypeCodeView:
				debugSignature, err := pe.ReadUint32(imgDbgDir.PointerToRawData)
				if err != nil {
					continue
				}
				switch debugSignature {
				case peparser.CVSignatureRSDS:
					pdb := debug.Info.(peparser.CVInfoPDB70)
					fmt.Fprintf(w, "CV Signature:\t 0x%x (%s)\n", pdb.CVSignature,
						pdb.CVSignature.String())
					fmt.Fprintf(w, "Signature:\t %s\n", pdb.Signature.String())
					fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age)
					fmt.Fprintf(w, "PDB FileName:\t %s\n", pdb.PDBFileName)
				case peparser.CVSignatureNB10:
					pdb := debug.Info.(peparser.CVInfoPDB20)
					fmt.Fprintf(w, "CV Header Signature:\t 0x%x (%s)\n",
						pdb.CVHeader.Signature, pdb.CVHeader.Signature.String())
					fmt.Fprintf(w, "CV Header Offset:\t 0x%x\n", pdb.CVHeader.Offset)
					fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", pdb.Signature,
						humanizeTimestamp(pdb.Signature))
					fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age)
					fmt.Fprintf(w, "PDBFileName:\t %s\n", pdb.PDBFileName)
				}
			case peparser.ImageDebugTypePOGO:
				pogo := debug.Info.(peparser.POGO)
				if len(pogo.Entries) > 0 {
					fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n\n", pogo.Signature,
						pogo.Signature.String())
					fmt.Fprintln(w, "RVA\tSize\tName\tDescription\t")
					fmt.Fprintln(w, "---\t----\t----\t-----------\t")
					for _, pogoEntry := range pogo.Entries {
						fmt.Fprintf(w, "0x%x\t0x%x\t%s\t%s\t\n", pogoEntry.RVA,
							pogoEntry.Size, pogoEntry.Name,
							peparser.SectionAttributeDescription(pogoEntry.Name))
					}
				}
			case peparser.ImageDebugTypeRepro:
				repro := debug.Info.(peparser.REPRO)
				fmt.Fprintf(w, "Hash:\t %x\n", repro.Hash)
				fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", repro.Size, BytesSize(float64(repro.Size)))
			case peparser.ImageDebugTypeExDllCharacteristics:
				exDllCharacteristics := debug.Info.(peparser.DllCharacteristicsExType)
				fmt.Fprintf(w, "Value:\t %d (%s)\n", exDllCharacteristics,
					exDllCharacteristics.String())
			case peparser.ImageDebugTypeVCFeature:
				VCFeature := debug.Info.(peparser.VCFeature)
				fmt.Fprintf(w, "Pre VC11:\t 0x%x\n", VCFeature.PreVC11)
				fmt.Fprintf(w, "C/C++:\t 0x%x\n", VCFeature.CCpp)
				fmt.Fprintf(w, "/GS:\t 0x%x\n", VCFeature.Gs)
				fmt.Fprintf(w, "/sdl:\t 0x%x\n", VCFeature.Sdl)
				fmt.Fprintf(w, "GuardN:\t 0x%x\n", VCFeature.GuardN)
			case peparser.ImageDebugTypeFPO:
				fpo := debug.Info.([]peparser.FPOData)
				if len(fpo) > 0 {
					fmt.Fprintln(w, "OffsetStart\tProcSize\tNumLocals\tParamsSize\tPrologLength\tSavedRegsCount\tHasSEH\tUseBP\tReserved\tFrameType\t")
					fmt.Fprintln(w, "------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t")
					for _, fpoData := range fpo {
						fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t%d (%s)\t\n",
							fpoData.OffsetStart, fpoData.ProcSize, fpoData.NumLocals,
							fpoData.ParamsSize, fpoData.PrologLength,
							fpoData.SavedRegsCount, fpoData.HasSEH, fpoData.UseBP,
							fpoData.Reserved, fpoData.FrameType, fpoData.FrameType.String())
					}
				}
			}
		}

		w.Flush()
	}

	if cfg.wantBoundImp && pe.FileInfo.HasBoundImp {
		fmt.Printf("\nBOUND IMPORTS\n************\n")

		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		for _, bndImp := range pe.BoundImports {
			fmt.Printf("\n\t------[ %s ]------\n\n", bndImp.Name)
			fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", bndImp.Struct.TimeDateStamp,
				humanizeTimestamp(bndImp.Struct.TimeDateStamp))
			fmt.Fprintf(w, "Offset Module Name:\t 0x%x\n", bndImp.Struct.OffsetModuleName)
			fmt.Fprintf(w, "# Module Forwarder Refs:\t 0x%x\n", bndImp.Struct.NumberOfModuleForwarderRefs)
			fmt.Fprintf(w, "\n")
			if len(bndImp.ForwardedRefs) > 0 {
				fmt.Fprintln(w, "Name\tTimeDateStamp\tOffsetModuleName\tReserved\t")
				for _, fr := range bndImp.ForwardedRefs {
					fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t\n", fr.Name,
						fr.Struct.TimeDateStamp, fr.Struct.OffsetModuleName,
						fr.Struct.Reserved)
				}
			}
			w.Flush()
		}
	}

	if cfg.wantTLS && pe.FileInfo.HasTLS {
		fmt.Printf("\nTLS\n*****\n\n")

		tls := pe.TLS
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		if pe.Is64 {
			imgTLSDirectory64 := tls.Struct.(peparser.ImageTLSDirectory64)
			fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.StartAddressOfRawData)
			fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.EndAddressOfRawData)
			fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory64.AddressOfIndex)
			fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory64.AddressOfCallBacks)
			fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory64.SizeOfZeroFill)
			fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory64.Characteristics,
				imgTLSDirectory64.Characteristics.String())
			fmt.Fprintf(w, "Callbacks:\n")
			if tls.Callbacks != nil && len(tls.Callbacks.([]uint64)) > 0 {
				for _, callback := range tls.Callbacks.([]uint64) {
					fmt.Fprintf(w, "0x%x\t\n", callback)
				}
			}
		} else {
			imgTLSDirectory32 := tls.Struct.(peparser.ImageTLSDirectory32)
			fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.StartAddressOfRawData)
			fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.EndAddressOfRawData)
			fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory32.AddressOfIndex)
			fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory32.AddressOfCallBacks)
			fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory32.SizeOfZeroFill)
			fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory32.Characteristics,
				imgTLSDirectory32.Characteristics.String())
			fmt.Fprintf(w, "Callbacks:\n")
			if tls.Callbacks != nil && len(tls.Callbacks.([]uint32)) > 0 {
				for _, callback := range tls.Callbacks.([]uint32) {
					fmt.Fprintf(w, "0x%x\t\n", callback)
				}
			}
		}

		w.Flush()
	}

	if cfg.wantLoadCfg && pe.FileInfo.HasLoadCFG {
		fmt.Printf("\nLOAD CONFIG\n************\n\n")

		loadConfig := pe.LoadConfig
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.TabIndent)
		v := reflect.ValueOf(loadConfig.Struct)
		typeOfS := v.Type()
		imgLoadConfigDirectorySize := v.Field(0).Interface().(uint32)
		tmp := uint32(0)
		for i := 0; i < v.NumField(); i++ {
			// Do not print the fields of the image load config directory structure
			// that does not belong to it.
			tmp += uint32(binary.Size((v.Field(i).Interface())))
			if tmp > imgLoadConfigDirectorySize {
				break
			}
			fmt.Fprintf(w, "  %s\t : 0x%v\n", sentenceCase(typeOfS.Field(i).Name),
				v.Field(i).Interface())
		}
		w.Flush()
	}

	if cfg.wantDelayImp && pe.FileInfo.HasDelayImp {
		fmt.Printf("\nDELAY IMPORTS\n**************\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		for _, imp := range pe.DelayImports {
			desc := imp.Descriptor
			fmt.Printf("\n\t------[ %s ]------\n\n", imp.Name)
			fmt.Fprintf(w, "Attributes:\t 0x%x\n", desc.Attributes)
			fmt.Fprintf(w, "Name:\t 0x%x\n", desc.Name)
			fmt.Fprintf(w, "Module Handle RVA:\t 0x%x\n", desc.ModuleHandleRVA)
			fmt.Fprintf(w, "Import Address Table RVA:\t 0x%x\n", desc.ImportAddressTableRVA)
			fmt.Fprintf(w, "Import Name Table RVA:\t 0x%x\n", desc.ImportNameTableRVA)
			fmt.Fprintf(w, "Bound Import Address Table RVA:\t 0x%x\n", desc.BoundImportAddressTableRVA)
			fmt.Fprintf(w, "Unload Information Table RVA:\t 0x%x\n", desc.UnloadInformationTableRVA)
			fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", desc.TimeDateStamp,
				humanizeTimestamp(desc.TimeDateStamp))
			fmt.Fprintf(w, "\n")
			fmt.Fprintln(w, "Name\tThunkRVA\tThunkValue\tOriginalThunkRVA\tOriginalThunkValue\tHint\t")
			for _, fn := range imp.Functions {
				fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
					fn.Name, fn.ThunkRVA, fn.ThunkValue,
					fn.OriginalThunkRVA, fn.OriginalThunkValue, fn.Hint)
			}
			w.Flush()
		}
	}

	if cfg.wantIAT && pe.FileInfo.HasIAT {
		fmt.Printf("\nIAT\n****\n\n")
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
		fmt.Fprintln(w, "Index\tRVA\tValue\tMeaning\t")
		for _, entry := range pe.IAT {
			fmt.Fprintf(w, "0x%x\t0x%x\t%v\t%s\t\n",
				entry.Index, entry.Rva, entry.Value, entry.Meaning)
		}
		w.Flush()
	}

	if cfg.wantCLR && pe.FileInfo.HasCLR {
		fmt.Printf("\nCLR\n****\n")

		fmt.Print("\n\t------[ CLR Header ]------\n\n")
		clr := pe.CLR
		w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)

		clrHdr := clr.CLRHeader
		flags := strings.Join(clrHdr.Flags.String(), " | ")
		fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", clrHdr.Cb)
		fmt.Fprintf(w, "Major Runtime Version:\t 0x%x\n", clrHdr.MajorRuntimeVersion)
		fmt.Fprintf(w, "Minor Runtime Version:\t 0x%x\n", clrHdr.MinorRuntimeVersion)
		fmt.Fprintf(w, "MetaData RVA:\t 0x%x\n", clrHdr.MetaData.VirtualAddress)
		fmt.Fprintf(w, "MetaData Size:\t 0x%x\n", clrHdr.MetaData.Size)
		fmt.Fprintf(w, "Flags:\t 0x%x (%v)\n", clrHdr.Flags, flags)
		fmt.Fprintf(w, "EntryPoint RVA or Token:\t 0x%x\n", clrHdr.EntryPointRVAorToken)
		fmt.Fprintf(w, "Resources RVA:\t 0x%x\n", clrHdr.Resources.VirtualAddress)
		fmt.Fprintf(w, "Resources Size:\t 0x%x (%s)\n", clrHdr.Resources.Size, BytesSize(float64(clrHdr.Resources.Size)))
		fmt.Fprintf(w, "Strong Name Signature RVA:\t 0x%x\n", clrHdr.StrongNameSignature.VirtualAddress)
		fmt.Fprintf(w, "Strong Name Signature Size:\t 0x%x (%s)\n", clrHdr.StrongNameSignature.Size, BytesSize(float64(clrHdr.StrongNameSignature.Size)))
		fmt.Fprintf(w, "Code Manager Table RVA:\t 0x%x\n", clrHdr.CodeManagerTable.VirtualAddress)
		fmt.Fprintf(w, "Code Manager Table Size:\t 0x%x (%s)\n", clrHdr.CodeManagerTable.Size, BytesSize(float64(clrHdr.CodeManagerTable.Size)))
		fmt.Fprintf(w, "VTable Fixups RVA:\t 0x%x\n", clrHdr.VTableFixups.VirtualAddress)
		fmt.Fprintf(w, "VTable Fixups Size:\t 0x%x (%s)\n", clrHdr.VTableFixups.Size, BytesSize(float64(clrHdr.VTableFixups.Size)))
		fmt.Fprintf(w, "Export Address Table Jumps RVA:\t 0x%x\n", clrHdr.ExportAddressTableJumps.VirtualAddress)
		fmt.Fprintf(w, "Export Address Table Jumps Size:\t 0x%x (%s)\n", clrHdr.ExportAddressTableJumps.Size, BytesSize(float64(clrHdr.ExportAddressTableJumps.Size)))
		fmt.Fprintf(w, "Managed Native Header RVA:\t 0x%x\n", clrHdr.ManagedNativeHeader.VirtualAddress)
		fmt.Fprintf(w, "Managed Native Header Size:\t 0x%x (%s)\n", clrHdr.ManagedNativeHeader.Size, BytesSize(float64(clrHdr.ManagedNativeHeader.Size)))
		w.Flush()

		fmt.Print("\n\t------[ MetaData Header ]------\n\n")
		mdHdr := clr.MetadataHeader
		fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", mdHdr.Signature,
			string(IntToByteArray(uint64(mdHdr.Signature))))
		fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdHdr.MajorVersion)
		fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdHdr.MinorVersion)
		fmt.Fprintf(w, "Extra Data:\t 0x%x\n", mdHdr.ExtraData)
		fmt.Fprintf(w, "Version String Length:\t 0x%x\n", mdHdr.VersionString)
		fmt.Fprintf(w, "Version String:\t %s\n", mdHdr.Version)
		fmt.Fprintf(w, "Flags:\t 0x%x\n", mdHdr.Flags)
		fmt.Fprintf(w, "Streams Count:\t 0x%x\n", mdHdr.Streams)
		w.Flush()

		fmt.Print("\n\t------[ MetaData Streams ]------\n\n")
		for _, sh := range clr.MetadataStreamHeaders {
			fmt.Fprintf(w, "Stream Name:\t %s\n", sh.Name)
			fmt.Fprintf(w, "Offset:\t 0x%x\n", sh.Offset)
			fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", sh.Size, BytesSize(float64(sh.Size)))
			w.Flush()
			fmt.Print("\n   ---Stream Content---\n")
			hexDumpSize(clr.MetadataStreams[sh.Name], 128)
			fmt.Print("\n")
		}

		fmt.Print("\n\t------[ MetaData Tables Stream Header ]------\n\n")
		mdTablesStreamHdr := clr.MetadataTablesStreamHeader
		fmt.Fprintf(w, "Reserved:\t 0x%x\n", mdTablesStreamHdr.Reserved)
		fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdTablesStreamHdr.MajorVersion)
		fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdTablesStreamHdr.MinorVersion)
		fmt.Fprintf(w, "Heaps:\t 0x%x\n", mdTablesStreamHdr.Heaps)
		fmt.Fprintf(w, "RID:\t 0x%x\n", mdTablesStreamHdr.RID)
		fmt.Fprintf(w, "MaskValid:\t 0x%x\n", mdTablesStreamHdr.MaskValid)
		fmt.Fprintf(w, "Sorted:\t 0x%x\n", mdTablesStreamHdr.Sorted)
		w.Flush()

		fmt.Print("\n\t------[ MetaData Tables ]------\n\n")
		mdTables := clr.MetadataTables
		for _, mdTable := range mdTables {
			fmt.Fprintf(w, "Name:\t %s | Items Count:\t 0x%x\n", mdTable.Name, mdTable.CountCols)
		}
		w.Flush()

		for table, modTable := range pe.CLR.MetadataTables {
			switch table {
			case peparser.Module:
				fmt.Print("\n\t[Modules]\n\t---------\n")
				modTableRows := modTable.Content.([]peparser.ModuleTableRow)
				for _, modTableRow := range modTableRows {
					modName := pe.GetStringFromData(modTableRow.Name, pe.CLR.MetadataStreams["#Strings"])
					Mvid := pe.GetStringFromData(modTableRow.Mvid, pe.CLR.MetadataStreams["#GUID"])
					MvidStr := hex.EncodeToString(Mvid)
					fmt.Fprintf(w, "Generation:\t 0x%x\n", modTableRow.Generation)
					fmt.Fprintf(w, "Name:\t 0x%x (%s)\n", modTableRow.Name, string(modName))
					fmt.Fprintf(w, "Mvid:\t 0x%x (%s)\n", modTableRow.Mvid, MvidStr)
					fmt.Fprintf(w, "EncID:\t 0x%x\n", modTableRow.EncID)
					fmt.Fprintf(w, "EncBaseID:\t 0x%x\n", modTableRow.EncBaseID)
				}
				w.Flush()

			}
		}
	}

	// Get file type.
	if pe.IsEXE() {
		log.Debug("File is Exe")
	}
	if pe.IsDLL() {
		log.Debug("File is DLL")
	}
	if pe.IsDriver() {
		log.Debug("File is Driver")
	}

	// Calculate the PE checksum.
	pe.Checksum()

	fmt.Print("\n")
}


================================================
FILE: cmd/main.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
)

type config struct {
	wantDOSHeader   bool
	wantRichHeader  bool
	wantNTHeader    bool
	wantCOFF        bool
	wantDataDirs    bool
	wantSections    bool
	wantExport      bool
	wantImport      bool
	wantResource    bool
	wantException   bool
	wantCertificate bool
	wantReloc       bool
	wantDebug       bool
	wantTLS         bool
	wantLoadCfg     bool
	wantBoundImp    bool
	wantIAT         bool
	wantDelayImp    bool
	wantCLR         bool
}

func main() {

	dumpCmd := flag.NewFlagSet("dump", flag.ExitOnError)
	dumpDOSHdr := dumpCmd.Bool("dosheader", false, "Dump DOS header")
	dumpRichHdr := dumpCmd.Bool("richheader", false, "Dump Rich header")
	dumpNTHdr := dumpCmd.Bool("ntheader", false, "Dump NT header")
	dumpCOFF := dumpCmd.Bool("coff", false, "Dump COFF symbols")
	dumpDirs := dumpCmd.Bool("directories", false, "Dump data directories")
	dumpSections := dumpCmd.Bool("sections", false, "Dump sections")
	dumpExport := dumpCmd.Bool("export", false, "Dump export table")
	dumpImport := dumpCmd.Bool("import", false, "Dump import table")
	dumpResource := dumpCmd.Bool("resource", false, "Dump resource table")
	dumpException := dumpCmd.Bool("exception", false, "Dump exception table")
	dumpCertificate := dumpCmd.Bool("cert", false, "Dump certificate directory")
	dumpReloc := dumpCmd.Bool("reloc", false, "Dump relocation table")
	dumpDebug := dumpCmd.Bool("debug", false, "Dump debug infos")
	dumpTLS := dumpCmd.Bool("tls", false, "Dump TLS")
	dumpLoadCfg := dumpCmd.Bool("loadconfig", false, "Dump load configuration table")
	dumpBoundImport := dumpCmd.Bool("bound", false, "Dump bound import table")
	dumpIAT := dumpCmd.Bool("iat", false, "Dump IAT")
	dumpDelayedImport := dumpCmd.Bool("delay", false, "Dump delay import descriptor")
	dumpCLR := dumpCmd.Bool("clr", false, "Dump CLR")

	dumpCmd.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: pedumper dump [flags] <file-or-directory>\n\nFlags:\n")
		dumpCmd.PrintDefaults()
	}

	if len(os.Args) < 2 {
		showHelp()
	}

	switch os.Args[1] {

	case "dump":
		dumpCmd.Parse(os.Args[2:])

		args := dumpCmd.Args()
		if len(args) == 0 {
			fmt.Fprintf(os.Stderr, "Error: missing file or directory path\n\n")
			dumpCmd.Usage()
			os.Exit(1)
		}
		filePath := args[0]

		// If no flags are specified, dump everything.
		noFlagsSet := true
		dumpCmd.Visit(func(f *flag.Flag) { noFlagsSet = false })

		cfg := config{
			wantDOSHeader:   *dumpDOSHdr || noFlagsSet,
			wantRichHeader:  *dumpRichHdr || noFlagsSet,
			wantNTHeader:    *dumpNTHdr || noFlagsSet,
			wantCOFF:        *dumpCOFF || noFlagsSet,
			wantDataDirs:    *dumpDirs || noFlagsSet,
			wantSections:    *dumpSections || noFlagsSet,
			wantExport:      *dumpExport || noFlagsSet,
			wantImport:      *dumpImport || noFlagsSet,
			wantResource:    *dumpResource || noFlagsSet,
			wantException:   *dumpException || noFlagsSet,
			wantCertificate: *dumpCertificate || noFlagsSet,
			wantReloc:       *dumpReloc || noFlagsSet,
			wantDebug:       *dumpDebug || noFlagsSet,
			wantTLS:         *dumpTLS || noFlagsSet,
			wantLoadCfg:     *dumpLoadCfg || noFlagsSet,
			wantBoundImp:    *dumpBoundImport || noFlagsSet,
			wantIAT:         *dumpIAT || noFlagsSet,
			wantDelayImp:    *dumpDelayedImport || noFlagsSet,
			wantCLR:         *dumpCLR || noFlagsSet,
		}

		// Start as many workers you want, default to cpu count -1.
		numWorkers := runtime.GOMAXPROCS(runtime.NumCPU() - 1)
		for w := 1; w <= numWorkers; w++ {
			go loopFilesWorker(cfg)
		}

		if !isDirectory(filePath) {
			// Input path in a single file.
			parsePE(filePath, cfg)
		} else {
			// Input path in a directory.
			LoopDirsFiles(filePath)
			wg.Wait()
		}

	case "version":
		fmt.Println("You are using version 1.6.0")
	default:
		showHelp()
	}
}

func showHelp() {
	fmt.Print(
		`
╔═╗╔═╗  ┌─┐┌─┐┬─┐┌─┐┌─┐┬─┐
╠═╝║╣   ├─┘├─┤├┬┘└─┐├┤ ├┬┘
╩  ╚═╝  ┴  ┴ ┴┴└─└─┘└─┘┴└─

A PE-Parser built for speed and malware-analysis in mind.
Brought to you by Saferwall (c) 2018 MIT

Usage: pedumper <command> [options]

Commands:
  dump [flags] <file-or-directory>    Parse and dump PE file information
  version                             Show version information

Run 'pedumper dump -help' for dump flags.
`)

	os.Exit(1)
}


================================================
FILE: cmd/size.go
================================================
package main

import (
	"fmt"
	"strconv"
	"strings"
)

// See: http://en.wikipedia.org/wiki/Binary_prefix
const (
	// Decimal

	KB = 1000
	MB = 1000 * KB
	GB = 1000 * MB
	TB = 1000 * GB
	PB = 1000 * TB

	// Binary

	KiB = 1024
	MiB = 1024 * KiB
	GiB = 1024 * MiB
	TiB = 1024 * GiB
	PiB = 1024 * TiB
)

type unitMap map[byte]int64

var (
	decimalMap = unitMap{'k': KB, 'm': MB, 'g': GB, 't': TB, 'p': PB}
	binaryMap  = unitMap{'k': KiB, 'm': MiB, 'g': GiB, 't': TiB, 'p': PiB}
)

var (
	decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
	binaryAbbrs  = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
)

func getSizeAndUnit(size float64, base float64, _map []string) (float64, string) {
	i := 0
	unitsLimit := len(_map) - 1
	for size >= base && i < unitsLimit {
		size = size / base
		i++
	}
	return size, _map[i]
}

// CustomSize returns a human-readable approximation of a size
// using custom format.
func CustomSize(format string, size float64, base float64, _map []string) string {
	size, unit := getSizeAndUnit(size, base, _map)
	return fmt.Sprintf(format, size, unit)
}

// HumanSizeWithPrecision allows the size to be in any precision,
// instead of 4 digit precision used in units.HumanSize.
func HumanSizeWithPrecision(size float64, precision int) string {
	size, unit := getSizeAndUnit(size, 1000.0, decimapAbbrs)
	return fmt.Sprintf("%.*g%s", precision, size, unit)
}

// HumanSize returns a human-readable approximation of a size
// capped at 4 valid numbers (eg. "2.746 MB", "796 KB").
func HumanSize(size float64) string {
	return HumanSizeWithPrecision(size, 4)
}

// BytesSize returns a human-readable size in bytes, kibibytes,
// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
func BytesSize(size float64) string {
	return CustomSize("%.4g%s", size, 1024.0, binaryAbbrs)
}

// FromHumanSize returns an integer from a human-readable specification of a
// size using SI standard (eg. "44kB", "17MB").
func FromHumanSize(size string) (int64, error) {
	return parseSize(size, decimalMap)
}

// RAMInBytes parses a human-readable string representing an amount of RAM
// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
// returns the number of bytes, or -1 if the string is unparseable.
// Units are case-insensitive, and the 'b' suffix is optional.
func RAMInBytes(size string) (int64, error) {
	return parseSize(size, binaryMap)
}

// Parses the human-readable size string into the amount it represents.
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
	// TODO: rewrite to use strings.Cut if there's a space
	// once Go < 1.18 is deprecated.
	sep := strings.LastIndexAny(sizeStr, "01234567890. ")
	if sep == -1 {
		// There should be at least a digit.
		return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
	}
	var num, sfx string
	if sizeStr[sep] != ' ' {
		num = sizeStr[:sep+1]
		sfx = sizeStr[sep+1:]
	} else {
		// Omit the space separator.
		num = sizeStr[:sep]
		sfx = sizeStr[sep+1:]
	}

	size, err := strconv.ParseFloat(num, 64)
	if err != nil {
		return -1, err
	}
	// Backward compatibility: reject negative sizes.
	if size < 0 {
		return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
	}

	if len(sfx) == 0 {
		return int64(size), nil
	}

	// Process the suffix.

	if len(sfx) > 3 { // Too long.
		goto badSuffix
	}
	sfx = strings.ToLower(sfx)
	// Trivial case: b suffix.
	if sfx[0] == 'b' {
		if len(sfx) > 1 { // no extra characters allowed after b.
			goto badSuffix
		}
		return int64(size), nil
	}
	// A suffix from the map.
	if mul, ok := uMap[sfx[0]]; ok {
		size *= float64(mul)
	} else {
		goto badSuffix
	}

	// The suffix may have extra "b" or "ib" (e.g. KiB or MB).
	switch {
	case len(sfx) == 2 && sfx[1] != 'b':
		goto badSuffix
	case len(sfx) == 3 && sfx[1:] != "ib":
		goto badSuffix
	}

	return int64(size), nil

badSuffix:
	return -1, fmt.Errorf("invalid suffix: '%s'", sfx)
}


================================================
FILE: cmd/size_test.go
================================================
package main

import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

func ExampleBytesSize() {
	fmt.Println(BytesSize(1024))
	fmt.Println(BytesSize(1024 * 1024))
	fmt.Println(BytesSize(1048576))
	fmt.Println(BytesSize(2 * MiB))
	fmt.Println(BytesSize(3.42 * GiB))
	fmt.Println(BytesSize(5.372 * TiB))
	fmt.Println(BytesSize(2.22 * PiB))
}

func ExampleHumanSize() {
	fmt.Println(HumanSize(1000))
	fmt.Println(HumanSize(1024))
	fmt.Println(HumanSize(1000000))
	fmt.Println(HumanSize(1048576))
	fmt.Println(HumanSize(2 * MB))
	fmt.Println(HumanSize(float64(3.42 * GB)))
	fmt.Println(HumanSize(float64(5.372 * TB)))
	fmt.Println(HumanSize(float64(2.22 * PB)))
}

func ExampleFromHumanSize() {
	fmt.Println(FromHumanSize("32"))
	fmt.Println(FromHumanSize("32b"))
	fmt.Println(FromHumanSize("32B"))
	fmt.Println(FromHumanSize("32k"))
	fmt.Println(FromHumanSize("32K"))
	fmt.Println(FromHumanSize("32kb"))
	fmt.Println(FromHumanSize("32Kb"))
	fmt.Println(FromHumanSize("32Mb"))
	fmt.Println(FromHumanSize("32Gb"))
	fmt.Println(FromHumanSize("32Tb"))
	fmt.Println(FromHumanSize("32Pb"))
}

func ExampleRAMInBytes() {
	fmt.Println(RAMInBytes("32"))
	fmt.Println(RAMInBytes("32b"))
	fmt.Println(RAMInBytes("32B"))
	fmt.Println(RAMInBytes("32k"))
	fmt.Println(RAMInBytes("32K"))
	fmt.Println(RAMInBytes("32kb"))
	fmt.Println(RAMInBytes("32Kb"))
	fmt.Println(RAMInBytes("32Mb"))
	fmt.Println(RAMInBytes("32Gb"))
	fmt.Println(RAMInBytes("32Tb"))
	fmt.Println(RAMInBytes("32Pb"))
	fmt.Println(RAMInBytes("32PB"))
	fmt.Println(RAMInBytes("32P"))
}

func TestBytesSize(t *testing.T) {
	assertEquals(t, "1KiB", BytesSize(1024))
	assertEquals(t, "1MiB", BytesSize(1024*1024))
	assertEquals(t, "1MiB", BytesSize(1048576))
	assertEquals(t, "2MiB", BytesSize(2*MiB))
	assertEquals(t, "3.42GiB", BytesSize(3.42*GiB))
	assertEquals(t, "5.372TiB", BytesSize(5.372*TiB))
	assertEquals(t, "2.22PiB", BytesSize(2.22*PiB))
	assertEquals(t, "1.049e+06YiB", BytesSize(KiB*KiB*KiB*KiB*KiB*PiB))
}

func TestHumanSize(t *testing.T) {
	assertEquals(t, "1kB", HumanSize(1000))
	assertEquals(t, "1.024kB", HumanSize(1024))
	assertEquals(t, "1MB", HumanSize(1000000))
	assertEquals(t, "1.049MB", HumanSize(1048576))
	assertEquals(t, "2MB", HumanSize(2*MB))
	assertEquals(t, "3.42GB", HumanSize(float64(3.42*GB)))
	assertEquals(t, "5.372TB", HumanSize(float64(5.372*TB)))
	assertEquals(t, "2.22PB", HumanSize(float64(2.22*PB)))
	assertEquals(t, "1e+04YB", HumanSize(float64(10000000000000*PB)))
}

func TestFromHumanSize(t *testing.T) {
	assertSuccessEquals(t, 0, FromHumanSize, "0")
	assertSuccessEquals(t, 0, FromHumanSize, "0b")
	assertSuccessEquals(t, 0, FromHumanSize, "0B")
	assertSuccessEquals(t, 0, FromHumanSize, "0 B")
	assertSuccessEquals(t, 32, FromHumanSize, "32")
	assertSuccessEquals(t, 32, FromHumanSize, "32b")
	assertSuccessEquals(t, 32, FromHumanSize, "32B")
	assertSuccessEquals(t, 32*KB, FromHumanSize, "32k")
	assertSuccessEquals(t, 32*KB, FromHumanSize, "32K")
	assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb")
	assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb")
	assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb")
	assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb")
	assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb")
	assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb")

	assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5kB")
	assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5 kB")
	assertSuccessEquals(t, 32, FromHumanSize, "32.5 B")
	assertSuccessEquals(t, 300, FromHumanSize, "0.3 K")
	assertSuccessEquals(t, 300, FromHumanSize, ".3kB")

	assertSuccessEquals(t, 0, FromHumanSize, "0.")
	assertSuccessEquals(t, 0, FromHumanSize, "0. ")
	assertSuccessEquals(t, 0, FromHumanSize, "0.b")
	assertSuccessEquals(t, 0, FromHumanSize, "0.B")
	assertSuccessEquals(t, 0, FromHumanSize, "-0")
	assertSuccessEquals(t, 0, FromHumanSize, "-0b")
	assertSuccessEquals(t, 0, FromHumanSize, "-0B")
	assertSuccessEquals(t, 0, FromHumanSize, "-0 b")
	assertSuccessEquals(t, 0, FromHumanSize, "-0 B")
	assertSuccessEquals(t, 32, FromHumanSize, "32.")
	assertSuccessEquals(t, 32, FromHumanSize, "32.b")
	assertSuccessEquals(t, 32, FromHumanSize, "32.B")
	assertSuccessEquals(t, 32, FromHumanSize, "32. b")
	assertSuccessEquals(t, 32, FromHumanSize, "32. B")

	// We do not tolerate extra leading or trailing spaces
	// (except for a space after the number and a missing suffix).
	assertSuccessEquals(t, 0, FromHumanSize, "0 ")

	assertError(t, FromHumanSize, " 0")
	assertError(t, FromHumanSize, " 0b")
	assertError(t, FromHumanSize, " 0B")
	assertError(t, FromHumanSize, " 0 B")
	assertError(t, FromHumanSize, "0b ")
	assertError(t, FromHumanSize, "0B ")
	assertError(t, FromHumanSize, "0 B ")

	assertError(t, FromHumanSize, "")
	assertError(t, FromHumanSize, "hello")
	assertError(t, FromHumanSize, ".")
	assertError(t, FromHumanSize, ". ")
	assertError(t, FromHumanSize, " ")
	assertError(t, FromHumanSize, "  ")
	assertError(t, FromHumanSize, " .")
	assertError(t, FromHumanSize, " . ")
	assertError(t, FromHumanSize, "-32")
	assertError(t, FromHumanSize, "-32b")
	assertError(t, FromHumanSize, "-32B")
	assertError(t, FromHumanSize, "-32 b")
	assertError(t, FromHumanSize, "-32 B")
	assertError(t, FromHumanSize, "32b.")
	assertError(t, FromHumanSize, "32B.")
	assertError(t, FromHumanSize, "32 b.")
	assertError(t, FromHumanSize, "32 B.")
	assertError(t, FromHumanSize, "32 bb")
	assertError(t, FromHumanSize, "32 BB")
	assertError(t, FromHumanSize, "32 b b")
	assertError(t, FromHumanSize, "32 B B")
	assertError(t, FromHumanSize, "32  b")
	assertError(t, FromHumanSize, "32  B")
	assertError(t, FromHumanSize, " 32 ")
	assertError(t, FromHumanSize, "32m b")
	assertError(t, FromHumanSize, "32bm")
}

func TestRAMInBytes(t *testing.T) {
	assertSuccessEquals(t, 32, RAMInBytes, "32")
	assertSuccessEquals(t, 32, RAMInBytes, "32b")
	assertSuccessEquals(t, 32, RAMInBytes, "32B")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kib")
	assertSuccessEquals(t, 32*KiB, RAMInBytes, "32KIB")
	assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb")
	assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb")
	assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb")
	assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb")
	assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB")
	assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P")

	assertSuccessEquals(t, 32, RAMInBytes, "32.3")
	tmp := 32.3 * MiB
	assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb")
	tmp = 0.3 * MiB
	assertSuccessEquals(t, int64(tmp), RAMInBytes, "0.3MB")

	assertError(t, RAMInBytes, "")
	assertError(t, RAMInBytes, "hello")
	assertError(t, RAMInBytes, "-32")
	assertError(t, RAMInBytes, " 32 ")
	assertError(t, RAMInBytes, "32m b")
	assertError(t, RAMInBytes, "32bm")
}

func BenchmarkParseSize(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, s := range []string{
			"", "32", "32b", "32 B", "32k", "32.5 K", "32kb", "32 Kb",
			"32.8Mb", "32.9Gb", "32.777Tb", "32Pb", "0.3Mb", "-1",
		} {
			FromHumanSize(s)
			RAMInBytes(s)
		}
	}
}

func assertEquals(t *testing.T, expected, actual interface{}) {
	t.Helper()
	if expected != actual {
		t.Errorf("Expected '%v' but got '%v'", expected, actual)
	}
}

// func that maps to the parse function signatures as testing abstraction
type parseFn func(string) (int64, error)

// Define 'String()' for pretty-print
func (fn parseFn) String() string {
	fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
	return fnName[strings.LastIndex(fnName, ".")+1:]
}

func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
	t.Helper()
	res, err := fn(arg)
	if err != nil || res != expected {
		t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err)
	}
}

func assertError(t *testing.T, fn parseFn, arg string) {
	t.Helper()
	res, err := fn(arg)
	if err == nil && res != -1 {
		t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
	}
}


================================================
FILE: debug.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
	"errors"
	"fmt"
)

// The following values are defined for the Type field of the debug directory entry:
const (
	// An unknown value that is ignored by all tools.
	ImageDebugTypeUnknown = 0

	// The COFF debug information (line numbers, symbol table, and string table).
	// This type of debug information is also pointed to by fields in the file headers.
	ImageDebugTypeCOFF = 1

	// The Visual C++ debug information.
	ImageDebugTypeCodeView = 2

	// The frame pointer omission (FPO) information. This information tells the
	// debugger how to interpret nonstandard stack frames, which use the EBP
	// register for a purpose other than as a frame pointer.
	ImageDebugTypeFPO = 3

	// The location of DBG file.
	ImageDebugTypeMisc = 4

	// A copy of .pdata section.
	ImageDebugTypeException = 5

	// Reserved.
	ImageDebugTypeFixup = 6

	// The mapping from an RVA in image to an RVA in source image.
	ImageDebugTypeOMAPToSrc = 7

	// The mapping from an RVA in source image to an RVA in image.
	ImageDebugTypeOMAPFromSrc = 8

	// Reserved for Borland.
	ImageDebugTypeBorland = 9

	// Reserved.
	ImageDebugTypeReserved = 10

	// Reserved.
	ImageDebugTypeCLSID = 11

	// Visual C++ features (/GS counts /sdl counts and guardN counts).
	ImageDebugTypeVCFeature = 12

	// Pogo aka PGO aka Profile Guided Optimization.
	ImageDebugTypePOGO = 13

	// Incremental Link Time Code Generation (iLTCG).
	ImageDebugTypeILTCG = 14

	// Intel MPX.
	ImageDebugTypeMPX = 15

	// PE determinism or reproducibility.
	ImageDebugTypeRepro = 16

	// Extended DLL characteristics bits.
	ImageDebugTypeExDllCharacteristics = 20
)

const (
	// CVSignatureRSDS represents the CodeView signature 'SDSR'.
	CVSignatureRSDS = 0x53445352

	// CVSignatureNB10 represents the CodeView signature 'NB10'.
	CVSignatureNB10 = 0x3031424e
)

const (
	// FrameFPO indicates a frame of type FPO.
	FrameFPO = 0x0

	// FrameTrap indicates a frame of type Trap.
	FrameTrap = 0x1

	// FrameTSS indicates a frame of type TSS.
	FrameTSS = 0x2

	// FrameNonFPO indicates a frame of type Non-FPO.
	FrameNonFPO = 0x3
)

// DllCharacteristicsExType represents a DLL Characteristics type.
type DllCharacteristicsExType uint32

const (
	// ImageDllCharacteristicsExCETCompat indicates that the image is CET
	// compatible.
	ImageDllCharacteristicsExCETCompat = 0x0001
)

const (
	// POGOTypePGU represents a signature for an undocumented PGO sub type.
	POGOTypePGU = 0x50475500
	// POGOTypePGI represents a signature for an undocumented PGO sub type.
	POGOTypePGI = 0x50474900
	// POGOTypePGO represents a signature for an undocumented PGO sub type.
	POGOTypePGO = 0x50474F00
	// POGOTypeLTCG represents a signature for an undocumented PGO sub type.
	POGOTypeLTCG = 0x4c544347
)

// ImageDebugDirectoryType represents the type of a debug directory.
type ImageDebugDirectoryType uint32

// ImageDebugDirectory represents the IMAGE_DEBUG_DIRECTORY structure.
// This directory indicates what form of debug information is present
// and where it is. This directory consists of an array of debug directory
// entries whose location and size are indicated in the image optional header.
type ImageDebugDirectory struct {
	// Reserved, must be 0.
	Characteristics uint32 `json:"characteristics"`

	// The time and date that the debug data was created.
	TimeDateStamp uint32 `json:"time_date_stamp"`

	// The major version number of the debug data format.
	MajorVersion uint16 `json:"major_version"`

	// The minor version number of the debug data format.
	MinorVersion uint16 `json:"minor_version"`

	// The format of debugging information. This field enables support of
	// multiple debuggers.
	Type ImageDebugDirectoryType `json:"type"`

	// The size of the debug data (not including the debug directory itself).
	SizeOfData uint32 `json:"size_of_data"`

	//The address of the debug data when loaded, relative to the image base.
	AddressOfRawData uint32 `json:"address_of_raw_data"`

	// The file pointer to the debug data.
	PointerToRawData uint32 `json:"pointer_to_raw_data"`
}

// DebugEntry wraps ImageDebugDirectory to include debug directory type.
type DebugEntry struct {
	// Points to the image debug entry structure.
	Struct ImageDebugDirectory `json:"struct"`

	// Holds specific information about the debug type entry.
	Info interface{} `json:"info"`

	// Type of the debug entry.
	Type string `json:"type"`
}

// GUID is a 128-bit value consisting of one group of 8 hexadecimal digits,
// followed by three groups of 4 hexadecimal digits each, followed by one
// group of 12 hexadecimal digits.
type GUID struct {
	Data1 uint32
	Data2 uint16
	Data3 uint16
	Data4 [8]byte
}

// CVSignature represents a CodeView signature.
type CVSignature uint32

// CVInfoPDB70 represents the the CodeView data block of a PDB 7.0 file.
type CVInfoPDB70 struct {
	// CodeView signature, equal to `RSDS`.
	CVSignature CVSignature `json:"cv_signature"`

	// A unique identifier, which changes with every rebuild of the executable and PDB file.
	Signature GUID `json:"signature"`

	// Ever-incrementing value, which is initially set to 1 and incremented every
	// time when a part of the PDB file is updated without rewriting the whole file.
	Age uint32 `json:"age"`

	// Null-terminated name of the PDB file. It can also contain full or partial
	// path to the file.
	PDBFileName string `json:"pdb_file_name"`
}

// CVHeader represents the the CodeView header struct to the PDB 2.0 file.
type CVHeader struct {
	// CodeView signature, equal to `NB10`.
	Signature CVSignature `json:"signature"`

	// CodeView offset. Set to 0, because debug information is stored in a
	// separate file.
	Offset uint32 `json:"offset"`
}

// CVInfoPDB20 represents the the CodeView data block of a PDB 2.0 file.
type CVInfoPDB20 struct {
	// Points to the CodeView header structure.
	CVHeader CVHeader `json:"cv_header"`

	// The time when debug information was created (in seconds since 01.01.1970).
	Signature uint32 `json:"signature"`

	// Ever-incrementing value, which is initially set to 1 and incremented every
	// time when a part of the PDB file is updated without rewriting the whole file.
	Age uint32 `json:"age"`

	// Null-terminated name of the PDB file. It can also contain full or partial
	// path to the file.
	PDBFileName string `json:"pdb_file_name"`
}

// FPOFrameType represents the type of a FPO frame.
type FPOFrameType uint8

// FPOData represents the stack frame layout for a function on an x86 computer when
// frame pointer omission (FPO) optimization is used. The structure is used to locate
// the base of the call frame.
type FPOData struct {
	// The offset of the first byte of the function code.
	OffsetStart uint32 `json:"offset_start"`

	// The number of bytes in the function.
	ProcSize uint32 `json:"proc_size"`

	// The number of local variables.
	NumLocals uint32 `json:"num_locals"`

	// The size of the parameters, in DWORDs.
	ParamsSize uint16 `json:"params_size"`

	// The number of bytes in the function prolog code.
	PrologLength uint8 `json:"prolog_length"`

	// The number of registers saved.
	SavedRegsCount uint8 `json:"saved_regs_count"`

	// A variable that indicates whether the function uses structured exception handling.
	HasSEH uint8 `json:"has_seh"`

	// A variable that indicates whether the EBP register has been allocated.
	UseBP uint8 `json:"use_bp"`

	// Reserved for future use.
	Reserved uint8 `json:"reserved"`

	// A variable that indicates the frame type.
	FrameType FPOFrameType `json:"frame_type"`
}

// ImagePGOItem represents the _IMAGE_POGO_INFO structure.
type ImagePGOItem struct {
	RVA  uint32 `json:"rva"`
	Size uint32 `json:"size"`
	Name string `json:"name"`
}

// POGOType represents a POGO type.
type POGOType uint32

// POGO structure contains information related to the Profile Guided Optimization.
// PGO is an approach to optimization where the compiler uses profile information
// to make better optimization decisions for the program.
type POGO struct {
	// Signature represents the PGO sub type.
	Signature POGOType       `json:"signature"`
	Entries   []ImagePGOItem `json:"entries"`
}

type VCFeature struct {
	PreVC11 uint32 `json:"pre_vc11"`
	CCpp    uint32 `json:"C/C++"`
	Gs      uint32 `json:"/GS"`
	Sdl     uint32 `json:"/sdl"`
	GuardN  uint32 `json:"guardN"`
}

type REPRO struct {
	Size uint32 `json:"size"`
	Hash []byte `json:"hash"`
}

// ImageDebugMisc represents the IMAGE_DEBUG_MISC structure.
type ImageDebugMisc struct {
	// The type of data carried in the `Data` field.
	DataType uint32 `json:"data_type"`

	// The length of this structure in bytes, including the entire Data field
	// and its NUL terminator (rounded to four byte multiple.)
	Length uint32 `json:"length"`

	// The encoding of the Data field. True if data is unicode string.
	Unicode bool `json:"unicode"`

	// Reserved.
	Reserved [3]byte `json:"reserved"`

	// Actual data.
	Data string `json:"data"`
}

// Image files contain an optional debug directory that indicates what form of
// debug information is present and where it is. This directory consists of an
// array of debug directory entries whose location and size are indicated in the
// image optional header.  The debug directory can be in a discardable .debug
// section (if one exists), or it can be included in any other section in the
// image file, or not be in a section at all.
func (pe *File) parseDebugDirectory(rva, size uint32) error {

	debugEntry := DebugEntry{}
	debugDir := ImageDebugDirectory{}
	errorMsg := fmt.Sprintf("Invalid debug information. Can't read data at RVA: 0x%x", rva)
	debugDirSize := uint32(binary.Size(debugDir))
	debugDirsCount := size / debugDirSize

	for i := uint32(0); i < debugDirsCount; i++ {
		offset := pe.GetOffsetFromRva(rva + debugDirSize*i)
		err := pe.structUnpack(&debugDir, offset, debugDirSize)
		if err != nil {
			return errors.New(errorMsg)
		}

		switch debugDir.Type {
		case ImageDebugTypeCodeView:
			debugSignature, err := pe.ReadUint32(debugDir.PointerToRawData)
			if err != nil {
				continue
			}

			if debugSignature == CVSignatureRSDS {
				// PDB 7.0
				pdb := CVInfoPDB70{CVSignature: CVSignatureRSDS}

				// Extract the GUID.
				offset := debugDir.PointerToRawData + 4
				guidSize := uint32(binary.Size(pdb.Signature))
				err = pe.structUnpack(&pdb.Signature, offset, guidSize)
				if err != nil {
					continue
				}

				// Extract the age.
				offset += guidSize
				pdb.Age, err = pe.ReadUint32(offset)
				if err != nil {
					continue
				}
				offset += 4

				// PDB file name.
				pdbFilenameSize := debugDir.SizeOfData - 24 - 1

				// pdbFileName_size can be negative here, as seen in the malware
				// sample with MD5 hash: 7c297600870d026c014d42596bb9b5fd
				// Checking for positive size here to ensure proper parsing.
				if pdbFilenameSize > 0 {
					pdbFilename := make([]byte, pdbFilenameSize)
					err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize)
					if err != nil {
						continue
					}
					pdb.PDBFileName = string(pdbFilename)
				}

				// Include these extra information.
				debugEntry.Info = pdb

			} else if debugSignature == CVSignatureNB10 {
				// PDB 2.0.
				cvHeader := CVHeader{}
				offset := debugDir.PointerToRawData
				err = pe.structUnpack(&cvHeader, offset, size)
				if err != nil {
					continue
				}

				pdb := CVInfoPDB20{CVHeader: cvHeader}

				// Extract the signature.
				pdb.Signature, err = pe.ReadUint32(offset + 8)
				if err != nil {
					continue
				}

				// Extract the age.
				pdb.Age, err = pe.ReadUint32(offset + 12)
				if err != nil {
					continue
				}
				offset += 16

				pdbFilenameSize := debugDir.SizeOfData - 16 - 1
				if pdbFilenameSize > 0 {
					pdbFilename := make([]byte, pdbFilenameSize)
					err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize)
					if err != nil {
						continue
					}
					pdb.PDBFileName = string(pdbFilename)
				}

				// Include these extra information.
				debugEntry.Info = pdb
			}
		case ImageDebugTypePOGO:
			pogoSignature, err := pe.ReadUint32(debugDir.PointerToRawData)
			if err != nil {
				continue
			}

			pogo := POGO{}

			switch pogoSignature {
			case 0x0, POGOTypePGU, POGOTypePGI, POGOTypePGO, POGOTypeLTCG:
				// TODO: Some files like 00da1a2a9d9ebf447508bf6550f05f466f8eabb4ed6c4f2a524c0769b2d75bc1
				// have a POGO signature of 0x0. To be reverse engineered.
				pogo.Signature = POGOType(pogoSignature)
				offset = debugDir.PointerToRawData + 4
				c := uint32(0)
				for c < debugDir.SizeOfData-4 {
					pogoEntry := ImagePGOItem{}
					pogoEntry.RVA, err = pe.ReadUint32(offset)
					if err != nil {
						break
					}
					offset += 4

					pogoEntry.Size, err = pe.ReadUint32(offset)
					if err != nil {
						break
					}
					offset += 4

					pogoEntry.Name = string(pe.GetStringFromData(0, pe.data[offset:offset+64]))

					pogo.Entries = append(pogo.Entries, pogoEntry)
					offset += uint32(len(pogoEntry.Name))

					// Make sure offset is aligned to 4 bytes.
					padding := 4 - (offset % 4)
					c += 4 + 4 + uint32(len(pogoEntry.Name)) + padding
					offset += padding
				}

				debugEntry.Info = pogo
			}
		case ImageDebugTypeVCFeature:
			vcf := VCFeature{}
			size := uint32(binary.Size(vcf))
			err := pe.structUnpack(&vcf, debugDir.PointerToRawData, size)
			if err != nil {
				continue
			}
			debugEntry.Info = vcf
		case ImageDebugTypeRepro:
			repro := REPRO{}
			offset := debugDir.PointerToRawData

			// Extract the size.
			repro.Size, err = pe.ReadUint32(offset)
			if err != nil {
				continue
			}

			// Extract the hash.
			repro.Hash, err = pe.ReadBytesAtOffset(offset+4, repro.Size)
			if err != nil {
				continue
			}
			debugEntry.Info = repro
		case ImageDebugTypeFPO:
			offset := debugDir.PointerToRawData
			size := uint32(16)
			fpoEntries := []FPOData{}
			c := uint32(0)
			for c < debugDir.SizeOfData {
				fpo := FPOData{}
				fpo.OffsetStart, err = pe.ReadUint32(offset)
				if err != nil {
					break
				}

				fpo.ProcSize, err = pe.ReadUint32(offset + 4)
				if err != nil {
					break
				}

				fpo.NumLocals, err = pe.ReadUint32(offset + 8)
				if err != nil {
					break
				}

				fpo.ParamsSize, err = pe.ReadUint16(offset + 12)
				if err != nil {
					break
				}

				fpo.PrologLength, err = pe.ReadUint8(offset + 14)
				if err != nil {
					break
				}

				attributes, err := pe.ReadUint16(offset + 15)
				if err != nil {
					break
				}

				//
				// UChar  cbRegs :3;  /* # regs saved */
				// UChar  fHasSEH:1;  /* Structured Exception Handling */
				// UChar  fUseBP :1;  /* EBP has been used */
				// UChar  reserved:1;
				// UChar  cbFrame:2;  /* frame type */
				//

				// The lowest 3 bits
				fpo.SavedRegsCount = uint8(attributes & 0x7)

				// The next bit.
				fpo.HasSEH = uint8(attributes & 0x8 >> 3)

				// The next bit.
				fpo.UseBP = uint8(attributes & 0x10 >> 4)

				// The next bit.
				fpo.Reserved = uint8(attributes & 0x20 >> 5)

				// The next 2 bits.
				fpo.FrameType = FPOFrameType(attributes & 0xC0 >> 6)

				fpoEntries = append(fpoEntries, fpo)
				c += size
				offset += 16
			}
			debugEntry.Info = fpoEntries
		case ImageDebugTypeExDllCharacteristics:
			exDllChar, err := pe.ReadUint32(debugDir.PointerToRawData)
			if err != nil {
				continue
			}

			debugEntry.Info = DllCharacteristicsExType(exDllChar)
		}

		debugEntry.Struct = debugDir
		debugEntry.Type = debugDir.Type.String()
		pe.Debugs = append(pe.Debugs, debugEntry)
	}

	if len(pe.Debugs) > 0 {
		pe.HasDebug = true
	}

	return nil
}

// SectionAttributeDescription maps a section attribute to a friendly name.
func SectionAttributeDescription(section string) string {
	sectionNameMap := map[string]string{
		".00cfg":                               "CFG Check Functions Pointers",
		".bss$00":                              "Uninit.data in phaseN of Pri7",
		".bss$dk00":                            "PGI: Uninit.data may be not const",
		".bss$dk01":                            "PGI: Uninit.data may be not const",
		".bss$pr00":                            "PGI: Uninit.data only for read",
		".bss$pr03":                            "PGI: Uninit.data only for read",
		".bss$zz":                              "PGO: Dead uninit.data",
		".CRT$XCA":                             "First C++ Initializer",
		".CRT$XCZ":                             "Last C++ Initializer",
		".xdata$x":                             "EH data",
		".gfids$y":                             "CFG Functions table",
		".CRT$XCAA":                            "Startup C++ Initializer",
		".CRT$XCC":                             "Global initializer: init_seg(compiler)",
		".CRT$XCL":                             "Global initializer: init_seg(lib)",
		".CRT$XCU":                             "Global initializer: init_seg(user)",
		".CRT$XDA":                             "First Dynamic TLS Initializer",
		".CRT$XDZ":                             "Last Dynamic TLS Initializer",
		".CRT$XIA":                             "First C Initializer",
		".CRT$XIAA":                            "Startup C Initializer",
		".CRT$XIAB":                            "PGO C Initializer",
		".CRT$XIAC":                            "Post-PGO C Initializer",
		".CRT$XIC":                             "CRT C Initializers",
		".CRT$XIYA":                            "VCCorLib Threading Model Initializer",
		".CRT$XIYAA":                           "XAML Designer Threading Model Override Initializer",
		".CRT$XIYB":                            "VCCorLib Main Initializer",
		".CRT$XIZ":                             "Last C Initializer",
		".CRT$XLA":                             "First Loader TLS Callback",
		".CRT$XLC":                             "CRT TLS Constructor",
		".CRT$XLD":                             "CRT TLS Terminator",
		".CRT$XLZ":                             "Last Loader TLS Callback",
		".CRT$XPA":                             "First Pre-Terminator",
		".CRT$XPB":                             "CRT ConcRT Pre-Terminator",
		".CRT$XPX":                             "CRT Pre-Terminators",
		".CRT$XPXA":                            "CRT stdio Pre-Terminator",
		".CRT$XPZ":                             "Last Pre-Terminator",
		".CRT$XTA":                             "First Terminator",
		".CRT$XTZ":                             "Last Terminator",
		".CRTMA$XCA":                           "First Managed C++ Initializer",
		".CRTMA$XCZ":                           "Last Managed C++ Initializer",
		".CRTVT$XCA":                           "First Managed VTable Initializer",
		".CRTVT$XCZ":                           "Last Managed VTable Initializer",
		".data$00":                             "Init.data in phaseN of Pri7",
		".data$dk00":                           "PGI: Init.data may be not const",
		".data$dk00$brc":                       "PGI: Init.data may be not const",
		".data$pr00":                           "PGI: Init.data only for read",
		".data$r":                              "RTTI Type Descriptors",
		".data$zz":                             "PGO: Dead init.data",
		".data$zz$brc":                         "PGO: Dead init.data",
		".didat$2":                             "Delay Import Descriptors",
		".didat$3":                             "Delay Import Final NULL Entry",
		".didat$4":                             "Delay Import INT",
		".didat$5":                             "Delay Import IAT",
		".didat$6":                             "Delay Import Symbol Names",
		".didat$7":                             "Delay Import Bound IAT",
		".edata":                               "Export Table",
		".gehcont":                             "CFG EHCont Table",
		".gfids":                               "CFG Functions Table",
		".giats":                               "CFG IAT Table",
		".idata$2":                             "Import Descriptors",
		".idata$3":                             "Import Final NULL Entry",
		".idata$4":                             "Import Names Table",
		".idata$5":                             "Import Addresses Table",
		".idata$6":                             "Import Symbol and DLL Names",
		".pdata":                               "Procedure data",
		".rdata$00":                            "Readonly data in phaseN of Pri7",
		".rdata$00$brc":                        "Readonly data in phaseN of Pri7",
		".rdata$09":                            "Readonly data in phaseN of Pri7",
		".rdata$brc":                           "BaseRelocation Clustering",
		".rdata$r":                             "RTTI Data",
		".rdata$sxdata":                        "Safe SEH",
		".rdata$T":                             "TLS Header",
		".rdata$zETW0":                         "ETW Metadata Header",
		".rdata$zETW1":                         "ETW Events Metadata",
		".rdata$zETW2":                         "ETW Providers Metadata",
		".rdata$zETW9":                         "ETW Metadata Footer",
		".rdata$zz":                            "PGO: Dead Readonly Data",
		".rdata$zz$brc":                        "PGO: Dead Readonly Data",
		".rdata$zzzdbg":                        "Debug directory data",
		".rsrc$01":                             "Resources Header",
		".rsrc$02":                             "Resources Data",
		".rtc$IAA":                             "First RTC Initializer",
		".rtc$IZZ":                             "Last RTC Initializer",
		".rtc$TAA":                             "First RTC Terminator",
		".rtc$TZZ":                             "Last RTC Terminator",
		".text$di":                             "MSVC Dynamic Initializers",
		".text$lp00kernel32.dll!20_pri7":       "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp01kernel32.dll!20_pri7":       "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp03kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp04kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp08kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp09kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
		".text$lp10kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
		".text$mn":                             "Contains EP",
		".text$mn$00":                          "CFG Dispatching",
		".text$np":                             "PGO: __asm or disabled via pragma",
		".text$x":                              "EH Filters",
		".text$yd":                             "MSVC Destructors",
		".text$zy":                             "PGO: Dead Code Blocks",
		".text$zz":                             "PGO: Dead Whole Functions",
		".xdata":                               "Unwind data",
	}

	if val, ok := sectionNameMap[section]; ok {
		return val
	}

	return ""
}

// String returns a string interpretation of the FPO frame type.
func (ft FPOFrameType) String() string {
	frameTypeMap := map[FPOFrameType]string{
		FrameFPO:    "FPO",
		FrameTrap:   "Trap",
		FrameTSS:    "TSS",
		FrameNonFPO: "Non FPO",
	}

	v, ok := frameTypeMap[ft]
	if ok {
		return v
	}

	return "?"
}

// String returns the string representation of a GUID.
func (g GUID) String() string {
	return fmt.Sprintf("{%06X-%04X-%04X-%04X-%X}", g.Data1, g.Data2, g.Data3, g.Data4[0:2], g.Data4[2:])
}

// String returns the string representation of a debug entry type.
func (t ImageDebugDirectoryType) String() string {

	debugTypeMap := map[ImageDebugDirectoryType]string{
		ImageDebugTypeUnknown:              "Unknown",
		ImageDebugTypeCOFF:                 "COFF",
		ImageDebugTypeCodeView:             "CodeView",
		ImageDebugTypeFPO:                  "FPO",
		ImageDebugTypeMisc:                 "Misc",
		ImageDebugTypeException:            "Exception",
		ImageDebugTypeFixup:                "Fixup",
		ImageDebugTypeOMAPToSrc:            "OMAP To Src",
		ImageDebugTypeOMAPFromSrc:          "OMAP From Src",
		ImageDebugTypeBorland:              "Borland",
		ImageDebugTypeReserved:             "Reserved",
		ImageDebugTypeVCFeature:            "VC Feature",
		ImageDebugTypePOGO:                 "POGO",
		ImageDebugTypeILTCG:                "iLTCG",
		ImageDebugTypeMPX:                  "MPX",
		ImageDebugTypeRepro:                "REPRO",
		ImageDebugTypeExDllCharacteristics: "Ex.DLL Characteristics",
	}

	v, ok := debugTypeMap[t]
	if ok {
		return v
	}

	return "?"
}

// String returns a string interpretation of a POGO type.
func (p POGOType) String() string {
	pogoTypeMap := map[POGOType]string{
		POGOTypePGU:  "PGU",
		POGOTypePGI:  "PGI",
		POGOTypePGO:  "PGO",
		POGOTypeLTCG: "LTCG",
	}

	v, ok := pogoTypeMap[p]
	if ok {
		return v
	}

	return "?"
}

// String returns a string interpretation of a CodeView signature.
func (s CVSignature) String() string {
	cvSignatureMap := map[CVSignature]string{
		CVSignatureRSDS: "RSDS",
		CVSignatureNB10: "NB10",
	}

	v, ok := cvSignatureMap[s]
	if ok {
		return v
	}

	return "?"
}

// String returns a string interpretation of Dll Characteristics Ex.
func (flag DllCharacteristicsExType) String() string {
	dllCharacteristicsExTypeMap := map[DllCharacteristicsExType]string{
		ImageDllCharacteristicsExCETCompat: "CET Compatible",
	}

	v, ok := dllCharacteristicsExTypeMap[flag]
	if ok {
		return v
	}

	return "?"
}


================================================
FILE: debug_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"reflect"
	"testing"
)

type TestDebugIn struct {
	filepath string
	index    int // debug entry index
}

func TestDebugDirectoryCodeView(t *testing.T) {

	type TestCodeView struct {
		debugEntry DebugEntry
		signature  string
	}

	tests := []struct {
		in  TestDebugIn
		out TestCodeView
	}{
		{
			TestDebugIn{
				index:    0,
				filepath: getAbsoluteFilePath("test/kernel32.dll"),
			},
			TestCodeView{
				debugEntry: DebugEntry{
					Struct: ImageDebugDirectory{
						Characteristics:  0x0,
						TimeDateStamp:    0x38b369c4,
						MajorVersion:     0x0,
						MinorVersion:     0x0,
						Type:             0x2,
						SizeOfData:       0x25,
						AddressOfRawData: 0x932f0,
						PointerToRawData: 0x91cf0,
					},
					Info: CVInfoPDB70{
						CVSignature: 0x53445352,
						Signature: GUID{
							Data1: 0xdbe09e71,
							Data2: 0xb370,
							Data3: 0x9cb7,
							Data4: [8]byte{34, 197, 94, 85, 115, 250, 123, 225},
						},
						Age:         0x1,
						PDBFileName: "kernel32.pdb",
					},
					Type: "CodeView",
				},
				signature: "RSDS",
			},
		},
		{
			TestDebugIn{
				index:    0,
				filepath: getAbsoluteFilePath("test/01008963d32f5cc17b64c31446386ee5b36a7eab6761df87a2989ba9394d8f3d"),
			},
			TestCodeView{
				debugEntry: DebugEntry{
					Struct: ImageDebugDirectory{
						Characteristics:  0x0,
						TimeDateStamp:    0x3b7d84d4,
						MajorVersion:     0x0,
						MinorVersion:     0x0,
						Type:             0x2,
						SizeOfData:       0x1d,
						AddressOfRawData: 0x1cf4,
						PointerToRawData: 0x10f4,
					},
					Info: CVInfoPDB20{
						CVHeader: CVHeader{
							Signature: 0x3031424e,
							Offset:    0x0,
						},
						Signature:   0x3b7d84d4,
						Age:         0x1,
						PDBFileName: "routemon.pdb",
					},
					Type: "CodeView",
				},
				signature: "NB10",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
					tt.in.filepath, err)
			}

			debugEntry := file.Debugs[tt.in.index]
			if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
				t.Fatalf("debug entry assertion failed, got %v, want %v",
					debugEntry, tt.out.debugEntry)
			}

			cvSignature := ""
			switch debugEntry.Info.(type) {
			case CVInfoPDB70:
				cvSignature = debugEntry.Info.(CVInfoPDB70).CVSignature.String()
			case CVInfoPDB20:
				cvSignature = debugEntry.Info.(CVInfoPDB20).CVHeader.Signature.String()
			}
			if cvSignature != tt.out.signature {
				t.Fatalf("debug CV signature assertion failed, got %v, want %v",
					cvSignature, tt.out.signature)
			}
		})
	}
}

func TestDebugDirectoryPOGO(t *testing.T) {

	type TestPOGO struct {
		imgDebugEntry ImageDebugDirectory
		entriesCount  int
		debugType     string
		POGOItemIndex int
		POGOItem      ImagePGOItem
		POGOSignature string
	}

	tests := []struct {
		in  TestDebugIn
		out TestPOGO
	}{
		{
			TestDebugIn{
				index:    1,
				filepath: getAbsoluteFilePath("test/kernel32.dll"),
			},
			TestPOGO{
				imgDebugEntry: ImageDebugDirectory{
					Characteristics:  0x0,
					TimeDateStamp:    0x38b369c4,
					MajorVersion:     0x0,
					MinorVersion:     0x0,
					Type:             0xd,
					SizeOfData:       0x574,
					AddressOfRawData: 0x93318,
					PointerToRawData: 0x91d18,
				},
				debugType:     "POGO",
				entriesCount:  60,
				POGOItemIndex: 0,
				POGOItem: ImagePGOItem{
					RVA:  0x1000,
					Size: 0x280,
					Name: ".text$lp00kernel32.dll!20_pri7",
				},
				POGOSignature: "PGU",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v", tt.in.filepath, err)
			}

			imgDebugEntry := file.Debugs[tt.in.index].Struct
			if !reflect.DeepEqual(imgDebugEntry, tt.out.imgDebugEntry) {
				t.Fatalf("debug entry assertion failed, got %v, want %v",
					imgDebugEntry, tt.out.imgDebugEntry)
			}

			debugTypeString := file.Debugs[tt.in.index].Type
			if debugTypeString != tt.out.debugType {
				t.Fatalf("debug type assertion failed, got %v, want %v",
					debugTypeString, tt.out.debugType)
			}

			pogo := file.Debugs[tt.in.index].Info.(POGO)
			entriesCount := len(pogo.Entries)
			if entriesCount != tt.out.entriesCount {
				t.Fatalf("debug entry count failed, got %v, want %v",
					entriesCount, tt.out.entriesCount)
			}

			pogoItem := pogo.Entries[tt.out.POGOItemIndex]
			if !reflect.DeepEqual(pogoItem, tt.out.POGOItem) {
				t.Fatalf("debug pogo entry assertion failed, got %v, want %v",
					pogoItem, tt.out.POGOItemIndex)
			}

			pogoItemSignature := pogo.Signature.String()
			if pogoItemSignature != tt.out.POGOSignature {
				t.Fatalf("debug pogo signature string assertion failed, got %v, want %v",
					pogoItemSignature, tt.out.POGOSignature)
			}
		})
	}
}

func TestDebugDirectoryREPRO(t *testing.T) {

	type TestREPRO struct {
		debugType  string
		debugEntry DebugEntry
	}

	tests := []struct {
		in  TestDebugIn
		out TestREPRO
	}{

		{
			TestDebugIn{
				index:    2,
				filepath: getAbsoluteFilePath("test/kernel32.dll"),
			},
			TestREPRO{
				debugEntry: DebugEntry{
					Struct: ImageDebugDirectory{
						Characteristics:  0x0,
						TimeDateStamp:    0x38b369c4,
						MajorVersion:     0x0,
						MinorVersion:     0x0,
						Type:             0x10,
						SizeOfData:       0x24,
						AddressOfRawData: 0x9388c,
						PointerToRawData: 0x9228c,
					},
					Info: REPRO{
						Size: 0x20,
						Hash: []byte{113, 158, 224, 219, 112, 179, 183, 156, 34, 197, 94, 85, 115, 250, 123, 225, 130,
							247, 187, 89, 220, 154, 207, 99, 80, 113, 179, 171, 196, 105, 179, 56},
					},

					Type: "REPRO",
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
					tt.in.filepath, err)
			}

			debugEntry := file.Debugs[tt.in.index]
			if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
				t.Fatalf("debug entry assertion failed, got %v, want %v",
					debugEntry, tt.out.debugEntry)
			}

		})
	}
}

func TestDebugDirectoryExDLLCharacteristics(t *testing.T) {

	type TestExDLLCharacteristics struct {
		debugEntry           DebugEntry
		exDLLCharacteristics string
	}

	tests := []struct {
		in  TestDebugIn
		out TestExDLLCharacteristics
	}{
		{
			TestDebugIn{
				index:    3,
				filepath: getAbsoluteFilePath("test/kernel32.dll"),
			},
			TestExDLLCharacteristics{
				debugEntry: DebugEntry{
					Struct: ImageDebugDirectory{
						Characteristics:  0x0,
						TimeDateStamp:    0x38b369c4,
						MajorVersion:     0x0,
						MinorVersion:     0x0,
						Type:             0x14,
						SizeOfData:       0x4,
						AddressOfRawData: 0x938b0,
						PointerToRawData: 0x922b0,
					},
					Info: DllCharacteristicsExType(0x1),
					Type: "Ex.DLL Characteristics",
				},
				exDLLCharacteristics: "CET Compatible",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
					tt.in.filepath, err)
			}

			debugEntry := file.Debugs[tt.in.index]
			if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
				t.Fatalf("debug entry assertion failed, got %v, want %v",
					debugEntry, tt.out.debugEntry)
			}

			dllCharacteristicsExString := debugEntry.Info.(DllCharacteristicsExType).String()
			if dllCharacteristicsExString != tt.out.exDLLCharacteristics {
				t.Fatalf("debug entry DllCharacteristicsEx string assertion failed, got %v, want %v",
					dllCharacteristicsExString, tt.out.exDLLCharacteristics)
			}
		})
	}
}

func TestDebugDirectoryVCFeature(t *testing.T) {

	type TestVCFeature struct {
		debugEntry DebugEntry
	}

	tests := []struct {
		in  TestDebugIn
		out TestVCFeature
	}{
		{
			TestDebugIn{
				index:    1,
				filepath: getAbsoluteFilePath("test/00da1a2a9d9ebf447508bf6550f05f466f8eabb4ed6c4f2a524c0769b2d75bc1"),
			},
			TestVCFeature{
				debugEntry: DebugEntry{
					Struct: ImageDebugDirectory{
						Characteristics:  0x0,
						TimeDateStamp:    0x5ef47ea0,
						MajorVersion:     0x0,
						MinorVersion:     0x0,
						Type:             0xc,
						SizeOfData:       0x14,
						AddressOfRawData: 0x39d58,
						PointerToRawData: 0x39158,
					},
					Info: VCFeature{
						PreVC11: 0xa,
						CCpp:    0x115,
						Gs:      0xe4,
						Sdl:     0x0,
						GuardN:  0x115,
					},
					Type: "VC Feature",
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
					tt.in.filepath, err)
			}

			debugEntry := file.Debugs[tt.in.index]
			if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
				t.Fatalf("debug entry assertion failed, got %+v, want %+v",
					debugEntry, tt.out.debugEntry)
			}

		})
	}
}

func TestDebugDirectoryFPO(t *testing.T) {

	type TestFPO struct {
		imgDebugEntry ImageDebugDirectory
		entriesCount  int
		debugType     string
		FPODataIndex  int
		FPOData       FPOData
		FPOFrameType  string
	}

	tests := []struct {
		in  TestDebugIn
		out TestFPO
	}{
		{
			TestDebugIn{
				index:    1,
				filepath: getAbsoluteFilePath("test/jobexec.dll"),
			},
			TestFPO{
				imgDebugEntry: ImageDebugDirectory{
					Characteristics:  0x0,
					TimeDateStamp:    0x355b8e5f,
					MajorVersion:     0x0,
					MinorVersion:     0x0,
					Type:             0x3,
					SizeOfData:       0x840,
					AddressOfRawData: 0x0,
					PointerToRawData: 0xb310,
				},
				debugType:    "FPO",
				entriesCount: 131,
				FPODataIndex: 0,
				FPOData: FPOData{
					OffsetStart: 0x1bc0,
					ProcSize:    0x22,
				},
				FPOFrameType: "FPO",
			},
		},
		{
			TestDebugIn{
				index:    1,
				filepath: getAbsoluteFilePath("test/jobexec.dll"),
			},
			TestFPO{
				imgDebugEntry: ImageDebugDirectory{
					Characteristics:  0x0,
					TimeDateStamp:    0x355b8e5f,
					MajorVersion:     0x0,
					MinorVersion:     0x0,
					Type:             0x3,
					SizeOfData:       0x840,
					AddressOfRawData: 0x0,
					PointerToRawData: 0xb310,
				},
				debugType:    "FPO",
				entriesCount: 131,
				FPODataIndex: 2,
				FPOData: FPOData{
					OffsetStart:    0x1c26,
					ProcSize:       0x267,
					NumLocals:      0x104,
					ParamsSize:     0x1,
					PrologLength:   0x16,
					SavedRegsCount: 0x3,
					HasSEH:         0x0,
					UseBP:          0x1,
					Reserved:       0x0,
					FrameType:      0x3,
				},
				FPOFrameType: "Non FPO",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in.filepath, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in.filepath, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDebugDirectory(va, size)
			if err != nil {
				t.Fatalf("parseExportDirectory(%s) failed, reason: %v", tt.in.filepath, err)
			}

			imgDebugEntry := file.Debugs[tt.in.index].Struct
			if !reflect.DeepEqual(imgDebugEntry, tt.out.imgDebugEntry) {
				t.Fatalf("debug entry assertion failed, got %v, want %v",
					imgDebugEntry, tt.out.imgDebugEntry)
			}

			debugTypeString := file.Debugs[tt.in.index].Type
			if debugTypeString != tt.out.debugType {
				t.Fatalf("debug type assertion failed, got %v, want %v",
					debugTypeString, tt.out.debugType)
			}

			fpo := file.Debugs[tt.in.index].Info.([]FPOData)
			entriesCount := len(fpo)
			if entriesCount != tt.out.entriesCount {
				t.Fatalf("debug entry count failed, got %v, want %v",
					entriesCount, tt.out.entriesCount)
			}

			fpoData := fpo[tt.out.FPODataIndex]
			if !reflect.DeepEqual(fpoData, tt.out.FPOData) {
				t.Fatalf("debug FPO data entry assertion failed, got %v, want %v",
					fpoData, tt.out.FPOData)
			}

			frameType := fpoData.FrameType.String()
			if frameType != tt.out.FPOFrameType {
				t.Fatalf("debug FPO frame type string assertion failed, got %v, want %v",
					frameType, tt.out.FPOFrameType)
			}
		})
	}
}

func TestDebugSectionAttributes(t *testing.T) {

	tests := []struct {
		in  string
		out string
	}{
		{

			".00cfg",
			"CFG Check Functions Pointers",
		},
		{
			"__undefined__",
			"",
		},
	}

	for _, tt := range tests {
		t.Run(tt.out, func(t *testing.T) {

			secAttrString := SectionAttributeDescription(tt.in)
			if secAttrString != tt.out {
				t.Fatalf("debug section attributes description failed, got %v, want %v",
					secAttrString, tt.out)
			}
		})
	}
}


================================================
FILE: delayimports.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
)

// ImageDelayImportDescriptor represents the _IMAGE_DELAYLOAD_DESCRIPTOR structure.
type ImageDelayImportDescriptor struct {
	// As yet, no attribute flags are defined. The linker sets this field to zero
	// in the image. This field can be used to extend the record by indicating
	// the presence of new fields, or it can be used to indicate behaviors to
	// the delay or unload helper functions.
	Attributes uint32 `json:"attributes"`

	// The name of the DLL to be delay-loaded resides in the read-only data
	// section of the image. It is referenced through the szName field.
	Name uint32 `json:"name"`

	// The handle of the DLL to be delay-loaded is in the data section of the
	// image. The phmod field points to the handle. The supplied delay-load
	// helper uses this location to store the handle to the loaded DLL.
	ModuleHandleRVA uint32 `json:"module_handle_rva"`

	// The delay import address table (IAT) is referenced by the delay import
	// descriptor through the pIAT field. The delay-load helper updates these
	// pointers with the real entry points so that the thunks are no longer in
	// the calling loop
	ImportAddressTableRVA uint32 `json:"import_address_table_rva"`

	// The delay import name table (INT) contains the names of the imports that
	// might require loading. They are ordered in the same fashion as the
	// function pointers in the IAT.
	ImportNameTableRVA uint32 `json:"import_name_table_rva"`

	// The delay bound import address table (BIAT) is an optional table of
	// IMAGE_THUNK_DATA items that is used along with the timestamp field
	// of the delay-load directory table by a post-process binding phase.
	BoundImportAddressTableRVA uint32 `json:"bound_import_address_table_rva"`

	// The delay unload import address table (UIAT) is an optional table of
	// IMAGE_THUNK_DATA items that the unload code uses to handle an explicit
	// unload request. It consists of initialized data in the read-only section
	// that is an exact copy of the original IAT that referred the code to the
	// delay-load thunks. On the unload request, the library can be freed,
	// the *phmod cleared, and the UIAT written over the IAT to restore
	// everything to its preload state.
	UnloadInformationTableRVA uint32 `json:"unload_information_table_rva"`

	// 0 if not bound, otherwise, date/time of the target DLL.
	TimeDateStamp uint32 `json:"time_date_stamp"`
}

// DelayImport represents an entry in the delay import table.
type DelayImport struct {
	Offset     uint32                     `json:"offset"`
	Name       string                     `json:"name"`
	Functions  []ImportFunction           `json:"functions"`
	Descriptor ImageDelayImportDescriptor `json:"descriptor"`
}

// Delay-Load Import Tables tables were added to the image to support a uniform
// mechanism for applications to delay the loading of a DLL until the first call
// into that DLL. The delay-load directory table is the counterpart to the
// import directory table.
func (pe *File) parseDelayImportDirectory(rva, size uint32) error {
	for {
		importDelayDesc := ImageDelayImportDescriptor{}
		fileOffset := pe.GetOffsetFromRva(rva)
		importDescSize := uint32(binary.Size(importDelayDesc))
		err := pe.structUnpack(&importDelayDesc, fileOffset, importDescSize)

		// If the RVA is invalid all would blow up. Some EXEs seem to be
		// specially nasty and have an invalid RVA.
		if err != nil {
			return err
		}

		// If the structure is all zeros, we reached the end of the list.
		if importDelayDesc == (ImageDelayImportDescriptor{}) {
			break
		}

		rva += importDescSize

		// If the array of thunks is somewhere earlier than the import
		// descriptor we can set a maximum length for the array. Otherwise
		// just set a maximum length of the size of the file
		maxLen := uint32(len(pe.data)) - fileOffset
		if rva > importDelayDesc.ImportNameTableRVA ||
			rva > importDelayDesc.ImportAddressTableRVA {
			if rva < importDelayDesc.ImportNameTableRVA {
				maxLen = rva - importDelayDesc.ImportAddressTableRVA
			} else if rva < importDelayDesc.ImportAddressTableRVA {
				maxLen = rva - importDelayDesc.ImportNameTableRVA
			} else {
				maxLen = Max(rva-importDelayDesc.ImportNameTableRVA,
					rva-importDelayDesc.ImportAddressTableRVA)
			}
		}

		var importedFunctions []ImportFunction
		if pe.Is64 {
			importedFunctions, err = pe.parseImports64(&importDelayDesc, maxLen)
		} else {
			importedFunctions, err = pe.parseImports32(&importDelayDesc, maxLen)
		}
		if err != nil {
			return err
		}

		nameRVA := uint32(0)
		if importDelayDesc.Attributes == 0 {
			nameRVA = importDelayDesc.Name -
				pe.NtHeader.OptionalHeader.(ImageOptionalHeader32).ImageBase
		} else {
			nameRVA = importDelayDesc.Name
		}
		dllName := pe.getStringAtRVA(nameRVA, maxLen)
		if !IsValidDosFilename(dllName) {
			dllName = "*invalid*"
			continue
		}

		pe.DelayImports = append(pe.DelayImports, DelayImport{
			Offset:     fileOffset,
			Name:       string(dllName),
			Functions:  importedFunctions,
			Descriptor: importDelayDesc,
		})
	}

	if len(pe.DelayImports) > 0 {
		pe.HasDelayImp = true
	}

	return nil
}

// GetDelayImportEntryInfoByRVA return an import function + index of the entry given
// an RVA.
func (pe *File) GetDelayImportEntryInfoByRVA(rva uint32) (DelayImport, int) {
	for _, imp := range pe.DelayImports {
		for i, entry := range imp.Functions {
			if entry.ThunkRVA == rva {
				return imp, i
			}
		}
	}

	return DelayImport{}, 0
}


================================================
FILE: delayimports_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"reflect"
	"testing"
)

type TestDelayImportEntry struct {
	entryCount int
	entryIndex int
	entry      DelayImport
}

func TestDelayImportDirectory(t *testing.T) {

	tests := []struct {
		in  string
		out TestDelayImportEntry
	}{
		{
			getAbsoluteFilePath("test/000049925c578e5a0883e7d1a8257c1a44feab8f7d9972ace8d0e3fb96612a4c"),
			TestDelayImportEntry{
				entryCount: 4,
				entryIndex: 0,
				entry: DelayImport{
					Offset: 0x5F7C00,
					Name:   "kernel32.dll",
					Functions: []ImportFunction{
						{
							Name:               "GetLogicalProcessorInformation",
							Hint:               0x0,
							ByOrdinal:          false,
							OriginalThunkValue: 0x601192,
							ThunkValue:         0xF04E60,
							ThunkRVA:           0x6010B4,
							OriginalThunkRVA:   0x6010F0,
						},
					},
					Descriptor: ImageDelayImportDescriptor{
						Attributes:                 0x1,
						Name:                       0x601184,
						ModuleHandleRVA:            0x6010A0,
						ImportAddressTableRVA:      0x6010B4,
						ImportNameTableRVA:         0x6010F0,
						BoundImportAddressTableRVA: 0x60112C,
						UnloadInformationTableRVA:  0x601158,
						TimeDateStamp:              0x0,
					},
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
			}

			err = file.Parse()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
			}

			var va, size uint32

			if file.Is64 {
				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
				dirEntry := oh64.DataDirectory[ImageDirectoryEntryDelayImport]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			} else {
				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
				dirEntry := oh32.DataDirectory[ImageDirectoryEntryDelayImport]
				va = dirEntry.VirtualAddress
				size = dirEntry.Size
			}

			err = file.parseDelayImportDirectory(va, size)
			if err != nil {
				t.Fatalf("parseDelayImportDirectory(%s) failed, reason: %v", tt.in, err)
			}
			got := file.DelayImports
			if len(got) != tt.out.entryCount {
				t.Errorf("delay imports entry count assertion failed, got %v, want %v",
					len(got), tt.out.entryCount)
			}

			if len(file.DelayImports) > 0 {
				delayImportEntry := file.DelayImports[tt.out.entryIndex]
				if !reflect.DeepEqual(delayImportEntry, tt.out.entry) {
					t.Errorf("delay import entry assertion failed, got %v, want %v",
						delayImportEntry, tt.out.entry)
				}
			}

		})
	}
}


================================================
FILE: dosheader.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
)

// ImageDOSHeader represents the DOS stub of a PE.
type ImageDOSHeader struct {
	// Magic number.
	Magic uint16 `json:"magic"`

	// Bytes on last page of file.
	BytesOnLastPageOfFile uint16 `json:"bytes_on_last_page_of_file"`

	// Pages in file.
	PagesInFile uint16 `json:"pages_in_file"`

	// Relocations.
	Relocations uint16 `json:"relocations"`

	// Size of header in paragraphs.
	SizeOfHeader uint16 `json:"size_of_header"`

	// Minimum extra paragraphs needed.
	MinExtraParagraphsNeeded uint16 `json:"min_extra_paragraphs_needed"`

	// Maximum extra paragraphs needed.
	MaxExtraParagraphsNeeded uint16 `json:"max_extra_paragraphs_needed"`

	// Initial (relative) SS value.
	InitialSS uint16 `json:"initial_ss"`

	// Initial SP value.
	InitialSP uint16 `json:"initial_sp"`

	// Checksum.
	Checksum uint16 `json:"checksum"`

	// Initial IP value.
	InitialIP uint16 `json:"initial_ip"`

	// Initial (relative) CS value.
	InitialCS uint16 `json:"initial_cs"`

	// File address of relocation table.
	AddressOfRelocationTable uint16 `json:"address_of_relocation_table"`

	// Overlay number.
	OverlayNumber uint16 `json:"overlay_number"`

	// Reserved words.
	ReservedWords1 [4]uint16 `json:"reserved_words_1"`

	// OEM identifier.
	OEMIdentifier uint16 `json:"oem_identifier"`

	// OEM information.
	OEMInformation uint16 `json:"oem_information"`

	// Reserved words.
	ReservedWords2 [10]uint16 `json:"reserved_words_2"`

	// File address of new exe header (Elfanew).
	AddressOfNewEXEHeader uint32 `json:"address_of_new_exe_header"`
}

// ParseDOSHeader parses the DOS header stub. Every PE file begins with a small
// MS-DOS stub. The need for this arose in the early days of Windows, before a
// significant number of consumers were running it. When executed on a machine
// without Windows, the program could at least print out a message saying that
// Windows was required to run the executable.
func (pe *File) ParseDOSHeader() (err error) {
	offset := uint32(0)
	size := uint32(binary.Size(pe.DOSHeader))
	err = pe.structUnpack(&pe.DOSHeader, offset, size)
	if err != nil {
		return err
	}

	// It can be ZM on an (non-PE) EXE.
	// These executables still work under XP via ntvdm.
	if pe.DOSHeader.Magic != ImageDOSSignature &&
		pe.DOSHeader.Magic != ImageDOSZMSignature {
		return ErrDOSMagicNotFound
	}

	// `e_lfanew` is the only required element (besides the signature) of the
	// DOS header to turn the EXE into a PE. It is is a relative offset to the
	// NT Headers. It can't be null (signatures would overlap).
	// Can be 4 at minimum.
	if pe.DOSHeader.AddressOfNewEXEHeader < 4 ||
		pe.DOSHeader.AddressOfNewEXEHeader > pe.size {
		return ErrInvalidElfanewValue
	}

	// tiny pe has a e_lfanew of 4, which means the NT Headers is overlapping
	// the DOS Header.
	if pe.DOSHeader.AddressOfNewEXEHeader <= 0x3c {
		pe.Anomalies = append(pe.Anomalies, AnoPEHeaderOverlapDOSHeader)
	}

	pe.HasDOSHdr = true
	return nil
}


================================================
FILE: dosheader_test.go
================================================
// Copyright 2022 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"testing"
)

type TestDOSHeader struct {
	imageDOSHeader ImageDOSHeader
}

func TestParseDOSHeader(t *testing.T) {
	tests := []struct {
		in  string
		out TestDOSHeader
	}{
		{
			getAbsoluteFilePath("test/putty.exe"),
			TestDOSHeader{
				imageDOSHeader: ImageDOSHeader{
					Magic:                    0x5a4d,
					BytesOnLastPageOfFile:    0x78,
					PagesInFile:              0x1,
					Relocations:              0x0,
					SizeOfHeader:             0x4,
					MinExtraParagraphsNeeded: 0x0,
					MaxExtraParagraphsNeeded: 0x0,
					InitialSS:                0x0,
					InitialSP:                0x0,
					Checksum:                 0x0,
					InitialIP:                0x0,
					InitialCS:                0x0,
					AddressOfRelocationTable: 0x40,
					OverlayNumber:            0x0,
					ReservedWords1:           [4]uint16{},
					OEMIdentifier:            0x0,
					OEMInformation:           0x0,
					ReservedWords2:           [10]uint16{},
					AddressOfNewEXEHeader:    0x78,
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.in, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
			}

			err = file.ParseDOSHeader()
			if err != nil {
				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
			}

			got := file.DOSHeader
			if got != tt.out.imageDOSHeader {
				t.Errorf("parse DOS header assertion failed, got %v, want %v", got,
					tt.out.imageDOSHeader)
			}

		})
	}
}

func TestParseDOSHeaderNonMZ(t *testing.T) {
	tests := []struct {
		in  string
		out error
	}{
		{
			// This is an ELF file.
			getAbsoluteFilePath("test/look"),
			ErrDOSMagicNotFound,
		},
	}

	for _, tt := range tests {
		t.Run(tt.in, func(t *testing.T) {
			ops := Options{Fast: true}
			file, err := New(tt.in, &ops)
			if err != nil {
				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
			}

			err = file.ParseDOSHeader()
			if err != tt.out {
				t.Fatalf("parsing DOS header failed, got %v, want %v", err, tt.out)
			}
		})
	}
}


================================================
FILE: dotnet.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

import (
	"encoding/binary"
)

// References
// https://www.ntcore.com/files/dotnetformat.htm

// COMImageFlagsType represents a COM+ header entry point flag type.
type COMImageFlagsType uint32

// COM+ Header entry point flags.
const (
	// The image file contains IL code only, with no embedded native unmanaged
	// code except the start-up stub (which simply executes an indirect jump to
	// the CLR entry point).
	COMImageFlagsILOnly = 0x00000001

	// The image file can be loaded only into a 32-bit process.
	COMImageFlags32BitRequired = 0x00000002

	// This flag is obsolete and should not be set. Setting it—as the IL
	// assembler allows, using the .corflags directive—will render your module
	// un-loadable.
	COMImageFlagILLibrary = 0x00000004

	// The image file is protected with a strong name signature.
	COMImageFlagsStrongNameSigned = 0x00000008

	// The executable’s entry point is an unmanaged method. The EntryPointToken/
	// EntryPointRVA field of the CLR header contains the RVA of this native
	// method. This flag was introduced in version 2.0 of the CLR.
	COMImageFlagsNativeEntrypoint = 0x00000010

	// The CLR loader and the JIT compiler are required to track debug
	// information about the methods. This flag is not used.
	COMImageFlagsTrackDebugData = 0x00010000

	// The image file can be loaded into any process, but preferably into a
	// 32-bit process. This flag can be only set together with flag
	// COMIMAGE_FLAGS_32BITREQUIRED. When set, these two flags mean the image
	// is platformneutral, but prefers to be loaded as 32-bit when possible.
	// This flag was introduced in CLR v4.0
	COMImageFlags32BitPreferred = 0x00020000
)

// V-table constants.
const (
	// V-table slots are 32-bits in size.
	CORVTable32Bit = 0x01

	// V-table slots are 64-bits in size.
	CORVTable64Bit = 0x02

	//  The thunk created by the common language runtime must provide data
	// marshaling between managed and unmanaged code.
	CORVTableFromUnmanaged = 0x04

	// The thunk created by the common language runtime must provide data
	// marshaling between managed and unmanaged code. Current appdomain should
	// be selected to dispatch the call.
	CORVTableFromUnmanagedRetainAppDomain = 0x08

	// Call most derived method described by
	CORVTableCallMostDerived = 0x10
)

// Metadata Tables constants.
const (
	// The current module descriptor.
	Module = 0
	// Class reference descriptors.
	TypeRef = 1
	// Class or interface definition descriptors.
	TypeDef = 2
	// A class-to-fields lookup table, which does not exist in optimized
	// metadata (#~ stream).
	FieldPtr = 3
	// Field definition descriptors.
	Field = 4
	// A class-to-methods lookup table, which does not exist in
	// optimized metadata (#~ stream).
	MethodPtr = 5
	// Method definition descriptors.
	MethodDef = 6
	// A method-to-parameters lookup table, which does not exist in optimized
	// metadata (#~ stream).
	ParamPtr = 7
	// Parameter definition descriptors.
	Param = 8
	// Interface implementation descriptors.
	InterfaceImpl = 9
	// Member (field or method) reference descriptors.
	MemberRef = 10
	// Constant value descriptors that map the default values stored in the
	// #Blob stream to respective fields, parameters, and properties.
	Constant = 11
	// Custom attribute descriptors.
	CustomAttribute = 12
	// Field or parameter marshaling descriptors for managed/unmanaged
	// inter-operations.
	FieldMarshal = 13
	// Security descriptors.
	DeclSecurity = 14
	// Class layout descriptors that hold information about how the loader
	// should lay out respective classes.
	ClassLayout = 15
	// Field layout descriptors that specify the offset or ordinal of
	// individual fields.
	FieldLayout = 16
	// Stand-alone signature descriptors. Signatures per se are used in two
	// capacities: as composite signatures of local variables of methods and as
	// parameters of the call indirect (calli) IL instruction.
	StandAloneSig = 17
	// A class-to-events mapping table. This is not an intermediate lookup
	// table, and it does exist in optimized metadata.
	EventMap = 18
	// An event map–to–events lookup table, which does not exist in optimized
	// metadata (#~ stream).
	EventPtr = 19
	// Event descriptors.
	Event = 20
	// A class-to-properties mapping table. This is not an intermediate lookup
	// table, and it does exist in optimized metadata.
	PropertyMap = 21
	// A property map–to–properties lookup table, which does not exist in
	// optimized metadata (#~ stream).
	PropertyPtr = 22
	// Property descriptors.
	Property = 23
	// Method semantics descriptors that hold information about which method is
	// associated with a specific property or event and in what capacity.
	MethodSemantics = 24
	// Method implementation descriptors.
	MethodImpl = 25
	// Module reference descriptors.
	ModuleRef = 26
	// Type specification descriptors.
	TypeSpec = 27
	// Implementation map descriptors used for the platform invocation
	// (P/Invoke) type of managed/unmanaged code inter-operation.
	ImplMap = 28
	// Field-to-data mapping descriptors.
	FieldRVA = 29
	// Edit-and-continue log descriptors that hold information about what
	// changes have been made to specific metadata items during in-memory
	// editing. This table does not exist in optimized metadata (#~ stream)
	ENCLog = 30
	// Edit-and-continue mapping descriptors. This table does not exist in
	// optimized metadata (#~ stream).
	ENCMap = 31
	// The current assembly descriptor, which should appear only in the prime
	// module metadata.
	Assembly = 32
	// This table is unused.
	AssemblyProcessor = 33
	// This table is unused.
	AssemblyOS = 34
	// Assembly reference descriptors.
	AssemblyRef = 35
	// This table is unused.
	AssemblyRefProcessor = 36
	// This table is unused.
	AssemblyRefOS = 37
	// File descriptors that contain information about other files in the
	// current assembly.
	FileMD = 38
	// Exported type descriptors that contain information about public classes
	// exported by the current assembly, which are declared in other modules of
	// the assembly. Only the prime module of the assembly should carry this
	// table.
	ExportedType = 39
	// Managed resource descriptors.
	ManifestResource = 40
	// Nested class descriptors that provide mapping of nested classes to their
	// respective enclosing classes.
	NestedClass = 41
	//  Type parameter descriptors for generic (parameterized) classes and
	// methods.
	GenericParam = 42
	// Generic method instantiation descriptors.
	MethodSpec = 43
	// Descriptors of constraints specified for type parameters of generic
	// classes and methods
	GenericParamConstraint = 44
)

// Heaps Streams Bit Positions.
const (
	StringStream = 0
	GUIDStream   = 1
	BlobStream   = 2
)

// MetadataTableIndexToString returns the string representation of the metadata
// table index.
func MetadataTableIndexToString(k int) string {
	metadataTablesMap := map[int]string{
		Module:                 "Module",
		TypeRef:                "TypeRef",
		TypeDef:                "TypeDef",
		FieldPtr:               "FieldPtr",
		Field:                  "Field",
		MethodPtr:              "MethodPtr",
		MethodDef:              "MethodDef",
		ParamPtr:               "ParamPtr",
		Param:                  "Param",
		InterfaceImpl:          "InterfaceImpl",
		MemberRef:              "MemberRef",
		Constant:               "Constant",
		CustomAttribute:        "CustomAttribute",
		FieldMarshal:           "FieldMarshal",
		DeclSecurity:           "DeclSecurity",
		ClassLayout:            "ClassLayout",
		FieldLayout:            "FieldLayout",
		StandAloneSig:          "StandAloneSig",
		EventMap:               "EventMap",
		EventPtr:               "EventPtr",
		Event:                  "Event",
		PropertyMap:            "PropertyMap",
		PropertyPtr:            "PropertyPtr",
		Property:               "Property",
		MethodSemantics:        "MethodSemantics",
		MethodImpl:             "MethodImpl",
		ModuleRef:              "ModuleRef",
		TypeSpec:               "TypeSpec",
		ImplMap:                "ImplMap",
		FieldRVA:               "FieldRVA",
		ENCLog:                 "ENCLog",
		ENCMap:                 "ENCMap",
		Assembly:               "Assembly",
		AssemblyProcessor:      "AssemblyProcessor",
		AssemblyOS:             "AssemblyOS",
		AssemblyRef:            "AssemblyRef",
		AssemblyRefProcessor:   "AssemblyRefProcessor",
		AssemblyRefOS:          "AssemblyRefOS",
		FileMD:                 "File",
		ExportedType:           "ExportedType",
		ManifestResource:       "ManifestResource",
		NestedClass:            "NestedClass",
		GenericParam:           "GenericParam",
		MethodSpec:             "MethodSpec",
		GenericParamConstraint: "GenericParamConstraint",
	}

	if value, ok := metadataTablesMap[k]; ok {
		return value
	}
	return ""
}

// GetMetadataStreamIndexSize returns the size of indexes to read into a
// particular heap.
func (pe *File) GetMetadataStreamIndexSize(BitPosition int) int {
	// The `Heaps` field is a bit vector that encodes how wide indexes into the
	// various heaps are:
	// - If bit 0 is set, indexes into the "#String" heap are 4 bytes wide;
	// - if bit 1 is set, indexes into the "#GUID" heap are 4 bytes wide;
	// - if bit 2 is set, indexes into the "#Blob" heap are 4 bytes wide.
	heaps := pe.CLR.MetadataTablesStreamHeader.Heaps
	if IsBitSet(uint64(heaps), BitPosition) {
		return 4
	}
	// Conversely, if the HeapSizes bit for a particular heap is not set,
	// indexes into that heap are 2 bytes wide.
	return 2
}

// ImageDataDirectory represents the  directory format.
type ImageDataDirectory struct {

	// The relative virtual address of the table.
	VirtualAddress uint32 `json:"virtual_address"`

	// The size of the table, in bytes.
	Size uint32 `json:"size"`
}

// ImageCOR20Header represents the CLR 2.0 header structure.
type ImageCOR20Header struct {

	// Size of the header in bytes.
	Cb uint32 `json:"cb"`

	// Major number of the minimum version of the runtime required to run the
	// program.
	MajorRuntimeVersion uint16 `json:"major_runtime_version"`

	// Minor number of the version of the runtime required to run the program.
	MinorRuntimeVersion uint16 `json:"minor_runtime_version"`

	// RVA and size of the metadata.
	MetaData ImageDataDirectory `json:"meta_data"`

	// Bitwise flags indicating attributes of this executable.
	Flags COMImageFlagsType `json:"flags"`

	// Metadata identifier (token) of the entry point for the image file; can
	// be 0 for DLL images. This field identifies a method belonging to this
	// module or a module containing the entry point method.
	// In images of version 2.0 and newer, this field may contain RVA of the
	// embedded native entry point method.
	// union {
	//
	// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set,
	// EntryPointToken represents a managed entrypoint.
	//	DWORD               EntryPointToken;
	//
	// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set,
	// EntryPointRVA represents an RVA to a native entrypoint
	//	DWORD               EntryPointRVA;
	//};
	EntryPointRVAorToken uint32 `json:"entry_point_rva_or_token"`

	// This is the blob of managed resources. Fetched using
	// code:AssemblyNative.GetResource and code:PEFile.GetResource and accessible
	// from managed code from System.Assembly.GetManifestResourceStream. The
	// metadata has a table that maps names to offsets into this blob, so
	// logically the blob is a set of resources.
	Resources ImageDataDirectory `json:"resources"`

	// RVA and size of the hash data for this PE file, used by the loader for
	// binding and versioning. IL assemblies can be signed with a public-private
	// key to validate who created it. The signature goes here if this feature
	// is used.
	StrongNameSignature ImageDataDirectory `json:"strong_name_signature"`

	// RVA and size of the Code Manager table. In the existing releases of the
	// runtime, this field is reserved and must be set to 0.
	CodeManagerTable ImageDataDirectory `json:"code_manager_table"`

	// RVA and size in bytes of an array of virtual table (v-table) fixups.
	// Among current managed compilers, only the VC++ linker and the IL
	// assembler can produce this array.
	VTableFixups ImageDataDirectory `json:"vtable_fixups"`

	// RVA and size of an array of addresses of jump thunks. Among managed
	// compilers, only the VC++ of versions pre-8.0 could produce this table,
	// which allows the export of unmanaged native methods embedded in the
	// managed PE file. In v2.0+ of CLR this entry is obsolete and must be set
	// to 0.
	ExportAddressTableJumps ImageDataDirectory `json:"export_address_table_jumps"`

	// Reserved for precompiled images; set to 0
	// NGEN images it points at a code:CORCOMPILE_HEADER structure
	ManagedNativeHeader ImageDataDirectory `json:"managed_native_header"`
}

// ImageCORVTableFixup defines the v-table fixups that contains the
// initializing information necessary for the runtime to create the thunks.
// Non VOS v-table entries.  Define an array of these pointed to by
// IMAGE_COR20_HEADER.VTableFixups.  Each entry describes a contiguous array of
// v-table slots.  The slots start out initialized to the meta data token value
// for the method they need to call.  At image load time, the CLR Loader will
// turn each entry into a pointer to machine code for the CPU and can be
// called directly.
type ImageCORVTableFixup struct {
	RVA   uint32 `json:"rva"`   // Offset of v-table array in image.
	Count uint16 `json:"count"` // How many entries at location.
	Type  uint16 `json:"type"`  // COR_VTABLE_xxx type of entries.
}

// MetadataHeader consists of a storage signature and a storage header.
type MetadataHeader struct {
	// The storage signature, which must be 4-byte aligned:
	// ”Magic” signature for physical metadata, currently 0x424A5342, or, read
	// as characters, BSJB—the initials of four “founding fathers” Brian Harry,
	// Susa Radke-Sproull, Jason Zander, and Bill Evans, who started the
	// runtime development in 1998.
	Signature uint32 `json:"signature"`

	// Major version.
	MajorVersion uint16 `json:"major_version"`

	// Minor version.
	MinorVersion uint16 `json:"minor_version"`

	// Reserved; set to 0.
	ExtraData uint32 `json:"extra_data"`

	// Length of the version string.
	VersionString uint32 `json:"version_string"`

	// Version string.
	Version string `json:"version"`

	// The storage header follows the storage signature, aligned on a 4-byte
	// boundary.
	//

	// Reserved; set to 0.
	Flags uint8 `json:"flags"`

	// Another byte used for [padding]

	// Number of streams.
	Streams uint16 `json:"streams"`
}

// MetadataStreamHeader represents a Metadata Stream Header Structure.
type MetadataStreamHeader struct {
	// Offset in the file for this stream.
	Offset uint32 `json:"offset"`

	// Size of the stream in bytes.
	Size uint32 `json:"size"`

	// Name of the stream; a zero-terminated ASCII string no longer than 31
	// characters (plus zero terminator). The name might be shorter, in which
	// case the size of the stream header is correspondingly reduced, padded to
	// the 4-byte boundary.
	Name string `json:"name"`
}

// MetadataTableStreamHeader represents the Metadata Table Stream Header Structure.
type MetadataTableStreamHeader struct {
	// Reserved; set to 0.
	Reserved uint32 `json:"reserved"`

	// Major version of the table schema (1 for v1.0 and v1.1; 2 for v2.0 or later).
	MajorVersion uint8 `json:"major_version"`

	// Minor version of the table schema (0 for all versions).
	MinorVersion uint8 `json:"minor_version"`

	// Binary flags indicate the offset sizes to be used within the heaps.
	// 4-byte unsigned integer offset is indicated by:
	// - 0x01 for a string heap, 0x02 for a GUID heap, and 0x04 for a blob heap.
	// If a flag is not set, the respective heap offset is a 2-byte unsigned integer.
	// A #- stream can also have special flags set:
	// - flag 0x20, indicating that the stream contains only changes made
	// during an edit-and-continue session, and;
	// - flag 0x80, indicating that the  metadata might contain items marked as
	// deleted.
	Heaps uint8 `json:"heaps"`

	// Bit width of the maximal record index to all tables of the metadata;
	// calculated at run time (during the metadata stream initialization).
	RID uint8 `json:"rid"`

	// Bit vector of present tables, each bit representing one table (1 if
	// present).
	MaskValid uint64 `json:"mask_valid"`

	// Bit vector of sorted tables, each bit representing a respective table (1
	// if sorted)
	Sorted uint64 `json:"sorted"`
}

// MetadataTable represents the content of a particular table in the metadata.
// The metadata schema defines 45 tables.
type MetadataTable struct {
	// The name of the table.
	Name string `json:"name"`

	// Number of columns in the table.
	CountCols uint32 `json:"count_cols"`

	// Every table has a different layout, defined in the ECMA-335 spec.
	// Content abstract the type each table is pointing to.
	Content interface{} `json:"content"`
}

// CLRData embeds the Common Language Runtime Header structure as well as the
// Metadata header structure.
type CLRData struct {
	CLRHeader                  ImageCOR20Header          `json:"clr_header"`
	MetadataHeader             MetadataHeader            `json:"metadata_header"`
	MetadataStreamHeaders      []MetadataStreamHeader    `json:"metadata_stream_headers"`
	MetadataStreams            map[string][]byte         `json:"-"`
	MetadataTablesStreamHeader MetadataTableStreamHeader `json:"metadata_tables_stream_header"`
	MetadataTables             map[int]*MetadataTable    `json:"metadata_tables"`
	StringStreamIndexSize      int                       `json:"-"`
	GUIDStreamIndexSize        int                       `json:"-"`
	BlobStreamIndexSize        int                       `json:"-"`
}

func (pe *File) parseMetadataStream(off, size uint32) (MetadataTableStreamHeader, error) {
	mdTableStreamHdr := MetadataTableStreamHeader{}
	if size == 0 {
		return mdTableStreamHdr, nil
	}

	mdTableStreamHdrSize := uint32(binary.Size(mdTableStreamHdr))
	err := pe.structUnpack(&mdTableStreamHdr, off, mdTableStreamHdrSize)
	if err != nil {
		return mdTableStreamHdr, err
	}

	return mdTableStreamHdr, nil
}

func (pe *File) parseMetadataHeader(offset, size uint32) (MetadataHeader, error) {
	var err error
	mh := MetadataHeader{}

	if mh.Signature, err = pe.ReadUint32(offset); err != nil {
		return mh, err
	}
	if mh.MajorVersion, err = pe.ReadUint16(offset + 4); err != nil {
		return mh, err
	}
	if mh.MinorVersion, err = pe.ReadUint16(offset + 6); err != nil {
		return mh, err
	}
	if mh.ExtraData, err = pe.ReadUint32(offset + 8); err != nil {
		return mh, err
	}
	if mh.VersionString, err = pe.ReadUint32(offset + 12); err != nil {
		return mh, err
	}
	mh.Version, err = pe.getStringAtOffset(offset+16, mh.VersionString)
	if err != nil {
		return mh, err
	}

	offset += 16 + mh.VersionString
	if mh.Flags, err = pe.ReadUint8(offset); err != nil {
		return mh, err
	}

	if mh.Streams, err = pe.ReadUint16(offset + 2); err != nil {
		return mh, err
	}

	return mh, err
}

// The 15th directory entry of the PE header contains the RVA and size of the
// runtime header in the image file. The runtime header, which contains all of
// the runtime-specific data entries and other information, should reside in a
// read-only section of the image file. The IL assembler puts the common
// language runtime header in the .text section.
func (pe *File) parseCLRHeaderDirectory(rva, size uint32) error {

	clrHeader := ImageCOR20Header{}
	offset := pe.GetOffsetFromRva(rva)
	err := pe.structUnpack(&clrHeader, offset, size)
	if err != nil {
		return err
	}

	pe.CLR.CLRHeader = clrHeader
	if clrHeader.MetaData.VirtualAddress == 0 || clrHeader.MetaData.Size == 0 {
		return nil
	}

	// If we get a CLR header, we assume that this is enough
	// to say we have a CLR data to show even if parsing
	// other structures fails later.
	pe.HasCLR = true

	if pe.opts.OmitCLRMetadata {
		return nil
	}

	offset = pe.GetOffsetFromRva(clrHeader.MetaData.VirtualAddress)
	mh, err := pe.parseMetadataHeader(offset, clrHeader.MetaData.Size)
	if err != nil {
		return err
	}
	pe.CLR.MetadataHeader = mh
	pe.CLR.MetadataStreams = make(map[string][]byte)
	offset += 16 + mh.VersionString + 4

	// Immediately following the MetadataHeader is a series of Stream Headers.
	// A “stream” is to the metadata what a “section” is to the assembly. The
	// NumberOfStreams property indicates how many StreamHeaders to read.
	mdStreamHdrOff := uint32(0)
	mdStreamHdrSize := uint32(0)
	for i := uint16(0); i < mh.Streams; i++ {
		sh := MetadataStreamHeader{}
		if sh.Offset, err = pe.ReadUint32(offset); err != nil {
			return err
		}
		if sh.Size, err = pe.ReadUint32(offset + 4); err != nil {
			return err
		}

		// Name requires a special treatment.
		offset += 8
		for j := uint32(0); j <= 32; j++ {
			var c uint8
			if c, err = pe.ReadUint8(offset); err != nil {
				return err
			}

			offset++
			if c == 0 && (j+1)%4 == 0 {
				break
			}
			if c != 0 {
				sh.Name += string(c)
			}
		}

		// The streams #~ and #- are mutually exclusive; that is, the metadata
		// structure of the module is either optimized or un-optimized; it
		// cannot be both at the same time or be something in between.
		if sh.Name == "#~" || sh.Name == "#-" {
			mdStreamHdrOff = sh.Offset
			mdStreamHdrSize = sh.Size
		}

		rva = clrHeader.MetaData.VirtualAddress + sh.Offset
		start := pe.GetOffsetFromRva(rva)

		// Some malformed/Corrupt PEs has invalid sizes on sh.
		mdStreamBytes := make([]byte, 0)
		if start+sh.Size <= uint32(len(pe.data)) {
			mdStreamBytes = pe.data[start : start+sh.Size]
		}

		// Save the stream into a map <string> []byte.
		pe.CLR.MetadataStreams[sh.Name] = mdStreamBytes
		pe.CLR.MetadataStreamHeaders = append(pe.CLR.MetadataStreamHeaders, sh)
	}

	// Get the Metadata Table Stream.
	if mdStreamHdrSize == 0 {
		return nil
	}
	// The .Offset indicated by the stream header is an RVA relative to the
	// metadataDirectoryAddress in the CLRHeader.
	rva = clrHeader.MetaData.VirtualAddress + mdStreamHdrOff
	offset = pe.GetOffsetFromRva(rva)
	mdTableStreamHdr, err := pe.parseMetadataStream(offset, mdStreamHdrSize)
	if err != nil {
		return nil
	}
	pe.CLR.MetadataTablesStreamHeader = mdTableStreamHdr

	// Get the size of indexes of #String", "#GUID" and "#Blob" streams.
	pe.CLR.StringStreamIndexSize = pe.GetMetadataStreamIndexSize(StringStream)
	pe.CLR.GUIDStreamIndexSize = pe.GetMetadataStreamIndexSize(GUIDStream)
	pe.CLR.BlobStreamIndexSize = pe.GetMetadataStreamIndexSize(BlobStream)

	// This header is followed by a sequence of 4-byte unsigned integers
	// indicating the number of records in each table marked 1 in the MaskValid
	// bit vector.
	offset += uint32(binary.Size(mdTableStreamHdr))
	pe.CLR.MetadataTables = make(map[int]*MetadataTable)
	for i := 0; i <= GenericParamConstraint; i++ {
		if IsBitSet(mdTableStreamHdr.MaskValid, i) {
			mdTable := MetadataTable{}
			mdTable.Name = MetadataTableIndexToString(i)
			mdTable.CountCols, err = pe.ReadUint32(offset)
			if err != nil {
				break
			}
			offset += 4
			pe.CLR.MetadataTables[i] = &mdTable
		}
	}

	// Parse the metadata tables.
	for tableIndex := 0; tableIndex <= GenericParamConstraint; tableIndex++ {
		table, ok := pe.CLR.MetadataTables[tableIndex]
		if !ok {
			continue
		}

		n := uint32(0)
		switch tableIndex {
		case Module: // 0x00
			table.Content, n, err = pe.parseMetadataModuleTable(offset)
		case TypeRef: // 0x01
			table.Content, n, err = pe.parseMetadataTypeRefTable(offset)
		case TypeDef: // 0x02
			table.Content, n, err = pe.parseMetadataTypeDefTable(offset)
		case Field: // 0x04
			table.Content, n, err = pe.parseMetadataFieldTable(offset)
		case MethodDef: // 0x06
			table.Content, n, err = pe.parseMetadataMethodDefTable(offset)
		case Param: // 0x08
			table.Content, n, err = pe.parseMetadataParamTable(offset)
		case InterfaceImpl: // 0x09
			table.Content, n, err = pe.parseMetadataInterfaceImplTable(offset)
		case MemberRef: // 0x0a
			table.Content, n, err = pe.parseMetadataMemberRefTable(offset)
		case Constant: // 0x0b
			table.Content, n, err = pe.parseMetadataConstantTable(offset)
		case CustomAttribute: // 0x0c
			table.Content, n, err = pe.parseMetadataCustomAttributeTable(offset)
		case FieldMarshal: // 0x0d
			table.Content, n, err = pe.parseMetadataFieldMarshalTable(offset)
		case DeclSecurity: // 0x0e
			table.Content, n, err = pe.parseMetadataDeclSecurityTable(offset)
		case ClassLayout: // 0x0f
			table.Content, n, err = pe.parseMetadataClassLayoutTable(offset)
		case FieldLayout: // 0x10
			table.Content, n, err = pe.parseMetadataFieldLayoutTable(offset)
		case StandAloneSig: // 0x11
			table.Content, n, err = pe.parseMetadataStandAloneSignTable(offset)
		case EventMap: // 0x12
			table.Content, n, err = pe.parseMetadataEventMapTable(offset)
		case Event: // 0x14
			table.Content, n, err = pe.parseMetadataEventTable(offset)
		case PropertyMap: // 0x15
			table.Content, n, err = pe.parseMetadataPropertyMapTable(offset)
		case Property: // 0x17
			table.Content, n, err = pe.parseMetadataPropertyTable(offset)
		case MethodSemantics: // 0x18
			table.Content, n, err = pe.parseMetadataMethodSemanticsTable(offset)
		case MethodImpl: // 0x19
			table.Content, n, err = pe.parseMetadataMethodImplTable(offset)
		case ModuleRef: // 0x1a
			table.Content, n, err = pe.parseMetadataModuleRefTable(offset)
		case TypeSpec: // 0x1b
			table.Content, n, err = pe.parseMetadataTypeSpecTable(offset)
		case ImplMap: // 0x1c
			table.Content, n, err = pe.parseMetadataImplMapTable(offset)
		case FieldRVA: // 0x1d
			table.Content, n, err = pe.parseMetadataFieldRVATable(offset)
		case Assembly: // 0x20
			table.Content, n, err = pe.parseMetadataAssemblyTable(offset)
		case AssemblyRef: // 0x23
			table.Content, n, err = pe.parseMetadataAssemblyRefTable(offset)
		case ExportedType: // 0x27
			table.Content, n, err = pe.parseMetadataExportedTypeTable(offset)
		case ManifestResource: // 0x28
			table.Content, n, err = pe.parseMetadataManifestResourceTable(offset)
		case NestedClass: // 0x29
			table.Content, n, err = pe.parseMetadataNestedClassTable(offset)
		case GenericParam: // 0x2a
			table.Content, n, err = pe.parseMetadataGenericParamTable(offset)
		case MethodSpec: // 0x2b
			table.Content, n, err = pe.parseMetadataMethodSpecTable(offset)
		case GenericParamConstraint: // 0x2c
			table.Content, n, err = pe.parseMetadataGenericParamConstraintTable(offset)
		case FileMD: // 0x26
			table.Content, n, err = pe.parseMetadataFileTable(offset)
		default:
			pe.logger.Warnf("unhandled metadata table %d %s offset 0x%x cols %d",
				tableIndex, MetadataTableIndexToString(tableIndex), offset, table.CountCols)
		}
		if err != nil {
			pe.logger.Warnf("parsing metadata table %s failed with %v",
				MetadataTableIndexToString(tableIndex), err)
		}
		offset += n

	}

	return nil
}

// String returns a string interpretation of a COMImageFlags type.
func (flags COMImageFlagsType) String() []string {
	COMImageFlags := map[COMImageFlagsType]string{
		COMImageFlagsILOnly:           "IL Only",
		COMImageFlags32BitRequired:    "32-Bit Required",
		COMImageFlagILLibrary:         "IL Library",
		COMImageFlagsStrongNameSigned: "Strong Name Signed",
		COMImageFlagsNativeEntrypoint: "Native Entrypoint",
		COMImageFlagsTrackDebugData:   "Track Debug Data",
		COMImageFlags32BitPreferred:   "32-Bit Preferred",
	}

	var values []string
	for k, v := range COMImageFlags {
		if (k & flags) == k {
			values = append(values, v)
		}
	}

	return values
}


================================================
FILE: dotnet_helper.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

const (
	// these are intentionally made so they do not collide with StringStream, GUIDStream, and BlobStream
	// they are used only for the getCodedIndexSize function
	idxStringStream = iota + 100
	idxGUIDStream
	idxBlobStream
)

type codedidx struct {
	tagbits uint8
	idx     []int
}

var (
	idxTypeDefOrRef        = codedidx{tagbits: 2, idx: []int{TypeDef, TypeRef, TypeSpec}}
	idxResolutionScope     = codedidx{tagbits: 2, idx: []int{Module, ModuleRef, AssemblyRef, TypeRef}}
	idxMemberRefParent     = codedidx{tagbits: 3, idx: []int{TypeDef, TypeRef, ModuleRef, MethodDef, TypeSpec}}
	idxHasConstant         = codedidx{tagbits: 2, idx: []int{Field, Param, Property}}
	idxHasCustomAttributes = codedidx{tagbits: 5, idx: []int{MethodDef, Field, TypeRef, TypeDef, Param, InterfaceImpl, MemberRef, Module, DeclSecurity, Property, Event, StandAloneSig, ModuleRef, TypeSpec, Assembly, AssemblyRef, FileMD, ExportedType, ManifestResource, GenericParam, GenericParamConstraint, MethodSpec}}
	idxCustomAttributeType = codedidx{tagbits: 3, idx: []int{MethodDef, MemberRef}}
	idxHasFieldMarshall    = codedidx{tagbits: 1, idx: []int{Field, Param}}
	idxHasDeclSecurity     = codedidx{tagbits: 2, idx: []int{TypeDef, MethodDef, Assembly}}
	idxHasSemantics        = codedidx{tagbits: 1, idx: []int{Event, Property}}
	idxMethodDefOrRef      = codedidx{tagbits: 1, idx: []int{MethodDef, MemberRef}}
	idxMemberForwarded     = codedidx{tagbits: 1, idx: []int{Field, MethodDef}}
	idxImplementation      = codedidx{tagbits: 2, idx: []int{FileMD, AssemblyRef, ExportedType}}
	idxTypeOrMethodDef     = codedidx{tagbits: 1, idx: []int{TypeDef, MethodDef}}

	idxField        = codedidx{tagbits: 0, idx: []int{Field}}
	idxMethodDef    = codedidx{tagbits: 0, idx: []int{MethodDef}}
	idxParam        = codedidx{tagbits: 0, idx: []int{Param}}
	idxTypeDef      = codedidx{tagbits: 0, idx: []int{TypeDef}}
	idxEvent        = codedidx{tagbits: 0, idx: []int{Event}}
	idxProperty     = codedidx{tagbits: 0, idx: []int{Property}}
	idxModuleRef    = codedidx{tagbits: 0, idx: []int{ModuleRef}}
	idxGenericParam = codedidx{tagbits: 0, idx: []int{GenericParam}}

	idxString = codedidx{tagbits: 0, idx: []int{idxStringStream}}
	idxBlob   = codedidx{tagbits: 0, idx: []int{idxBlobStream}}
	idxGUID   = codedidx{tagbits: 0, idx: []int{idxGUIDStream}}
)

func (pe *File) getCodedIndexSize(tagbits uint32, idx ...int) uint32 {
	// special case String/GUID/Blob streams
	switch idx[0] {
	case int(idxStringStream):
		return uint32(pe.GetMetadataStreamIndexSize(StringStream))
	case int(idxGUIDStream):
		return uint32(pe.GetMetadataStreamIndexSize(GUIDStream))
	case int(idxBlobStream):
		return uint32(pe.GetMetadataStreamIndexSize(BlobStream))
	}

	// now deal with coded indices or single table
	var maxIndex16 uint32 = 1 << (16 - tagbits)
	var maxColumnCount uint32
	for _, tblidx := range idx {
		tbl, ok := pe.CLR.MetadataTables[tblidx]
		if ok {
			if tbl.CountCols > maxColumnCount {
				maxColumnCount = tbl.CountCols
			}
		}
	}
	if maxColumnCount >= maxIndex16 {
		return 4
	}
	return 2
}

func (pe *File) readFromMetadataStream(cidx codedidx, off uint32, out *uint32) (uint32, error) {
	indexSize := pe.getCodedIndexSize(uint32(cidx.tagbits), cidx.idx...)
	var data uint32
	var err error
	switch indexSize {
	case 2:
		d, err := pe.ReadUint16(off)
		if err != nil {
			return 0, err
		}
		data = uint32(d)
	case 4:
		data, err = pe.ReadUint32(off)
		if err != nil {
			return 0, err
		}
	}

	*out = data
	return uint32(indexSize), nil
}


================================================
FILE: dotnet_metadata_tables.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.

package pe

// the struct definition and comments are from the ECMA-335 spec 6th edition
// https://www.ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf

// Module 0x00
type ModuleTableRow struct {
	// a 2-byte value, reserved, shall be zero
	Generation uint16 `json:"generation"`
	// an index into the String heap
	Name uint32 `json:"name"`
	// an index into the Guid heap; simply a Guid used to distinguish between
	// two versions of the same module
	Mvid uint32 `json:"mvid"`
	// an index into the Guid heap; reserved, shall be zero
	EncID uint32 `json:"enc_id"`
	// an index into the Guid heap; reserved, shall be zero
	EncBaseID uint32 `json:"enc_base_id"`
}

// Module 0x00
func (pe *File) parseMetadataModuleTable(off uint32) ([]ModuleTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[Module].CountCols)
	rows := make([]ModuleTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if rows[i].Generation, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].Mvid); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].EncID); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].EncBaseID); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// TypeRef 0x01
type TypeRefTableRow struct {
	// an index into a Module, ModuleRef, AssemblyRef or TypeRef table, or null;
	// more precisely, a ResolutionScope (§II.24.2.6) coded index.
	ResolutionScope uint32 `json:"resolution_scope"`
	// an index into the String heap
	TypeName uint32 `json:"type_name"`
	// an index into the String heap
	TypeNamespace uint32 `json:"type_namespace"`
}

// TypeRef 0x01
func (pe *File) parseMetadataTypeRefTable(off uint32) ([]TypeRefTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[TypeRef].CountCols)
	rows := make([]TypeRefTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if indexSize, err = pe.readFromMetadataStream(idxResolutionScope, off, &rows[i].ResolutionScope); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeName); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeNamespace); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// TypeDef 0x02
type TypeDefTableRow struct {
	// a 4-byte bitmask of type TypeAttributes, §II.23.1.15
	Flags uint32 `json:"flags"`
	// an index into the String heap
	TypeName uint32 `json:"type_name"`
	// an index into the String heap
	TypeNamespace uint32 `json:"type_namespace"`
	// an index into the TypeDef, TypeRef, or TypeSpec table; more precisely,
	// a TypeDefOrRef (§II.24.2.6) coded index
	Extends uint32 `json:"extends"`
	// an index into the Field table; it marks the first of a contiguous run
	// of Fields owned by this Type
	FieldList uint32 `json:"field_list"`
	// an index into the MethodDef table; it marks the first of a contiguous
	// run of Methods owned by this Type
	MethodList uint32 `json:"method_list"`
}

// TypeDef 0x02
func (pe *File) parseMetadataTypeDefTable(off uint32) ([]TypeDefTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[TypeDef].CountCols)
	rows := make([]TypeDefTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if rows[i].Flags, err = pe.ReadUint32(off); err != nil {
			return rows, n, err
		}
		off += 4
		n += 4

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeName); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeNamespace); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxTypeDefOrRef, off, &rows[i].Extends); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxField, off, &rows[i].FieldList); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxMethodDef, off, &rows[i].MethodList); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// Field 0x04
type FieldTableRow struct {
	// a 2-byte bitmask of type FieldAttributes, §II.23.1.5
	Flags uint16 `json:"flags"`
	// an index into the String heap
	Name uint32 `json:"name"`
	// an index into the Blob heap
	Signature uint32 `json:"signature"`
}

// Field 0x04
func (pe *File) parseMetadataFieldTable(off uint32) ([]FieldTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[Field].CountCols)
	rows := make([]FieldTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxBlob, off, &rows[i].Signature); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// MethodDef 0x06
type MethodDefTableRow struct {
	// a 4-byte constant
	RVA uint32 `json:"rva"`
	// a 2-byte bitmask of type MethodImplAttributes, §II.23.1.10
	ImplFlags uint16 `json:"impl_flags"`
	// a 2-byte bitmask of type MethodAttributes, §II.23.1.10
	Flags uint16 `json:"flags"`
	// an index into the String heap
	Name uint32 `json:"name"`
	// an index into the Blob heap
	Signature uint32 `json:"signature"`
	// an index into the Param table
	ParamList uint32 `json:"param_list"`
}

// MethodDef 0x06
func (pe *File) parseMetadataMethodDefTable(off uint32) ([]MethodDefTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[MethodDef].CountCols)
	rows := make([]MethodDefTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if rows[i].RVA, err = pe.ReadUint32(off); err != nil {
			return rows, n, err
		}
		off += 4
		n += 4

		if rows[i].ImplFlags, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxBlob, off, &rows[i].Signature); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize

		if indexSize, err = pe.readFromMetadataStream(idxParam, off, &rows[i].ParamList); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// Param 0x08
type ParamTableRow struct {
	// a 2-byte bitmask of type ParamAttributes, §II.23.1.13
	Flags uint16 `json:"flags"`
	// a 2-byte constant
	Sequence uint16 `json:"sequence"`
	// an index into the String heap
	Name uint32 `json:"name"`
}

// Param 0x08
func (pe *File) parseMetadataParamTable(off uint32) ([]ParamTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[Param].CountCols)
	rows := make([]ParamTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if rows[i].Sequence, err = pe.ReadUint16(off); err != nil {
			return rows, n, err
		}
		off += 2
		n += 2

		if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
			return rows, n, err
		}
		off += indexSize
		n += indexSize
	}
	return rows, n, nil
}

// InterfaceImpl 0x09
type InterfaceImplTableRow struct {
	// an index into the TypeDef table
	Class uint32 `json:"class"`
	// an index into the TypeDef, TypeRef, or TypeSpec table; more precisely,
	// a TypeDefOrRef (§II.24.2.6) coded index
	Interface uint32 `json:"interface"`
}

// InterfaceImpl 0x09
func (pe *File) parseMetadataInterfaceImplTable(off uint32) ([]InterfaceImplTableRow, uint32, error) {
	var err error
	var indexSize uint32
	var n uint32

	rowCount := int(pe.CLR.MetadataTables[InterfaceImpl].CountCols)
	rows := make([]InterfaceImplTableRow, rowCount)
	for i := 0; i < rowCount; i++ {
		if
Download .txt
gitextract_so1rfj4w/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.YML
│   └── workflows/
│       └── ci.yaml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── anomaly.go
├── anomaly_test.go
├── arch.go
├── boundimports.go
├── boundimports_test.go
├── cmd/
│   ├── dump.go
│   ├── main.go
│   ├── size.go
│   └── size_test.go
├── debug.go
├── debug_test.go
├── delayimports.go
├── delayimports_test.go
├── dosheader.go
├── dosheader_test.go
├── dotnet.go
├── dotnet_helper.go
├── dotnet_metadata_tables.go
├── dotnet_test.go
├── exception.go
├── exception_test.go
├── exports.go
├── exports_test.go
├── file.go
├── file_test.go
├── globalptr.go
├── go.mod
├── go.sum
├── helper.go
├── helper_test.go
├── iat.go
├── imports.go
├── imports_test.go
├── loadconfig.go
├── loadconfig_test.go
├── log/
│   ├── README.md
│   ├── filter.go
│   ├── filter_test.go
│   ├── global.go
│   ├── global_test.go
│   ├── helper.go
│   ├── helper_test.go
│   ├── level.go
│   ├── level_test.go
│   ├── log.go
│   ├── log_test.go
│   ├── std.go
│   ├── std_test.go
│   ├── value.go
│   └── value_test.go
├── ntheader.go
├── ntheader_test.go
├── ordlookup.go
├── overlay.go
├── overlay_test.go
├── pe.go
├── reloc.go
├── reloc_test.go
├── resource.go
├── resource_test.go
├── richheader.go
├── richheader_test.go
├── scripts/
│   ├── extract-rsrc-lang.py
│   └── ms-lcid.txt
├── section.go
├── section_test.go
├── security.go
├── security_linux_mac.go
├── security_test.go
├── security_windows.go
├── staticcheck.conf
├── symbol.go
├── symbol_test.go
├── test/
│   ├── WdBoot.sys
│   ├── acpi.sys
│   ├── amdi2c.sys
│   ├── amdxata.sys
│   └── look
├── tls.go
├── tls_test.go
├── version.go
└── version_test.go
Download .txt
SYMBOL INDEX (1452 symbols across 72 files)

FILE: anomaly.go
  method GetAnomalies (line 91) | func (pe *File) GetAnomalies() error {
  method addAnomaly (line 214) | func (pe *File) addAnomaly(anomaly string) {

FILE: anomaly_test.go
  function TestGetAnomalies (line 11) | func TestGetAnomalies(t *testing.T) {

FILE: arch.go
  method parseArchitectureDirectory (line 9) | func (pe *File) parseArchitectureDirectory(rva, size uint32) error {

FILE: boundimports.go
  constant MaxStringLength (line 15) | MaxStringLength = uint32(0x100)
  type ImageBoundImportDescriptor (line 19) | type ImageBoundImportDescriptor struct
  type ImageBoundForwardedRef (line 31) | type ImageBoundForwardedRef struct
  type BoundImportDescriptorData (line 38) | type BoundImportDescriptorData struct
  type BoundForwardedRefData (line 45) | type BoundForwardedRefData struct
  method parseBoundImportDirectory (line 56) | func (pe *File) parseBoundImportDirectory(rva, size uint32) (err error) {

FILE: boundimports_test.go
  type TestBoundImportEntry (line 12) | type TestBoundImportEntry struct
  function TestBoundImportDirectory (line 19) | func TestBoundImportDirectory(t *testing.T) {

FILE: cmd/dump.go
  function loopFilesWorker (line 32) | func loopFilesWorker(cfg config) error {
  function LoopDirsFiles (line 51) | func LoopDirsFiles(path string) error {
  function prettyPrint (line 69) | func prettyPrint(iface interface{}) string {
  function humanizeTimestamp (line 81) | func humanizeTimestamp(ts uint32) string {
  function hexDump (line 86) | func hexDump(b []byte) {
  function hexDumpSize (line 114) | func hexDumpSize(b []byte, size int) {
  function IntToByteArray (line 151) | func IntToByteArray(num uint64) []byte {
  function sentenceCase (line 161) | func sentenceCase(s string) string {
  function isDirectory (line 186) | func isDirectory(path string) bool {
  function parse (line 194) | func parse(filePath string, cfg config) {
  function parsePE (line 217) | func parsePE(filename string, cfg config) {

FILE: cmd/main.go
  type config (line 14) | type config struct
  function main (line 36) | func main() {
  function showHelp (line 129) | func showHelp() {

FILE: cmd/size.go
  constant KB (line 13) | KB = 1000
  constant MB (line 14) | MB = 1000 * KB
  constant GB (line 15) | GB = 1000 * MB
  constant TB (line 16) | TB = 1000 * GB
  constant PB (line 17) | PB = 1000 * TB
  constant KiB (line 21) | KiB = 1024
  constant MiB (line 22) | MiB = 1024 * KiB
  constant GiB (line 23) | GiB = 1024 * MiB
  constant TiB (line 24) | TiB = 1024 * GiB
  constant PiB (line 25) | PiB = 1024 * TiB
  type unitMap (line 28) | type unitMap
  function getSizeAndUnit (line 40) | func getSizeAndUnit(size float64, base float64, _map []string) (float64,...
  function CustomSize (line 52) | func CustomSize(format string, size float64, base float64, _map []string...
  function HumanSizeWithPrecision (line 59) | func HumanSizeWithPrecision(size float64, precision int) string {
  function HumanSize (line 66) | func HumanSize(size float64) string {
  function BytesSize (line 72) | func BytesSize(size float64) string {
  function FromHumanSize (line 78) | func FromHumanSize(size string) (int64, error) {
  function RAMInBytes (line 86) | func RAMInBytes(size string) (int64, error) {
  function parseSize (line 91) | func parseSize(sizeStr string, uMap unitMap) (int64, error) {

FILE: cmd/size_test.go
  function ExampleBytesSize (line 11) | func ExampleBytesSize() {
  function ExampleHumanSize (line 21) | func ExampleHumanSize() {
  function ExampleFromHumanSize (line 32) | func ExampleFromHumanSize() {
  function ExampleRAMInBytes (line 46) | func ExampleRAMInBytes() {
  function TestBytesSize (line 62) | func TestBytesSize(t *testing.T) {
  function TestHumanSize (line 73) | func TestHumanSize(t *testing.T) {
  function TestFromHumanSize (line 85) | func TestFromHumanSize(t *testing.T) {
  function TestRAMInBytes (line 163) | func TestRAMInBytes(t *testing.T) {
  function BenchmarkParseSize (line 194) | func BenchmarkParseSize(b *testing.B) {
  function assertEquals (line 206) | func assertEquals(t *testing.T, expected, actual interface{}) {
  type parseFn (line 214) | type parseFn
    method String (line 217) | func (fn parseFn) String() string {
  function assertSuccessEquals (line 222) | func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg s...
  function assertError (line 230) | func assertError(t *testing.T, fn parseFn, arg string) {

FILE: debug.go
  constant ImageDebugTypeUnknown (line 16) | ImageDebugTypeUnknown = 0
  constant ImageDebugTypeCOFF (line 20) | ImageDebugTypeCOFF = 1
  constant ImageDebugTypeCodeView (line 23) | ImageDebugTypeCodeView = 2
  constant ImageDebugTypeFPO (line 28) | ImageDebugTypeFPO = 3
  constant ImageDebugTypeMisc (line 31) | ImageDebugTypeMisc = 4
  constant ImageDebugTypeException (line 34) | ImageDebugTypeException = 5
  constant ImageDebugTypeFixup (line 37) | ImageDebugTypeFixup = 6
  constant ImageDebugTypeOMAPToSrc (line 40) | ImageDebugTypeOMAPToSrc = 7
  constant ImageDebugTypeOMAPFromSrc (line 43) | ImageDebugTypeOMAPFromSrc = 8
  constant ImageDebugTypeBorland (line 46) | ImageDebugTypeBorland = 9
  constant ImageDebugTypeReserved (line 49) | ImageDebugTypeReserved = 10
  constant ImageDebugTypeCLSID (line 52) | ImageDebugTypeCLSID = 11
  constant ImageDebugTypeVCFeature (line 55) | ImageDebugTypeVCFeature = 12
  constant ImageDebugTypePOGO (line 58) | ImageDebugTypePOGO = 13
  constant ImageDebugTypeILTCG (line 61) | ImageDebugTypeILTCG = 14
  constant ImageDebugTypeMPX (line 64) | ImageDebugTypeMPX = 15
  constant ImageDebugTypeRepro (line 67) | ImageDebugTypeRepro = 16
  constant ImageDebugTypeExDllCharacteristics (line 70) | ImageDebugTypeExDllCharacteristics = 20
  constant CVSignatureRSDS (line 75) | CVSignatureRSDS = 0x53445352
  constant CVSignatureNB10 (line 78) | CVSignatureNB10 = 0x3031424e
  constant FrameFPO (line 83) | FrameFPO = 0x0
  constant FrameTrap (line 86) | FrameTrap = 0x1
  constant FrameTSS (line 89) | FrameTSS = 0x2
  constant FrameNonFPO (line 92) | FrameNonFPO = 0x3
  type DllCharacteristicsExType (line 96) | type DllCharacteristicsExType
    method String (line 760) | func (flag DllCharacteristicsExType) String() string {
  constant ImageDllCharacteristicsExCETCompat (line 101) | ImageDllCharacteristicsExCETCompat = 0x0001
  constant POGOTypePGU (line 106) | POGOTypePGU = 0x50475500
  constant POGOTypePGI (line 108) | POGOTypePGI = 0x50474900
  constant POGOTypePGO (line 110) | POGOTypePGO = 0x50474F00
  constant POGOTypeLTCG (line 112) | POGOTypeLTCG = 0x4c544347
  type ImageDebugDirectoryType (line 116) | type ImageDebugDirectoryType
    method String (line 697) | func (t ImageDebugDirectoryType) String() string {
  type ImageDebugDirectory (line 122) | type ImageDebugDirectory struct
  type DebugEntry (line 150) | type DebugEntry struct
  type GUID (line 164) | type GUID struct
    method String (line 692) | func (g GUID) String() string {
  type CVSignature (line 172) | type CVSignature
    method String (line 745) | func (s CVSignature) String() string {
  type CVInfoPDB70 (line 175) | type CVInfoPDB70 struct
  type CVHeader (line 192) | type CVHeader struct
  type CVInfoPDB20 (line 202) | type CVInfoPDB20 struct
  type FPOFrameType (line 219) | type FPOFrameType
    method String (line 675) | func (ft FPOFrameType) String() string {
  type FPOData (line 224) | type FPOData struct
  type ImagePGOItem (line 257) | type ImagePGOItem struct
  type POGOType (line 264) | type POGOType
    method String (line 728) | func (p POGOType) String() string {
  type POGO (line 269) | type POGO struct
  type VCFeature (line 275) | type VCFeature struct
  type REPRO (line 283) | type REPRO struct
  type ImageDebugMisc (line 289) | type ImageDebugMisc struct
  method parseDebugDirectory (line 313) | func (pe *File) parseDebugDirectory(rva, size uint32) error {
  function SectionAttributeDescription (line 563) | func SectionAttributeDescription(section string) string {

FILE: debug_test.go
  type TestDebugIn (line 12) | type TestDebugIn struct
  function TestDebugDirectoryCodeView (line 17) | func TestDebugDirectoryCodeView(t *testing.T) {
  function TestDebugDirectoryPOGO (line 148) | func TestDebugDirectoryPOGO(t *testing.T) {
  function TestDebugDirectoryREPRO (line 258) | func TestDebugDirectoryREPRO(t *testing.T) {
  function TestDebugDirectoryExDLLCharacteristics (line 342) | func TestDebugDirectoryExDLLCharacteristics(t *testing.T) {
  function TestDebugDirectoryVCFeature (line 426) | func TestDebugDirectoryVCFeature(t *testing.T) {
  function TestDebugDirectoryFPO (line 509) | func TestDebugDirectoryFPO(t *testing.T) {
  function TestDebugSectionAttributes (line 652) | func TestDebugSectionAttributes(t *testing.T) {

FILE: delayimports.go
  type ImageDelayImportDescriptor (line 12) | type ImageDelayImportDescriptor struct
  type DelayImport (line 58) | type DelayImport struct
  method parseDelayImportDirectory (line 69) | func (pe *File) parseDelayImportDirectory(rva, size uint32) error {
  method GetDelayImportEntryInfoByRVA (line 145) | func (pe *File) GetDelayImportEntryInfoByRVA(rva uint32) (DelayImport, i...

FILE: delayimports_test.go
  type TestDelayImportEntry (line 12) | type TestDelayImportEntry struct
  function TestDelayImportDirectory (line 18) | func TestDelayImportDirectory(t *testing.T) {

FILE: dosheader.go
  type ImageDOSHeader (line 12) | type ImageDOSHeader struct
  method ParseDOSHeader (line 76) | func (pe *File) ParseDOSHeader() (err error) {

FILE: dosheader_test.go
  type TestDOSHeader (line 11) | type TestDOSHeader struct
  function TestParseDOSHeader (line 15) | func TestParseDOSHeader(t *testing.T) {
  function TestParseDOSHeaderNonMZ (line 71) | func TestParseDOSHeaderNonMZ(t *testing.T) {

FILE: dotnet.go
  type COMImageFlagsType (line 15) | type COMImageFlagsType
    method String (line 754) | func (flags COMImageFlagsType) String() []string {
  constant COMImageFlagsILOnly (line 22) | COMImageFlagsILOnly = 0x00000001
  constant COMImageFlags32BitRequired (line 25) | COMImageFlags32BitRequired = 0x00000002
  constant COMImageFlagILLibrary (line 30) | COMImageFlagILLibrary = 0x00000004
  constant COMImageFlagsStrongNameSigned (line 33) | COMImageFlagsStrongNameSigned = 0x00000008
  constant COMImageFlagsNativeEntrypoint (line 38) | COMImageFlagsNativeEntrypoint = 0x00000010
  constant COMImageFlagsTrackDebugData (line 42) | COMImageFlagsTrackDebugData = 0x00010000
  constant COMImageFlags32BitPreferred (line 49) | COMImageFlags32BitPreferred = 0x00020000
  constant CORVTable32Bit (line 55) | CORVTable32Bit = 0x01
  constant CORVTable64Bit (line 58) | CORVTable64Bit = 0x02
  constant CORVTableFromUnmanaged (line 62) | CORVTableFromUnmanaged = 0x04
  constant CORVTableFromUnmanagedRetainAppDomain (line 67) | CORVTableFromUnmanagedRetainAppDomain = 0x08
  constant CORVTableCallMostDerived (line 70) | CORVTableCallMostDerived = 0x10
  constant Module (line 76) | Module = 0
  constant TypeRef (line 78) | TypeRef = 1
  constant TypeDef (line 80) | TypeDef = 2
  constant FieldPtr (line 83) | FieldPtr = 3
  constant Field (line 85) | Field = 4
  constant MethodPtr (line 88) | MethodPtr = 5
  constant MethodDef (line 90) | MethodDef = 6
  constant ParamPtr (line 93) | ParamPtr = 7
  constant Param (line 95) | Param = 8
  constant InterfaceImpl (line 97) | InterfaceImpl = 9
  constant MemberRef (line 99) | MemberRef = 10
  constant Constant (line 102) | Constant = 11
  constant CustomAttribute (line 104) | CustomAttribute = 12
  constant FieldMarshal (line 107) | FieldMarshal = 13
  constant DeclSecurity (line 109) | DeclSecurity = 14
  constant ClassLayout (line 112) | ClassLayout = 15
  constant FieldLayout (line 115) | FieldLayout = 16
  constant StandAloneSig (line 119) | StandAloneSig = 17
  constant EventMap (line 122) | EventMap = 18
  constant EventPtr (line 125) | EventPtr = 19
  constant Event (line 127) | Event = 20
  constant PropertyMap (line 130) | PropertyMap = 21
  constant PropertyPtr (line 133) | PropertyPtr = 22
  constant Property (line 135) | Property = 23
  constant MethodSemantics (line 138) | MethodSemantics = 24
  constant MethodImpl (line 140) | MethodImpl = 25
  constant ModuleRef (line 142) | ModuleRef = 26
  constant TypeSpec (line 144) | TypeSpec = 27
  constant ImplMap (line 147) | ImplMap = 28
  constant FieldRVA (line 149) | FieldRVA = 29
  constant ENCLog (line 153) | ENCLog = 30
  constant ENCMap (line 156) | ENCMap = 31
  constant Assembly (line 159) | Assembly = 32
  constant AssemblyProcessor (line 161) | AssemblyProcessor = 33
  constant AssemblyOS (line 163) | AssemblyOS = 34
  constant AssemblyRef (line 165) | AssemblyRef = 35
  constant AssemblyRefProcessor (line 167) | AssemblyRefProcessor = 36
  constant AssemblyRefOS (line 169) | AssemblyRefOS = 37
  constant FileMD (line 172) | FileMD = 38
  constant ExportedType (line 177) | ExportedType = 39
  constant ManifestResource (line 179) | ManifestResource = 40
  constant NestedClass (line 182) | NestedClass = 41
  constant GenericParam (line 185) | GenericParam = 42
  constant MethodSpec (line 187) | MethodSpec = 43
  constant GenericParamConstraint (line 190) | GenericParamConstraint = 44
  constant StringStream (line 195) | StringStream = 0
  constant GUIDStream (line 196) | GUIDStream   = 1
  constant BlobStream (line 197) | BlobStream   = 2
  function MetadataTableIndexToString (line 202) | func MetadataTableIndexToString(k int) string {
  method GetMetadataStreamIndexSize (line 259) | func (pe *File) GetMetadataStreamIndexSize(BitPosition int) int {
  type ImageDataDirectory (line 275) | type ImageDataDirectory struct
  type ImageCOR20Header (line 285) | type ImageCOR20Header struct
  type ImageCORVTableFixup (line 362) | type ImageCORVTableFixup struct
  type MetadataHeader (line 369) | type MetadataHeader struct
  type MetadataStreamHeader (line 406) | type MetadataStreamHeader struct
  type MetadataTableStreamHeader (line 421) | type MetadataTableStreamHeader struct
  type MetadataTable (line 457) | type MetadataTable struct
  type CLRData (line 471) | type CLRData struct
  method parseMetadataStream (line 483) | func (pe *File) parseMetadataStream(off, size uint32) (MetadataTableStre...
  method parseMetadataHeader (line 498) | func (pe *File) parseMetadataHeader(offset, size uint32) (MetadataHeader...
  method parseCLRHeaderDirectory (line 539) | func (pe *File) parseCLRHeaderDirectory(rva, size uint32) error {

FILE: dotnet_helper.go
  constant idxStringStream (line 10) | idxStringStream = iota + 100
  constant idxGUIDStream (line 11) | idxGUIDStream
  constant idxBlobStream (line 12) | idxBlobStream
  type codedidx (line 15) | type codedidx struct
  method getCodedIndexSize (line 49) | func (pe *File) getCodedIndexSize(tagbits uint32, idx ...int) uint32 {
  method readFromMetadataStream (line 77) | func (pe *File) readFromMetadataStream(cidx codedidx, off uint32, out *u...

FILE: dotnet_metadata_tables.go
  type ModuleTableRow (line 11) | type ModuleTableRow struct
  method parseMetadataModuleTable (line 26) | func (pe *File) parseMetadataModuleTable(off uint32) ([]ModuleTableRow, ...
  type TypeRefTableRow (line 68) | type TypeRefTableRow struct
  method parseMetadataTypeRefTable (line 79) | func (pe *File) parseMetadataTypeRefTable(off uint32) ([]TypeRefTableRow...
  type TypeDefTableRow (line 109) | type TypeDefTableRow struct
  method parseMetadataTypeDefTable (line 128) | func (pe *File) parseMetadataTypeDefTable(off uint32) ([]TypeDefTableRow...
  type FieldTableRow (line 176) | type FieldTableRow struct
  method parseMetadataFieldTable (line 186) | func (pe *File) parseMetadataFieldTable(off uint32) ([]FieldTableRow, ui...
  type MethodDefTableRow (line 216) | type MethodDefTableRow struct
  method parseMetadataMethodDefTable (line 232) | func (pe *File) parseMetadataMethodDefTable(off uint32) ([]MethodDefTabl...
  type ParamTableRow (line 280) | type ParamTableRow struct
  method parseMetadataParamTable (line 290) | func (pe *File) parseMetadataParamTable(off uint32) ([]ParamTableRow, ui...
  type InterfaceImplTableRow (line 320) | type InterfaceImplTableRow struct
  method parseMetadataInterfaceImplTable (line 329) | func (pe *File) parseMetadataInterfaceImplTable(off uint32) ([]Interface...
  type MemberRefTableRow (line 353) | type MemberRefTableRow struct
  method parseMetadataMemberRefTable (line 364) | func (pe *File) parseMetadataMemberRefTable(off uint32) ([]MemberRefTabl...
  type ConstantTableRow (line 395) | type ConstantTableRow struct
  method parseMetadataConstantTable (line 409) | func (pe *File) parseMetadataConstantTable(off uint32) ([]ConstantTableR...
  type CustomAttributeTableRow (line 445) | type CustomAttributeTableRow struct
  method parseMetadataCustomAttributeTable (line 457) | func (pe *File) parseMetadataCustomAttributeTable(off uint32) ([]CustomA...
  type FieldMarshalTableRow (line 487) | type FieldMarshalTableRow struct
  method parseMetadataFieldMarshalTable (line 496) | func (pe *File) parseMetadataFieldMarshalTable(off uint32) ([]FieldMarsh...
  type DeclSecurityTableRow (line 520) | type DeclSecurityTableRow struct
  method parseMetadataDeclSecurityTable (line 531) | func (pe *File) parseMetadataDeclSecurityTable(off uint32) ([]DeclSecuri...
  type ClassLayoutTableRow (line 561) | type ClassLayoutTableRow struct
  method parseMetadataClassLayoutTable (line 571) | func (pe *File) parseMetadataClassLayoutTable(off uint32) ([]ClassLayout...
  type FieldLayoutTableRow (line 601) | type FieldLayoutTableRow struct
  method parseMetadataFieldLayoutTable (line 607) | func (pe *File) parseMetadataFieldLayoutTable(off uint32) ([]FieldLayout...
  type StandAloneSigTableRow (line 631) | type StandAloneSigTableRow struct
  method parseMetadataStandAloneSignTable (line 636) | func (pe *File) parseMetadataStandAloneSignTable(off uint32) ([]StandAlo...
  type EventMapTableRow (line 654) | type EventMapTableRow struct
  method parseMetadataEventMapTable (line 662) | func (pe *File) parseMetadataEventMapTable(off uint32) ([]EventMapTableR...
  type EventTableRow (line 687) | type EventTableRow struct
  method parseMetadataEventTable (line 698) | func (pe *File) parseMetadataEventTable(off uint32) ([]EventTableRow, ui...
  type PropertyMapTableRow (line 728) | type PropertyMapTableRow struct
  method parseMetadataPropertyMapTable (line 736) | func (pe *File) parseMetadataPropertyMapTable(off uint32) ([]PropertyMap...
  type PropertyTableRow (line 760) | type PropertyTableRow struct
  method parseMetadataPropertyTable (line 770) | func (pe *File) parseMetadataPropertyTable(off uint32) ([]PropertyTableR...
  type MethodSemanticsTableRow (line 800) | type MethodSemanticsTableRow struct
  method parseMetadataMethodSemanticsTable (line 811) | func (pe *File) parseMetadataMethodSemanticsTable(off uint32) ([]MethodS...
  type MethodImplTableRow (line 841) | type MethodImplTableRow struct
  method parseMetadataMethodImplTable (line 853) | func (pe *File) parseMetadataMethodImplTable(off uint32) ([]MethodImplTa...
  type ModuleRefTableRow (line 883) | type ModuleRefTableRow struct
  method parseMetadataModuleRefTable (line 889) | func (pe *File) parseMetadataModuleRefTable(off uint32) ([]ModuleRefTabl...
  type TypeSpecTableRow (line 907) | type TypeSpecTableRow struct
  method parseMetadataTypeSpecTable (line 913) | func (pe *File) parseMetadataTypeSpecTable(off uint32) ([]TypeSpecTableR...
  type ImplMapTableRow (line 931) | type ImplMapTableRow struct
  method parseMetadataImplMapTable (line 944) | func (pe *File) parseMetadataImplMapTable(off uint32) ([]ImplMapTableRow...
  type FieldRVATableRow (line 980) | type FieldRVATableRow struct
  method parseMetadataFieldRVATable (line 988) | func (pe *File) parseMetadataFieldRVATable(off uint32) ([]FieldRVATableR...
  type AssemblyTableRow (line 1012) | type AssemblyTableRow struct
  method parseMetadataAssemblyTable (line 1034) | func (pe *File) parseMetadataAssemblyTable(off uint32) ([]AssemblyTableR...
  type AssemblyProcessorTableRow (line 1100) | type AssemblyProcessorTableRow struct
  type AssemblyOSTableRow (line 1105) | type AssemblyOSTableRow struct
  type AssemblyRefTableRow (line 1112) | type AssemblyRefTableRow struct
  method parseMetadataAssemblyRefTable (line 1125) | func (pe *File) parseMetadataAssemblyRefTable(off uint32) ([]AssemblyRef...
  type AssemblyRefProcessorTableRow (line 1191) | type AssemblyRefProcessorTableRow struct
  type AssemblyRefOSTableRow (line 1197) | type AssemblyRefOSTableRow struct
  type ExportedTypeTableRow (line 1205) | type ExportedTypeTableRow struct
  method parseMetadataExportedTypeTable (line 1214) | func (pe *File) parseMetadataExportedTypeTable(off uint32) ([]ExportedTy...
  type ManifestResourceTableRow (line 1256) | type ManifestResourceTableRow struct
  method parseMetadataManifestResourceTable (line 1264) | func (pe *File) parseMetadataManifestResourceTable(off uint32) ([]Manife...
  type NestedClassTableRow (line 1300) | type NestedClassTableRow struct
  method parseMetadataNestedClassTable (line 1306) | func (pe *File) parseMetadataNestedClassTable(off uint32) ([]NestedClass...
  type GenericParamTableRow (line 1330) | type GenericParamTableRow struct
  method parseMetadataGenericParamTable (line 1338) | func (pe *File) parseMetadataGenericParamTable(off uint32) ([]GenericPar...
  type MethodSpecTableRow (line 1373) | type MethodSpecTableRow struct
  method parseMetadataMethodSpecTable (line 1379) | func (pe *File) parseMetadataMethodSpecTable(off uint32) ([]MethodSpecTa...
  type GenericParamConstraintTableRow (line 1403) | type GenericParamConstraintTableRow struct
  method parseMetadataGenericParamConstraintTable (line 1409) | func (pe *File) parseMetadataGenericParamConstraintTable(off uint32) ([]...
  type FileTableRow (line 1433) | type FileTableRow struct
  method parseMetadataFileTable (line 1440) | func (pe *File) parseMetadataFileTable(off uint32) ([]FileTableRow, uint...

FILE: dotnet_test.go
  function TestClrDirectoryHeaders (line 14) | func TestClrDirectoryHeaders(t *testing.T) {
  function TestClrDirectoryMetadataTables (line 144) | func TestClrDirectoryMetadataTables(t *testing.T) {
  function TestClrDirectorCOMImageFlagsType (line 841) | func TestClrDirectorCOMImageFlagsType(t *testing.T) {
  function TestClrDirectoryMalformed (line 865) | func TestClrDirectoryMalformed(t *testing.T) {

FILE: exception.go
  constant UnwFlagNHandler (line 16) | UnwFlagNHandler = uint8(0x0)
  constant UnwFlagEHandler (line 20) | UnwFlagEHandler = uint8(0x1)
  constant UnwFlagUHandler (line 24) | UnwFlagUHandler = uint8(0x2)
  constant UnwFlagChainInfo (line 33) | UnwFlagChainInfo = uint8(0x4)
  constant rax (line 39) | rax = iota
  constant rcx (line 40) | rcx
  constant rdx (line 41) | rdx
  constant rbx (line 42) | rbx
  constant rsp (line 43) | rsp
  constant rbp (line 44) | rbp
  constant rsi (line 45) | rsi
  constant rdi (line 46) | rdi
  constant r8 (line 47) | r8
  constant r9 (line 48) | r9
  constant r10 (line 49) | r10
  constant r11 (line 50) | r11
  constant r12 (line 51) | r12
  constant r13 (line 52) | r13
  constant r14 (line 53) | r14
  constant r15 (line 54) | r15
  type UnwindOpType (line 78) | type UnwindOpType
    method String (line 576) | func (uo UnwindOpType) String() string {
  constant UwOpPushNonVol (line 87) | UwOpPushNonVol = UnwindOpType(0)
  constant UwOpAllocLarge (line 95) | UwOpAllocLarge = UnwindOpType(1)
  constant UwOpAllocSmall (line 100) | UwOpAllocSmall = UnwindOpType(2)
  constant UwOpSetFpReg (line 109) | UwOpSetFpReg = UnwindOpType(3)
  constant UwOpSaveNonVol (line 117) | UwOpSaveNonVol = UnwindOpType(4)
  constant UwOpSaveNonVolFar (line 125) | UwOpSaveNonVolFar = UnwindOpType(5)
  constant UwOpEpilog (line 133) | UwOpEpilog = UnwindOpType(6)
  constant UwOpSpareCode (line 141) | UwOpSpareCode = UnwindOpType(7)
  constant UwOpSaveXmm128 (line 146) | UwOpSaveXmm128 = UnwindOpType(8)
  constant UwOpSaveXmm128Far (line 151) | UwOpSaveXmm128Far = UnwindOpType(9)
  constant UwOpPushMachFrame (line 155) | UwOpPushMachFrame = UnwindOpType(10)
  constant UwOpSetFpRegLarge (line 171) | UwOpSetFpRegLarge = UnwindOpType(11)
  type ImageRuntimeFunctionEntry (line 178) | type ImageRuntimeFunctionEntry struct
  type ImageARMRuntimeFunctionEntry (line 193) | type ImageARMRuntimeFunctionEntry struct
  type UnwindCode (line 238) | type UnwindCode struct
  type UnwindInfo (line 258) | type UnwindInfo struct
  type ScopeRecord (line 317) | type ScopeRecord struct
  type ScopeTable (line 340) | type ScopeTable struct
  type Exception (line 360) | type Exception struct
  method parseUnwindCode (line 365) | func (pe *File) parseUnwindCode(offset uint32, version uint8) (UnwindCod...
  method parseUnwindInfo (line 445) | func (pe *File) parseUnwindInfo(unwindInfo uint32) UnwindInfo {
  method parseExceptionDirectory (line 521) | func (pe *File) parseExceptionDirectory(rva, size uint32) error {
  function PrettyUnwindInfoHandlerFlags (line 557) | func PrettyUnwindInfoHandlerFlags(flags uint8) []string {

FILE: exception_test.go
  type TestExceptionEntry (line 13) | type TestExceptionEntry struct
  function TestParseExceptionDirectory (line 20) | func TestParseExceptionDirectory(t *testing.T) {
  function TestExceptionDirectoryUnwindOpcode (line 121) | func TestExceptionDirectoryUnwindOpcode(t *testing.T) {

FILE: exports.go
  constant maxExportedSymbols (line 14) | maxExportedSymbols = 0x2000
  type ImageExportDirectory (line 27) | type ImageExportDirectory struct
  type ExportFunction (line 69) | type ExportFunction struct
  type Export (line 80) | type Export struct
  method parseExportDirectory (line 101) | func (pe *File) parseExportDirectory(rva, size uint32) error {
  method GetExportFunctionByRVA (line 322) | func (pe *File) GetExportFunctionByRVA(rva uint32) ExportFunction {

FILE: exports_test.go
  type TestExport (line 11) | type TestExport struct
  function TestExportDirectory (line 19) | func TestExportDirectory(t *testing.T) {

FILE: file.go
  type File (line 17) | type File struct
    method Close (line 199) | func (pe *File) Close() error {
    method Unmap (line 209) | func (pe *File) Unmap() error {
    method Parse (line 218) | func (pe *File) Parse() error {
    method ParseDataDirectories (line 291) | func (pe *File) ParseDataDirectories() error {
  type Options (line 49) | type Options struct
  function New (line 121) | func New(name string, opts *Options) (*File, error) {
  function NewFile (line 131) | func NewFile(f *os.File, opts *Options) (*File, error) {
  function NewBytes (line 169) | func NewBytes(data []byte, opts *Options) (*File, error) {
  method String (line 265) | func (entry ImageDirectoryEntry) String() string {

FILE: file_test.go
  function TestParse (line 20) | func TestParse(t *testing.T) {
  function TestParseOmitDirectories (line 36) | func TestParseOmitDirectories(t *testing.T) {
  function TestNewBytes (line 56) | func TestNewBytes(t *testing.T) {
  function TestChecksum (line 73) | func TestChecksum(t *testing.T) {
  function TestCanParseWithHandleAndClose (line 107) | func TestCanParseWithHandleAndClose(t *testing.T) {

FILE: globalptr.go
  constant AnoInvalidGlobalPtrReg (line 9) | AnoInvalidGlobalPtrReg = "Global pointer register offset outside of PE i...
  method parseGlobalPtrDirectory (line 16) | func (pe *File) parseGlobalPtrDirectory(rva, size uint32) error {

FILE: helper.go
  constant TinyPESize (line 20) | TinyPESize = 97
  constant FileAlignmentHardcodedValue (line 26) | FileAlignmentHardcodedValue = 0x200
  function Max (line 96) | func Max(x, y uint32) uint32 {
  function min (line 103) | func min(a, b uint32) uint32 {
  function Min (line 111) | func Min(values []uint32) uint32 {
  function IsValidDosFilename (line 126) | func IsValidDosFilename(filename string) bool {
  function IsValidFunctionName (line 142) | func IsValidFunctionName(functionName string) bool {
  function IsPrintable (line 156) | func IsPrintable(s string) bool {
  method getSectionByRva (line 171) | func (pe *File) getSectionByRva(rva uint32) *Section {
  method getSectionNameByRva (line 181) | func (pe *File) getSectionNameByRva(rva uint32) string {
  method getSectionByOffset (line 190) | func (pe *File) getSectionByOffset(offset uint32) *Section {
  method GetOffsetFromRva (line 207) | func (pe *File) GetOffsetFromRva(rva uint32) uint32 {
  method GetRVAFromOffset (line 224) | func (pe *File) GetRVAFromOffset(offset uint32) uint32 {
  method getSectionByName (line 256) | func (pe *File) getSectionByName(secName string) (section *ImageSectionH...
  method getStringAtRVA (line 267) | func (pe *File) getStringAtRVA(rva, maxLen uint32) string {
  method readUnicodeStringAtRVA (line 289) | func (pe *File) readUnicodeStringAtRVA(rva uint32, maxLength uint32) str...
  method readASCIIStringAtOffset (line 303) | func (pe *File) readASCIIStringAtOffset(offset, maxLength uint32) (uint3...
  method GetStringFromData (line 318) | func (pe *File) GetStringFromData(offset uint32, data []byte) []byte {
  method getStringAtOffset (line 340) | func (pe *File) getStringAtOffset(offset, size uint32) (string, error) {
  method GetData (line 351) | func (pe *File) GetData(rva, length uint32) ([]byte, error) {
  method adjustFileAlignment (line 389) | func (pe *File) adjustFileAlignment(va uint32) uint32 {
  method adjustSectionAlignment (line 419) | func (pe *File) adjustSectionAlignment(va uint32) uint32 {
  function alignDword (line 449) | func alignDword(offset, base uint32) uint32 {
  function stringInSlice (line 454) | func stringInSlice(a string, list []string) bool {
  function intInSlice (line 464) | func intInSlice(a uint32, list []uint32) bool {
  method IsDriver (line 474) | func (pe *File) IsDriver() bool {
  method IsDLL (line 531) | func (pe *File) IsDLL() bool {
  method IsEXE (line 536) | func (pe *File) IsEXE() bool {
  method Checksum (line 552) | func (pe *File) Checksum() uint32 {
  method ReadUint64 (line 600) | func (pe *File) ReadUint64(offset uint32) (uint64, error) {
  method ReadUint32 (line 609) | func (pe *File) ReadUint32(offset uint32) (uint32, error) {
  method ReadUint16 (line 618) | func (pe *File) ReadUint16(offset uint32) (uint16, error) {
  method ReadUint8 (line 627) | func (pe *File) ReadUint8(offset uint32) (uint8, error) {
  method structUnpack (line 636) | func (pe *File) structUnpack(iface interface{}, offset, size uint32) (er...
  method ReadBytesAtOffset (line 658) | func (pe *File) ReadBytesAtOffset(offset, size uint32) ([]byte, error) {
  function DecodeUTF16String (line 675) | func DecodeUTF16String(b []byte) (string, error) {
  function IsBitSet (line 689) | func IsBitSet(n uint64, pos int) bool {
  function getAbsoluteFilePath (line 694) | func getAbsoluteFilePath(testfile string) string {

FILE: helper_test.go
  function TestIsEXE (line 11) | func TestIsEXE(t *testing.T) {
  function TestIsDLL (line 40) | func TestIsDLL(t *testing.T) {
  function TestIsDriver (line 69) | func TestIsDriver(t *testing.T) {

FILE: iat.go
  type IATEntry (line 8) | type IATEntry struct
  method parseIATDirectory (line 28) | func (pe *File) parseIATDirectory(rva, size uint32) error {

FILE: imports.go
  constant imageOrdinalFlag32 (line 18) | imageOrdinalFlag32   = uint32(0x80000000)
  constant imageOrdinalFlag64 (line 19) | imageOrdinalFlag64   = uint64(0x8000000000000000)
  constant maxRepeatedAddresses (line 20) | maxRepeatedAddresses = uint32(0xF)
  constant maxAddressSpread (line 21) | maxAddressSpread     = uint32(0x8000000)
  constant addressMask32 (line 22) | addressMask32        = uint32(0x7fffffff)
  constant addressMask64 (line 23) | addressMask64        = uint64(0x7fffffffffffffff)
  constant maxDllLength (line 24) | maxDllLength         = 0x200
  constant maxImportNameLength (line 25) | maxImportNameLength  = 0x200
  type ImageImportDescriptor (line 55) | type ImageImportDescriptor struct
  type ImageThunkData32 (line 85) | type ImageThunkData32 struct
  type ImageThunkData64 (line 90) | type ImageThunkData64 struct
  type ThunkData32 (line 94) | type ThunkData32 struct
  type ThunkData64 (line 99) | type ThunkData64 struct
  type ImportFunction (line 105) | type ImportFunction struct
  type Import (line 137) | type Import struct
  method parseImportDirectory (line 144) | func (pe *File) parseImportDirectory(rva, size uint32) (err error) {
  method getImportTable32 (line 211) | func (pe *File) getImportTable32(rva uint32, maxLen uint32,
  method getImportTable64 (line 336) | func (pe *File) getImportTable64(rva uint32, maxLen uint32,
  method parseImports32 (line 463) | func (pe *File) parseImports32(importDesc interface{}, maxLen uint32) (
  method parseImports64 (line 597) | func (pe *File) parseImports64(importDesc interface{}, maxLen uint32) ([...
  method GetImportEntryInfoByRVA (line 733) | func (pe *File) GetImportEntryInfoByRVA(rva uint32) (Import, int) {
  function md5hash (line 746) | func md5hash(text string) string {
  method ImpHash (line 759) | func (pe *File) ImpHash() (string, error) {

FILE: imports_test.go
  type TestImportEntry (line 12) | type TestImportEntry struct
  function TestImportDirectory (line 18) | func TestImportDirectory(t *testing.T) {
  function TestImpHash (line 130) | func TestImpHash(t *testing.T) {

FILE: loadconfig.go
  type ImageGuardFlagType (line 25) | type ImageGuardFlagType
    method String (line 1517) | func (flag ImageGuardFlagType) String() string {
  constant ImageGuardFlagFIDSuppressed (line 31) | ImageGuardFlagFIDSuppressed = 0x1
  constant ImageGuardFlagExportSuppressed (line 35) | ImageGuardFlagExportSuppressed = 0x2
  constant ImageGuardCfInstrumented (line 43) | ImageGuardCfInstrumented = 0x00000100
  constant ImageGuardCfWInstrumented (line 47) | ImageGuardCfWInstrumented = 0x00000200
  constant ImageGuardCfFunctionTablePresent (line 51) | ImageGuardCfFunctionTablePresent = 0x00000400
  constant ImageGuardSecurityCookieUnused (line 55) | ImageGuardSecurityCookieUnused = 0x00000800
  constant ImageGuardProtectDelayLoadIAT (line 59) | ImageGuardProtectDelayLoadIAT = 0x00001000
  constant ImageGuardDelayLoadIATInItsOwnSection (line 64) | ImageGuardDelayLoadIATInItsOwnSection = 0x00002000
  constant ImageGuardCfExportSuppressionInfoPresent (line 69) | ImageGuardCfExportSuppressionInfoPresent = 0x00004000
  constant ImageGuardCfEnableExportSuppression (line 73) | ImageGuardCfEnableExportSuppression = 0x00008000
  constant ImageGuardCfLongJumpTablePresent (line 77) | ImageGuardCfLongJumpTablePresent = 0x00010000
  constant ImageGuardCfFunctionTableSizeMask (line 84) | ImageGuardCfFunctionTableSizeMask = 0xF0000000
  constant ImageGuardCfFunctionTableSizeShift (line 88) | ImageGuardCfFunctionTableSizeShift = 28
  constant ImageDynamicRelocationGuardRfPrologue (line 92) | ImageDynamicRelocationGuardRfPrologue = 0x00000001
  constant ImageDynamicRelocationGuardREpilogue (line 93) | ImageDynamicRelocationGuardREpilogue  = 0x00000002
  constant ImageEnclaveLongIDLength (line 98) | ImageEnclaveLongIDLength  = 32
  constant ImageEnclaveShortIDLength (line 99) | ImageEnclaveShortIDLength = 16
  constant ImageEnclaveImportMatchNone (line 105) | ImageEnclaveImportMatchNone = 0x00000000
  constant ImageEnclaveImportMatchUniqueID (line 110) | ImageEnclaveImportMatchUniqueID = 0x00000001
  constant ImageEnclaveImportMatchAuthorID (line 117) | ImageEnclaveImportMatchAuthorID = 0x00000002
  constant ImageEnclaveImportMatchFamilyID (line 122) | ImageEnclaveImportMatchFamilyID = 0x00000003
  constant ImageEnclaveImportMatchImageID (line 127) | ImageEnclaveImportMatchImageID = 0x00000004
  type ImageLoadConfigDirectory32 (line 131) | type ImageLoadConfigDirectory32 struct
  type ImageLoadConfigDirectory64 (line 257) | type ImageLoadConfigDirectory64 struct
  type ImageCHPEMetadataX86 (line 383) | type ImageCHPEMetadataX86 struct
  type CodeRange (line 398) | type CodeRange struct
  type CompilerIAT (line 404) | type CompilerIAT struct
  type HybridPE (line 410) | type HybridPE struct
  type ImageDynamicRelocationTable (line 417) | type ImageDynamicRelocationTable struct
  type ImageDynamicRelocation32 (line 430) | type ImageDynamicRelocation32 struct
  type ImageDynamicRelocation64 (line 442) | type ImageDynamicRelocation64 struct
  type ImageDynamicRelocation32v2 (line 453) | type ImageDynamicRelocation32v2 struct
  type ImageDynamicRelocation64v2 (line 463) | type ImageDynamicRelocation64v2 struct
  type ImagePrologueDynamicRelocationHeader (line 473) | type ImagePrologueDynamicRelocationHeader struct
  type ImageEpilogueDynamicRelocationHeader (line 478) | type ImageEpilogueDynamicRelocationHeader struct
  type CFGFunction (line 487) | type CFGFunction struct
  type CFGIATEntry (line 496) | type CFGIATEntry struct
  type RelocBlock (line 503) | type RelocBlock struct
  type RelocEntry (line 507) | type RelocEntry struct
  type ImageImportControlTransferDynamicRelocation (line 515) | type ImageImportControlTransferDynamicRelocation struct
  type ImageIndirectControlTransferDynamicRelocation (line 525) | type ImageIndirectControlTransferDynamicRelocation struct
  type ImageSwitchableBranchDynamicRelocation (line 535) | type ImageSwitchableBranchDynamicRelocation struct
  type DVRT (line 551) | type DVRT struct
  type Enclave (line 556) | type Enclave struct
  type RangeTableEntry (line 564) | type RangeTableEntry struct
  type VolatileMetadata (line 569) | type VolatileMetadata struct
  type LoadConfig (line 574) | type LoadConfig struct
  type ImageLoadConfigCodeIntegrity (line 587) | type ImageLoadConfigCodeIntegrity struct
  type ImageEnclaveConfig32 (line 597) | type ImageEnclaveConfig32 struct
  type ImageEnclaveConfig64 (line 656) | type ImageEnclaveConfig64 struct
  type ImageEnclaveImport (line 715) | type ImageEnclaveImport struct
  type ImageVolatileMetadata (line 746) | type ImageVolatileMetadata struct
  method parseLoadConfigDirectory (line 767) | func (pe *File) parseLoadConfigDirectory(rva, size uint32) error {
  function StringifyGuardFlags (line 856) | func StringifyGuardFlags(flags uint32) []string {
  method getSEHHandlers (line 878) | func (pe *File) getSEHHandlers() []uint32 {
  method getControlFlowGuardFunctions (line 903) | func (pe *File) getControlFlowGuardFunctions() []CFGFunction {
  method getControlFlowGuardIAT (line 980) | func (pe *File) getControlFlowGuardIAT() []CFGIATEntry {
  method getLongJumpTargetTable (line 1047) | func (pe *File) getLongJumpTargetTable() []uint32 {
  method getHybridPE (line 1095) | func (pe *File) getHybridPE() *HybridPE {
  method getDynamicValueRelocTable (line 1227) | func (pe *File) getDynamicValueRelocTable() *DVRT {
  method getEnclaveConfiguration (line 1395) | func (pe *File) getEnclaveConfiguration() *Enclave {
  method getVolatileMetadata (line 1451) | func (pe *File) getVolatileMetadata() *VolatileMetadata {

FILE: loadconfig_test.go
  function TestLoadConfigDirectory (line 12) | func TestLoadConfigDirectory(t *testing.T) {
  function TestLoadConfigDirectorySEHHandlers (line 209) | func TestLoadConfigDirectorySEHHandlers(t *testing.T) {
  function TestLoadConfigDirectoryControlFlowGuardFunctions (line 264) | func TestLoadConfigDirectoryControlFlowGuardFunctions(t *testing.T) {
  function TestLoadConfigDirectoryControlFlowGuardIAT (line 351) | func TestLoadConfigDirectoryControlFlowGuardIAT(t *testing.T) {
  function TestLoadConfigDirectoryControlFlowGuardLongJump (line 440) | func TestLoadConfigDirectoryControlFlowGuardLongJump(t *testing.T) {
  function TestLoadConfigDirectoryHybridPE (line 499) | func TestLoadConfigDirectoryHybridPE(t *testing.T) {
  function TestLoadConfigDirectoryDVRT (line 604) | func TestLoadConfigDirectoryDVRT(t *testing.T) {
  function TestLoadConfigDirectoryDVRTRetpolineType (line 675) | func TestLoadConfigDirectoryDVRTRetpolineType(t *testing.T) {
  function TestLoadConfigDirectoryEnclave (line 820) | func TestLoadConfigDirectoryEnclave(t *testing.T) {
  function TestLoadConfigDirectoryVolatileMetadata (line 915) | func TestLoadConfigDirectoryVolatileMetadata(t *testing.T) {
  function TestLoadConfigDirectoryCorruptSize (line 1020) | func TestLoadConfigDirectoryCorruptSize(t *testing.T) {

FILE: log/filter.go
  type FilterOption (line 4) | type FilterOption
  constant fuzzyStr (line 6) | fuzzyStr = "***"
  function FilterLevel (line 9) | func FilterLevel(level Level) FilterOption {
  function FilterKey (line 16) | func FilterKey(key ...string) FilterOption {
  function FilterValue (line 25) | func FilterValue(value ...string) FilterOption {
  function FilterFunc (line 34) | func FilterFunc(f func(level Level, keyvals ...interface{}) bool) Filter...
  type Filter (line 41) | type Filter struct
    method Log (line 63) | func (f *Filter) Log(level Level, keyvals ...interface{}) error {
  function NewFilter (line 50) | func NewFilter(logger Logger, opts ...FilterOption) *Filter {

FILE: log/filter_test.go
  function TestFilterAll (line 9) | func TestFilterAll(t *testing.T) {
  function TestFilterLevel (line 24) | func TestFilterLevel(t *testing.T) {
  function TestFilterCaller (line 34) | func TestFilterCaller(t *testing.T) {
  function TestFilterKey (line 42) | func TestFilterKey(t *testing.T) {
  function TestFilterValue (line 48) | func TestFilterValue(t *testing.T) {
  function TestFilterFunc (line 54) | func TestFilterFunc(t *testing.T) {
  function BenchmarkFilterKey (line 61) | func BenchmarkFilterKey(b *testing.B) {
  function BenchmarkFilterValue (line 68) | func BenchmarkFilterValue(b *testing.B) {
  function BenchmarkFilterFunc (line 75) | func BenchmarkFilterFunc(b *testing.B) {
  function testFilterFunc (line 82) | func testFilterFunc(level Level, keyvals ...interface{}) bool {
  function TestFilterFuncWitchLoggerPrefix (line 94) | func TestFilterFuncWitchLoggerPrefix(t *testing.T) {
  function testFilterFuncWithLoggerPrefix (line 123) | func testFilterFuncWithLoggerPrefix(level Level, keyvals ...interface{})...

FILE: log/global.go
  type loggerAppliance (line 12) | type loggerAppliance struct
    method SetLogger (line 22) | func (a *loggerAppliance) SetLogger(in Logger) {
    method GetLogger (line 29) | func (a *loggerAppliance) GetLogger() Logger {
  function init (line 18) | func init() {
  function SetLogger (line 35) | func SetLogger(logger Logger) {
  function GetLogger (line 40) | func GetLogger() Logger {
  function Log (line 45) | func Log(level Level, keyvals ...interface{}) {
  function Debug (line 50) | func Debug(a ...interface{}) {
  function Debugf (line 55) | func Debugf(format string, a ...interface{}) {
  function Debugw (line 60) | func Debugw(keyvals ...interface{}) {
  function Info (line 65) | func Info(a ...interface{}) {
  function Infof (line 70) | func Infof(format string, a ...interface{}) {
  function Infow (line 75) | func Infow(keyvals ...interface{}) {
  function Warn (line 80) | func Warn(a ...interface{}) {
  function Warnf (line 85) | func Warnf(format string, a ...interface{}) {
  function Warnw (line 90) | func Warnw(keyvals ...interface{}) {
  function Error (line 95) | func Error(a ...interface{}) {
  function Errorf (line 100) | func Errorf(format string, a ...interface{}) {
  function Errorw (line 105) | func Errorw(keyvals ...interface{}) {
  function Fatal (line 110) | func Fatal(a ...interface{}) {
  function Fatalf (line 115) | func Fatalf(format string, a ...interface{}) {
  function Fatalw (line 120) | func Fatalw(keyvals ...interface{}) {

FILE: log/global_test.go
  function TestGlobalLog (line 11) | func TestGlobalLog(t *testing.T) {
  function TestGlobalLogUpdate (line 71) | func TestGlobalLogUpdate(t *testing.T) {

FILE: log/helper.go
  type Option (line 13) | type Option
  type Helper (line 16) | type Helper struct
    method WithContext (line 42) | func (h *Helper) WithContext(ctx context.Context) *Helper {
    method Log (line 50) | func (h *Helper) Log(level Level, keyvals ...interface{}) {
    method Debug (line 55) | func (h *Helper) Debug(a ...interface{}) {
    method Debugf (line 60) | func (h *Helper) Debugf(format string, a ...interface{}) {
    method Debugw (line 65) | func (h *Helper) Debugw(keyvals ...interface{}) {
    method Info (line 70) | func (h *Helper) Info(a ...interface{}) {
    method Infof (line 75) | func (h *Helper) Infof(format string, a ...interface{}) {
    method Infow (line 80) | func (h *Helper) Infow(keyvals ...interface{}) {
    method Warn (line 85) | func (h *Helper) Warn(a ...interface{}) {
    method Warnf (line 90) | func (h *Helper) Warnf(format string, a ...interface{}) {
    method Warnw (line 95) | func (h *Helper) Warnw(keyvals ...interface{}) {
    method Error (line 100) | func (h *Helper) Error(a ...interface{}) {
    method Errorf (line 105) | func (h *Helper) Errorf(format string, a ...interface{}) {
    method Errorw (line 110) | func (h *Helper) Errorw(keyvals ...interface{}) {
    method Fatal (line 115) | func (h *Helper) Fatal(a ...interface{}) {
    method Fatalf (line 121) | func (h *Helper) Fatalf(format string, a ...interface{}) {
    method Fatalw (line 127) | func (h *Helper) Fatalw(keyvals ...interface{}) {
  function WithMessageKey (line 22) | func WithMessageKey(k string) Option {
  function NewHelper (line 29) | func NewHelper(logger Logger, opts ...Option) *Helper {

FILE: log/helper_test.go
  function TestHelper (line 10) | func TestHelper(t *testing.T) {
  function TestHelperWithMsgKey (line 24) | func TestHelperWithMsgKey(t *testing.T) {
  function TestHelperLevel (line 31) | func TestHelperLevel(t *testing.T) {
  function BenchmarkHelperPrint (line 42) | func BenchmarkHelperPrint(b *testing.B) {
  function BenchmarkHelperPrintf (line 49) | func BenchmarkHelperPrintf(b *testing.B) {
  function BenchmarkHelperPrintw (line 56) | func BenchmarkHelperPrintw(b *testing.B) {
  type traceKey (line 63) | type traceKey struct
  function TestContext (line 65) | func TestContext(t *testing.T) {
  function Trace (line 74) | func Trace() Valuer {

FILE: log/level.go
  type Level (line 6) | type Level
    method String (line 24) | func (l Level) String() string {
  constant LevelKey (line 9) | LevelKey = "level"
  constant LevelDebug (line 13) | LevelDebug Level = iota - 1
  constant LevelInfo (line 15) | LevelInfo
  constant LevelWarn (line 17) | LevelWarn
  constant LevelError (line 19) | LevelError
  constant LevelFatal (line 21) | LevelFatal
  function ParseLevel (line 42) | func ParseLevel(s string) Level {

FILE: log/level_test.go
  function TestLevel_String (line 5) | func TestLevel_String(t *testing.T) {
  function TestParseLevel (line 51) | func TestParseLevel(t *testing.T) {

FILE: log/log.go
  type Logger (line 12) | type Logger interface
  type logger (line 16) | type logger struct
    method Log (line 23) | func (c *logger) Log(level Level, keyvals ...interface{}) error {
  function With (line 39) | func With(l Logger, kv ...interface{}) Logger {
  function WithContext (line 56) | func WithContext(ctx context.Context, l Logger) Logger {
  function MultiLogger (line 69) | func MultiLogger(logs ...Logger) Logger {

FILE: log/log_test.go
  function TestInfo (line 9) | func TestInfo(t *testing.T) {
  function TestWrapper (line 15) | func TestWrapper(t *testing.T) {
  function TestWithContext (line 23) | func TestWithContext(t *testing.T) {

FILE: log/std.go
  type stdLogger (line 13) | type stdLogger struct
    method Log (line 31) | func (l *stdLogger) Log(level Level, keyvals ...interface{}) error {
  function NewStdLogger (line 19) | func NewStdLogger(w io.Writer) Logger {

FILE: log/std_test.go
  function TestStdLogger (line 5) | func TestStdLogger(t *testing.T) {

FILE: log/value.go
  type Valuer (line 21) | type Valuer
  function Value (line 24) | func Value(ctx context.Context, v interface{}) interface{} {
  function Caller (line 32) | func Caller(depth int) Valuer {
  function Timestamp (line 50) | func Timestamp(layout string) Valuer {
  function bindValues (line 56) | func bindValues(ctx context.Context, keyvals []interface{}) {
  function containsValuer (line 64) | func containsValuer(keyvals []interface{}) bool {

FILE: log/value_test.go
  function TestValue (line 8) | func TestValue(t *testing.T) {

FILE: ntheader.go
  type ImageFileHeaderMachineType (line 12) | type ImageFileHeaderMachineType
    method String (line 462) | func (t ImageFileHeaderMachineType) String() string {
  type ImageFileHeaderCharacteristicsType (line 16) | type ImageFileHeaderCharacteristicsType
    method String (line 498) | func (t ImageFileHeaderCharacteristicsType) String() []string {
  type ImageOptionalHeaderSubsystemType (line 19) | type ImageOptionalHeaderSubsystemType
    method String (line 555) | func (subsystem ImageOptionalHeaderSubsystemType) String() string {
  type ImageOptionalHeaderDllCharacteristicsType (line 22) | type ImageOptionalHeaderDllCharacteristicsType
    method String (line 527) | func (t ImageOptionalHeaderDllCharacteristicsType) String() []string {
  type ImageNtHeader (line 26) | type ImageNtHeader struct
  type ImageFileHeader (line 42) | type ImageFileHeader struct
  type ImageOptionalHeader32 (line 75) | type ImageOptionalHeader32 struct
  type ImageOptionalHeader64 (line 218) | type ImageOptionalHeader64 struct
  type DataDirectory (line 355) | type DataDirectory struct
  method ParseNTHeader (line 365) | func (pe *File) ParseNTHeader() (err error) {
  method PrettyOptionalHeaderMagic (line 582) | func (pe *File) PrettyOptionalHeaderMagic() string {

FILE: ntheader_test.go
  function TestParseNtHeaderNE (line 14) | func TestParseNtHeaderNE(t *testing.T) {
  function TestNtHeaderMachineType (line 43) | func TestNtHeaderMachineType(t *testing.T) {
  function TestNtHeaderCharacteristicsType (line 70) | func TestNtHeaderCharacteristicsType(t *testing.T) {
  function TestOptionalHeaderSubsystemType (line 95) | func TestOptionalHeaderSubsystemType(t *testing.T) {
  function TestOptionalHeaderDllCharacteristicsType (line 121) | func TestOptionalHeaderDllCharacteristicsType(t *testing.T) {

FILE: ordlookup.go
  function OrdLookup (line 543) | func OrdLookup(libname string, ord uint64, makeName bool) string {

FILE: overlay.go
  method NewOverlayReader (line 18) | func (pe *File) NewOverlayReader() (*io.SectionReader, error) {
  method Overlay (line 26) | func (pe *File) Overlay() ([]byte, error) {
  method OverlayLength (line 42) | func (pe *File) OverlayLength() int64 {

FILE: overlay_test.go
  type TestOverlay (line 9) | type TestOverlay struct
  function TestFile_NewOverlayReader (line 27) | func TestFile_NewOverlayReader(t *testing.T) {

FILE: pe.go
  constant ImageDOSSignature (line 12) | ImageDOSSignature   = 0x5A4D
  constant ImageDOSZMSignature (line 13) | ImageDOSZMSignature = 0x4D5A
  constant ImageOS2Signature (line 20) | ImageOS2Signature = 0x454E
  constant ImageOS2LESignature (line 26) | ImageOS2LESignature = 0x454C
  constant ImageVXDSignature (line 30) | ImageVXDSignature = 0x584C
  constant ImageTESignature (line 33) | ImageTESignature = 0x5A56
  constant ImageNTSignature (line 38) | ImageNTSignature = 0x00004550
  constant ImageNtOptionalHeader32Magic (line 43) | ImageNtOptionalHeader32Magic = 0x10b
  constant ImageNtOptionalHeader64Magic (line 44) | ImageNtOptionalHeader64Magic = 0x20b
  constant ImageROMOptionalHeaderMagic (line 45) | ImageROMOptionalHeaderMagic  = 0x10
  constant ImageFileMachineUnknown (line 50) | ImageFileMachineUnknown   = ImageFileHeaderMachineType(0x0)
  constant ImageFileMachineAM33 (line 51) | ImageFileMachineAM33      = ImageFileHeaderMachineType(0x1d3)
  constant ImageFileMachineAMD64 (line 52) | ImageFileMachineAMD64     = ImageFileHeaderMachineType(0x8664)
  constant ImageFileMachineARM (line 53) | ImageFileMachineARM       = ImageFileHeaderMachineType(0x1c0)
  constant ImageFileMachineARM64 (line 54) | ImageFileMachineARM64     = ImageFileHeaderMachineType(0xaa64)
  constant ImageFileMachineARMNT (line 55) | ImageFileMachineARMNT     = ImageFileHeaderMachineType(0x1c4)
  constant ImageFileMachineEBC (line 56) | ImageFileMachineEBC       = ImageFileHeaderMachineType(0xebc)
  constant ImageFileMachineI386 (line 57) | ImageFileMachineI386      = ImageFileHeaderMachineType(0x14c)
  constant ImageFileMachineIA64 (line 58) | ImageFileMachineIA64      = ImageFileHeaderMachineType(0x200)
  constant ImageFileMachineM32R (line 59) | ImageFileMachineM32R      = ImageFileHeaderMachineType(0x9041)
  constant ImageFileMachineMIPS16 (line 60) | ImageFileMachineMIPS16    = ImageFileHeaderMachineType(0x266)
  constant ImageFileMachineMIPSFPU (line 61) | ImageFileMachineMIPSFPU   = ImageFileHeaderMachineType(0x366)
  constant ImageFileMachineMIPSFPU16 (line 62) | ImageFileMachineMIPSFPU16 = ImageFileHeaderMachineType(0x466)
  constant ImageFileMachinePowerPC (line 63) | ImageFileMachinePowerPC   = ImageFileHeaderMachineType(0x1f0)
  constant ImageFileMachinePowerPCFP (line 64) | ImageFileMachinePowerPCFP = ImageFileHeaderMachineType(0x1f1)
  constant ImageFileMachineR4000 (line 65) | ImageFileMachineR4000     = ImageFileHeaderMachineType(0x166)
  constant ImageFileMachineRISCV32 (line 66) | ImageFileMachineRISCV32   = ImageFileHeaderMachineType(0x5032)
  constant ImageFileMachineRISCV64 (line 67) | ImageFileMachineRISCV64   = ImageFileHeaderMachineType(0x5064)
  constant ImageFileMachineRISCV128 (line 68) | ImageFileMachineRISCV128  = ImageFileHeaderMachineType(0x5128)
  constant ImageFileMachineSH3 (line 69) | ImageFileMachineSH3       = ImageFileHeaderMachineType(0x1a2)
  constant ImageFileMachineSH3DSP (line 70) | ImageFileMachineSH3DSP    = ImageFileHeaderMachineType(0x1a3)
  constant ImageFileMachineSH4 (line 71) | ImageFileMachineSH4       = ImageFileHeaderMachineType(0x1a6)
  constant ImageFileMachineSH5 (line 72) | ImageFileMachineSH5       = ImageFileHeaderMachineType(0x1a8)
  constant ImageFileMachineTHUMB (line 73) | ImageFileMachineTHUMB     = ImageFileHeaderMachineType(0x1c2)
  constant ImageFileMachineWCEMIPSv2 (line 74) | ImageFileMachineWCEMIPSv2 = ImageFileHeaderMachineType(0x169)
  constant ImageFileRelocsStripped (line 83) | ImageFileRelocsStripped = 0x0001
  constant ImageFileExecutableImage (line 88) | ImageFileExecutableImage = 0x0002
  constant ImageFileLineNumsStripped (line 94) | ImageFileLineNumsStripped = 0x0004
  constant ImageFileLocalSymsStripped (line 99) | ImageFileLocalSymsStripped = 0x0008
  constant ImageFileAggressiveWSTrim (line 102) | ImageFileAggressiveWSTrim = 0x0010
  constant ImageFileLargeAddressAware (line 107) | ImageFileLargeAddressAware = 0x0020
  constant ImageFileBytesReservedLow (line 110) | ImageFileBytesReservedLow = 0x0080
  constant ImageFile32BitMachine (line 116) | ImageFile32BitMachine = 0x0100
  constant ImageFileDebugStripped (line 119) | ImageFileDebugStripped = 0x0200
  constant ImageFileRemovableRunFromSwap (line 123) | ImageFileRemovableRunFromSwap = 0x0400
  constant ImageFileNetRunFromSwap (line 126) | ImageFileNetRunFromSwap = 0x0800
  constant ImageFileSystem (line 129) | ImageFileSystem = 0x1000
  constant ImageFileDLL (line 132) | ImageFileDLL = 0x2000
  constant ImageFileUpSystemOnly (line 135) | ImageFileUpSystemOnly = 0x4000
  constant ImageFileBytesReservedHigh (line 138) | ImageFileBytesReservedHigh = 0x8000
  constant ImageSubsystemUnknown (line 143) | ImageSubsystemUnknown                = 0
  constant ImageSubsystemNative (line 144) | ImageSubsystemNative                 = 1
  constant ImageSubsystemWindowsGUI (line 145) | ImageSubsystemWindowsGUI             = 2
  constant ImageSubsystemWindowsCUI (line 146) | ImageSubsystemWindowsCUI             = 3
  constant ImageSubsystemOS2CUI (line 147) | ImageSubsystemOS2CUI                 = 5
  constant ImageSubsystemPosixCUI (line 148) | ImageSubsystemPosixCUI               = 7
  constant ImageSubsystemNativeWindows (line 149) | ImageSubsystemNativeWindows          = 8
  constant ImageSubsystemWindowsCEGUI (line 150) | ImageSubsystemWindowsCEGUI           = 9
  constant ImageSubsystemEFIApplication (line 151) | ImageSubsystemEFIApplication         = 10
  constant ImageSubsystemEFIBootServiceDriver (line 152) | ImageSubsystemEFIBootServiceDriver   = 11
  constant ImageSubsystemEFIRuntimeDriver (line 153) | ImageSubsystemEFIRuntimeDriver       = 12
  constant ImageSubsystemEFIRom (line 154) | ImageSubsystemEFIRom                 = 13
  constant ImageSubsystemXBOX (line 155) | ImageSubsystemXBOX                   = 14
  constant ImageSubsystemWindowsBootApplication (line 156) | ImageSubsystemWindowsBootApplication = 16
  constant ImageDllCharacteristicsReserved1 (line 161) | ImageDllCharacteristicsReserved1            = 0x0001
  constant ImageDllCharacteristicsReserved2 (line 162) | ImageDllCharacteristicsReserved2            = 0x0002
  constant ImageDllCharacteristicsReserved4 (line 163) | ImageDllCharacteristicsReserved4            = 0x0004
  constant ImageDllCharacteristicsReserved8 (line 164) | ImageDllCharacteristicsReserved8            = 0x0008
  constant ImageDllCharacteristicsHighEntropyVA (line 165) | ImageDllCharacteristicsHighEntropyVA        = 0x0020
  constant ImageDllCharacteristicsDynamicBase (line 166) | ImageDllCharacteristicsDynamicBase          = 0x0040
  constant ImageDllCharacteristicsForceIntegrity (line 167) | ImageDllCharacteristicsForceIntegrity       = 0x0080
  constant ImageDllCharacteristicsNXCompact (line 168) | ImageDllCharacteristicsNXCompact            = 0x0100
  constant ImageDllCharacteristicsNoIsolation (line 169) | ImageDllCharacteristicsNoIsolation          = 0x0200
  constant ImageDllCharacteristicsNoSEH (line 170) | ImageDllCharacteristicsNoSEH                = 0x0400
  constant ImageDllCharacteristicsNoBind (line 171) | ImageDllCharacteristicsNoBind               = 0x0800
  constant ImageDllCharacteristicsAppContainer (line 172) | ImageDllCharacteristicsAppContainer         = 0x1000
  constant ImageDllCharacteristicsWdmDriver (line 173) | ImageDllCharacteristicsWdmDriver            = 0x2000
  constant ImageDllCharacteristicsGuardCF (line 174) | ImageDllCharacteristicsGuardCF              = 0x4000
  constant ImageDllCharacteristicsTerminalServiceAware (line 175) | ImageDllCharacteristicsTerminalServiceAware = 0x8000
  type ImageDirectoryEntry (line 180) | type ImageDirectoryEntry
  constant ImageDirectoryEntryExport (line 184) | ImageDirectoryEntryExport       ImageDirectoryEntry = iota
  constant ImageDirectoryEntryImport (line 185) | ImageDirectoryEntryImport
  constant ImageDirectoryEntryResource (line 186) | ImageDirectoryEntryResource
  constant ImageDirectoryEntryException (line 187) | ImageDirectoryEntryException
  constant ImageDirectoryEntryCertificate (line 188) | ImageDirectoryEntryCertificate
  constant ImageDirectoryEntryBaseReloc (line 189) | ImageDirectoryEntryBaseReloc
  constant ImageDirectoryEntryDebug (line 190) | ImageDirectoryEntryDebug
  constant ImageDirectoryEntryArchitecture (line 191) | ImageDirectoryEntryArchitecture
  constant ImageDirectoryEntryGlobalPtr (line 192) | ImageDirectoryEntryGlobalPtr
  constant ImageDirectoryEntryTLS (line 193) | ImageDirectoryEntryTLS
  constant ImageDirectoryEntryLoadConfig (line 194) | ImageDirectoryEntryLoadConfig
  constant ImageDirectoryEntryBoundImport (line 195) | ImageDirectoryEntryBoundImport
  constant ImageDirectoryEntryIAT (line 196) | ImageDirectoryEntryIAT
  constant ImageDirectoryEntryDelayImport (line 197) | ImageDirectoryEntryDelayImport
  constant ImageDirectoryEntryCLR (line 198) | ImageDirectoryEntryCLR
  constant ImageDirectoryEntryReserved (line 199) | ImageDirectoryEntryReserved
  constant ImageNumberOfDirectoryEntries (line 200) | ImageNumberOfDirectoryEntries
  type FileInfo (line 204) | type FileInfo struct

FILE: reloc.go
  type ImageBaseRelocationEntryType (line 23) | type ImageBaseRelocationEntryType
    method String (line 248) | func (t ImageBaseRelocationEntryType) String(pe *File) string {
  constant ImageRelBasedAbsolute (line 30) | ImageRelBasedAbsolute = 0
  constant ImageRelBasedHigh (line 34) | ImageRelBasedHigh = 1
  constant ImageRelBasedLow (line 38) | ImageRelBasedLow = 2
  constant ImageRelBasedHighLow (line 42) | ImageRelBasedHighLow = 3
  constant ImageRelBasedHighAdj (line 49) | ImageRelBasedHighAdj = 4
  constant ImageRelBasedMIPSJmpAddr (line 54) | ImageRelBasedMIPSJmpAddr = 5
  constant ImageRelBasedARMMov32 (line 59) | ImageRelBasedARMMov32 = 5
  constant ImageRelBasedRISCVHigh20 (line 63) | ImageRelBasedRISCVHigh20 = 5
  constant ImageRelReserved (line 66) | ImageRelReserved = 6
  constant ImageRelBasedThumbMov32 (line 71) | ImageRelBasedThumbMov32 = 7
  constant ImageRelBasedRISCVLow12i (line 76) | ImageRelBasedRISCVLow12i = 7
  constant ImageRelBasedRISCVLow12s (line 81) | ImageRelBasedRISCVLow12s = 8
  constant ImageRelBasedMIPSJmpAddr16 (line 85) | ImageRelBasedMIPSJmpAddr16 = 9
  constant ImageRelBasedDir64 (line 88) | ImageRelBasedDir64 = 10
  constant MaxDefaultRelocEntriesCount (line 96) | MaxDefaultRelocEntriesCount = 0x1000
  type ImageBaseRelocation (line 101) | type ImageBaseRelocation struct
  type ImageBaseRelocationEntry (line 112) | type ImageBaseRelocationEntry struct
  type Relocation (line 128) | type Relocation struct
  method parseRelocations (line 136) | func (pe *File) parseRelocations(dataRVA, rva, size uint32) ([]ImageBase...
  method parseRelocDirectory (line 165) | func (pe *File) parseRelocDirectory(rva, size uint32) error {

FILE: reloc_test.go
  function TestParseRelocDirectoryData (line 11) | func TestParseRelocDirectoryData(t *testing.T) {
  function TestParseRelocDirectoryZeroSizeOfBlock (line 90) | func TestParseRelocDirectoryZeroSizeOfBlock(t *testing.T) {
  function TestParseRelocDirectoryEntry (line 152) | func TestParseRelocDirectoryEntry(t *testing.T) {

FILE: resource.go
  type ResourceType (line 12) | type ResourceType
    method String (line 1195) | func (rt ResourceType) String() string {
  type ResourceLang (line 15) | type ResourceLang
    method String (line 1229) | func (lang ResourceLang) String() string {
  type ResourceSubLang (line 18) | type ResourceSubLang
    method String (line 1381) | func (subLang ResourceSubLang) String() string {
  constant LangNeutral (line 24) | LangNeutral       ResourceLang = 0x00
  constant LangUserDefault (line 25) | LangUserDefault   ResourceLang = 0x01
  constant LangSystemDefault (line 26) | LangSystemDefault ResourceLang = 0x02
  constant LangInvariant (line 27) | LangInvariant     ResourceLang = 0x7F
  constant SubLangNeutral (line 29) | SubLangNeutral           ResourceSubLang = 0x00
  constant SubLangInvariant (line 30) | SubLangInvariant         ResourceSubLang = 0x00
  constant SubLangDefault (line 31) | SubLangDefault           ResourceSubLang = 0x01
  constant SubLangSysDefault (line 32) | SubLangSysDefault        ResourceSubLang = 0x02
  constant SubLangCustomDefault (line 33) | SubLangCustomDefault     ResourceSubLang = 0x03
  constant SubLangCustomUnspecified (line 34) | SubLangCustomUnspecified ResourceSubLang = 0x04
  constant SubLangMUICustomDefault (line 35) | SubLangMUICustomDefault  ResourceSubLang = 0x05
  constant LangAfrikaans (line 41) | LangAfrikaans ResourceLang = 0x0036
  constant LangAlbanian (line 43) | LangAlbanian ResourceLang = 0x001C
  constant LangAlsatian (line 45) | LangAlsatian ResourceLang = 0x0084
  constant LangAmharic (line 47) | LangAmharic ResourceLang = 0x005E
  constant LangArabic (line 49) | LangArabic ResourceLang = 0x0001
  constant LangArmenian (line 51) | LangArmenian ResourceLang = 0x002B
  constant LangAssamese (line 53) | LangAssamese ResourceLang = 0x004D
  constant LangAzerbaijaniLatin (line 55) | LangAzerbaijaniLatin ResourceLang = 0x002C
  constant LangBangla (line 57) | LangBangla ResourceLang = 0x0045
  constant LangBashkir (line 59) | LangBashkir ResourceLang = 0x006D
  constant LangBasque (line 61) | LangBasque ResourceLang = 0x002D
  constant LangBelarusian (line 63) | LangBelarusian ResourceLang = 0x0023
  constant LangBosnianLatin (line 65) | LangBosnianLatin ResourceLang = 0x781A
  constant LangBreton (line 67) | LangBreton ResourceLang = 0x007E
  constant LangBulgarian (line 69) | LangBulgarian ResourceLang = 0x0002
  constant LangBurmese (line 71) | LangBurmese ResourceLang = 0x0055
  constant LangCatalan (line 73) | LangCatalan ResourceLang = 0x0003
  constant LangCentralKurdish (line 75) | LangCentralKurdish ResourceLang = 0x0092
  constant LangCherokee (line 77) | LangCherokee ResourceLang = 0x005C
  constant LangChineseSimplified (line 79) | LangChineseSimplified ResourceLang = 0x7804
  constant LangCorsican (line 81) | LangCorsican ResourceLang = 0x0083
  constant LangCroatian (line 83) | LangCroatian ResourceLang = 0x001A
  constant LangCzech (line 85) | LangCzech ResourceLang = 0x0005
  constant LangDanish (line 87) | LangDanish ResourceLang = 0x0006
  constant LangDari (line 89) | LangDari ResourceLang = 0x008C
  constant LangDivehi (line 91) | LangDivehi ResourceLang = 0x0065
  constant LangDutch (line 93) | LangDutch ResourceLang = 0x0013
  constant LangEnglish (line 95) | LangEnglish ResourceLang = 0x0009
  constant LangEstonian (line 97) | LangEstonian ResourceLang = 0x0025
  constant LangFaroese (line 99) | LangFaroese ResourceLang = 0x0038
  constant LangFilipino (line 101) | LangFilipino ResourceLang = 0x0064
  constant LangFinnish (line 103) | LangFinnish ResourceLang = 0x000B
  constant LangFrench (line 105) | LangFrench ResourceLang = 0x000C
  constant LangFrisian (line 107) | LangFrisian ResourceLang = 0x0062
  constant LangFulah (line 109) | LangFulah ResourceLang = 0x0067
  constant LangFulahLatin (line 111) | LangFulahLatin ResourceLang = 0x7C67
  constant LangGalician (line 113) | LangGalician ResourceLang = 0x0056
  constant LangGeorgian (line 115) | LangGeorgian ResourceLang = 0x0037
  constant LangGerman (line 117) | LangGerman ResourceLang = 0x0007
  constant LangGreek (line 119) | LangGreek ResourceLang = 0x0008
  constant LangGreenlandic (line 121) | LangGreenlandic ResourceLang = 0x006F
  constant LangGuarani (line 123) | LangGuarani ResourceLang = 0x0074
  constant LangGujarati (line 125) | LangGujarati ResourceLang = 0x0047
  constant LangHausaLatin (line 127) | LangHausaLatin ResourceLang = 0x0068
  constant LangHawaiian (line 129) | LangHawaiian ResourceLang = 0x0075
  constant LangHebrew (line 131) | LangHebrew ResourceLang = 0x000D
  constant LangHindi (line 133) | LangHindi ResourceLang = 0x0039
  constant LangHungarian (line 135) | LangHungarian ResourceLang = 0x000E
  constant LangIcelandic (line 137) | LangIcelandic ResourceLang = 0x000F
  constant LangIgbo (line 139) | LangIgbo ResourceLang = 0x0070
  constant LangIndonesian (line 141) | LangIndonesian ResourceLang = 0x0021
  constant LangInuktitutLatin (line 143) | LangInuktitutLatin ResourceLang = 0x005D
  constant LangIrish (line 145) | LangIrish ResourceLang = 0x003C
  constant LangItalian (line 147) | LangItalian ResourceLang = 0x0010
  constant LangJapanese (line 149) | LangJapanese ResourceLang = 0x0011
  constant LangKannada (line 151) | LangKannada ResourceLang = 0x004B
  constant LangKashmiri (line 153) | LangKashmiri ResourceLang = 0x0060
  constant LangKazakh (line 155) | LangKazakh ResourceLang = 0x003F
  constant LangKhmer (line 157) | LangKhmer ResourceLang = 0x0053
  constant LangKiche (line 159) | LangKiche ResourceLang = 0x0086
  constant LangKinyarwanda (line 161) | LangKinyarwanda ResourceLang = 0x0087
  constant LangKiswahili (line 163) | LangKiswahili ResourceLang = 0x0041
  constant LangKonkani (line 165) | LangKonkani ResourceLang = 0x0057
  constant LangKorean (line 167) | LangKorean ResourceLang = 0x0012
  constant LangKyrgyz (line 169) | LangKyrgyz ResourceLang = 0x0040
  constant LangLao (line 171) | LangLao ResourceLang = 0x0054
  constant LangLatvian (line 173) | LangLatvian ResourceLang = 0x0026
  constant LangLithuanian (line 175) | LangLithuanian ResourceLang = 0x0027
  constant LangLowerSorbian (line 177) | LangLowerSorbian ResourceLang = 0x7C2E
  constant LangLuxembourgish (line 179) | LangLuxembourgish ResourceLang = 0x006E
  constant LangMacedonian (line 181) | LangMacedonian ResourceLang = 0x002F
  constant LangMalay (line 183) | LangMalay ResourceLang = 0x003E
  constant LangMalayalam (line 185) | LangMalayalam ResourceLang = 0x004C
  constant LangMaltese (line 187) | LangMaltese ResourceLang = 0x003A
  constant LangMaori (line 189) | LangMaori ResourceLang = 0x0081
  constant LangMapudungun (line 191) | LangMapudungun ResourceLang = 0x007A
  constant LangMarathi (line 193) | LangMarathi ResourceLang = 0x004E
  constant LangMohawk (line 195) | LangMohawk ResourceLang = 0x007C
  constant LangMongolianCyrillic (line 197) | LangMongolianCyrillic ResourceLang = 0x0050
  constant LangNepali (line 199) | LangNepali ResourceLang = 0x0061
  constant LangNorwegianBokmalNo (line 201) | LangNorwegianBokmalNo ResourceLang = 0x0014
  constant LangNorwegianBokmal (line 203) | LangNorwegianBokmal ResourceLang = 0x7C14
  constant LangNorwegianNynorsk (line 205) | LangNorwegianNynorsk ResourceLang = 0x7814
  constant LangOccitan (line 207) | LangOccitan ResourceLang = 0x0082
  constant LangOdia (line 209) | LangOdia ResourceLang = 0x0048
  constant LangOromo (line 211) | LangOromo ResourceLang = 0x0072
  constant LangPashto (line 213) | LangPashto ResourceLang = 0x0063
  constant LangPersian (line 215) | LangPersian ResourceLang = 0x0029
  constant LangPolish (line 217) | LangPolish ResourceLang = 0x0015
  constant LangPortuguese (line 219) | LangPortuguese ResourceLang = 0x0016
  constant LangPunjabi (line 221) | LangPunjabi ResourceLang = 0x0046
  constant LangQuechua (line 223) | LangQuechua ResourceLang = 0x006B
  constant LangRomanian (line 225) | LangRomanian ResourceLang = 0x0018
  constant LangRomansh (line 227) | LangRomansh ResourceLang = 0x0017
  constant LangRussian (line 229) | LangRussian ResourceLang = 0x0019
  constant LangSakha (line 231) | LangSakha ResourceLang = 0x0085
  constant LangSamiInari (line 233) | LangSamiInari ResourceLang = 0x703B
  constant LangSamiLule (line 235) | LangSamiLule ResourceLang = 0x7C3B
  constant LangSamiNorthern (line 237) | LangSamiNorthern ResourceLang = 0x003B
  constant LangSamiSkolt (line 239) | LangSamiSkolt ResourceLang = 0x743B
  constant LangSamiSouthern (line 241) | LangSamiSouthern ResourceLang = 0x783B
  constant LangSanskrit (line 243) | LangSanskrit ResourceLang = 0x004F
  constant LangScottishGaelic (line 245) | LangScottishGaelic ResourceLang = 0x0091
  constant LangSerbianLatin (line 247) | LangSerbianLatin ResourceLang = 0x7C1A
  constant LangSesothoSaLeboa (line 249) | LangSesothoSaLeboa ResourceLang = 0x006C
  constant LangSetswana (line 251) | LangSetswana ResourceLang = 0x0032
  constant LangSindhi (line 253) | LangSindhi ResourceLang = 0x0059
  constant LangSinhala (line 255) | LangSinhala ResourceLang = 0x005B
  constant LangSlovak (line 257) | LangSlovak ResourceLang = 0x001B
  constant LangSlovenian (line 259) | LangSlovenian ResourceLang = 0x0024
  constant LangSomali (line 261) | LangSomali ResourceLang = 0x0077
  constant LangSotho (line 263) | LangSotho ResourceLang = 0x0030
  constant LangSpanish (line 265) | LangSpanish ResourceLang = 0x000A
  constant LangSwedish (line 267) | LangSwedish ResourceLang = 0x001D
  constant LangSyriac (line 269) | LangSyriac ResourceLang = 0x005A
  constant LangTajikCyrillic (line 271) | LangTajikCyrillic ResourceLang = 0x0028
  constant LangTamazightLatin (line 273) | LangTamazightLatin ResourceLang = 0x005F
  constant LangTamil (line 275) | LangTamil ResourceLang = 0x0049
  constant LangTatar (line 277) | LangTatar ResourceLang = 0x0044
  constant LangTelugu (line 279) | LangTelugu ResourceLang = 0x004A
  constant LangThai (line 281) | LangThai ResourceLang = 0x001E
  constant LangTibetan (line 283) | LangTibetan ResourceLang = 0x0051
  constant LangTigrinya (line 285) | LangTigrinya ResourceLang = 0x0073
  constant LangTsonga (line 287) | LangTsonga ResourceLang = 0x0031
  constant LangTurkish (line 289) | LangTurkish ResourceLang = 0x001F
  constant LangTurkmen (line 291) | LangTurkmen ResourceLang = 0x0042
  constant LangUkrainian (line 293) | LangUkrainian ResourceLang = 0x0022
  constant LangUpperSorbian (line 295) | LangUpperSorbian ResourceLang = 0x002E
  constant LangUrdu (line 297) | LangUrdu ResourceLang = 0x0020
  constant LangUyghur (line 299) | LangUyghur ResourceLang = 0x0080
  constant LangUzbekLatin (line 301) | LangUzbekLatin ResourceLang = 0x0043
  constant LangVenda (line 303) | LangVenda ResourceLang = 0x0033
  constant LangVietnamese (line 305) | LangVietnamese ResourceLang = 0x002A
  constant LangWelsh (line 307) | LangWelsh ResourceLang = 0x0052
  constant LangWolof (line 309) | LangWolof ResourceLang = 0x0088
  constant LangXhosa (line 311) | LangXhosa ResourceLang = 0x0034
  constant LangYi (line 313) | LangYi ResourceLang = 0x0078
  constant LangYoruba (line 315) | LangYoruba ResourceLang = 0x006A
  constant LangZulu (line 317) | LangZulu ResourceLang = 0x0035
  constant SubLangAfrikaansSouthAfrica (line 323) | SubLangAfrikaansSouthAfrica ResourceSubLang = iota
  constant SubLangAlbanianAlbania (line 325) | SubLangAlbanianAlbania
  constant SubLangAlsatianFrance (line 327) | SubLangAlsatianFrance
  constant SubLangAmharicEthiopia (line 329) | SubLangAmharicEthiopia
  constant SubLangArabicAlgeria (line 331) | SubLangArabicAlgeria
  constant SubLangArabicBahrain (line 333) | SubLangArabicBahrain
  constant SubLangArabicEgypt (line 335) | SubLangArabicEgypt
  constant SubLangArabicIraq (line 337) | SubLangArabicIraq
  constant SubLangArabicJordan (line 339) | SubLangArabicJordan
  constant SubLangArabicKuwait (line 341) | SubLangArabicKuwait
  constant SubLangArabicLebanon (line 343) | SubLangArabicLebanon
  constant SubLangArabicLibya (line 345) | SubLangArabicLibya
  constant SubLangArabicMorocco (line 347) | SubLangArabicMorocco
  constant SubLangArabicOman (line 349) | SubLangArabicOman
  constant SubLangArabicQatar (line 351) | SubLangArabicQatar
  constant SubLangArabicSaudiArabia (line 353) | SubLangArabicSaudiArabia
  constant SubLangArabicSyria (line 355) | SubLangArabicSyria
  constant SubLangArabicTunisia (line 357) | SubLangArabicTunisia
  constant SubLangArabicUae (line 359) | SubLangArabicUae
  constant SubLangArabicYemen (line 361) | SubLangArabicYemen
  constant SubLangArmenianArmenia (line 363) | SubLangArmenianArmenia
  constant SubLangAssameseIndia (line 365) | SubLangAssameseIndia
  constant SubLangAzerbaijaniCyrillic (line 367) | SubLangAzerbaijaniCyrillic
  constant SubLangAzerbaijaniCyrillicAzerbaijan (line 369) | SubLangAzerbaijaniCyrillicAzerbaijan
  constant SubLangAzerbaijaniLatin (line 371) | SubLangAzerbaijaniLatin
  constant SubLangAzerbaijaniLatinAzerbaijan (line 373) | SubLangAzerbaijaniLatinAzerbaijan
  constant SubLangBanglaBangladesh (line 375) | SubLangBanglaBangladesh
  constant SubLangBanglaIndia (line 377) | SubLangBanglaIndia
  constant SubLangBashkirRussia (line 379) | SubLangBashkirRussia
  constant SubLangBasqueSpain (line 381) | SubLangBasqueSpain
  constant SubLangBelarusianBelarus (line 383) | SubLangBelarusianBelarus
  constant SubLangBosnianCyrillic (line 385) | SubLangBosnianCyrillic
  constant SubLangBosnianCyrillicBosniaAndHerzegovina (line 387) | SubLangBosnianCyrillicBosniaAndHerzegovina
  constant SubLangBosnianLatin (line 389) | SubLangBosnianLatin
  constant SubLangBosnianLatinBosniaAndHerzegovina (line 391) | SubLangBosnianLatinBosniaAndHerzegovina
  constant SubLangBretonFrance (line 393) | SubLangBretonFrance
  constant SubLangBulgarianBulgaria (line 395) | SubLangBulgarianBulgaria
  constant SubLangBurmeseMyanmar (line 397) | SubLangBurmeseMyanmar
  constant SubLangCatalanSpain (line 399) | SubLangCatalanSpain
  constant SubLangCentralAtlasTamazightArabicMorocco (line 401) | SubLangCentralAtlasTamazightArabicMorocco
  constant SubLangCentralKurdish (line 403) | SubLangCentralKurdish
  constant SubLangCentralKurdishIraq (line 405) | SubLangCentralKurdishIraq
  constant SubLangCherokee (line 407) | SubLangCherokee
  constant SubLangCherokeeUnitedStates (line 409) | SubLangCherokeeUnitedStates
  constant SubLangChineseSimplified (line 411) | SubLangChineseSimplified
  constant SubLangChineseSimplifiedPeoplesRepublicOfChina (line 413) | SubLangChineseSimplifiedPeoplesRepublicOfChina
  constant SubLangChineseSimplifiedSingapore (line 415) | SubLangChineseSimplifiedSingapore
  constant SubLangChineseTraditional (line 417) | SubLangChineseTraditional
  constant SubLangChineseTraditionalHongKongSar (line 419) | SubLangChineseTraditionalHongKongSar
  constant SubLangChineseTraditionalMacaoSar (line 421) | SubLangChineseTraditionalMacaoSar
  constant SubLangChineseTraditionalTaiwan (line 423) | SubLangChineseTraditionalTaiwan
  constant SubLangCorsicanFrance (line 425) | SubLangCorsicanFrance
  constant SubLangCroatianCroatia (line 427) | SubLangCroatianCroatia
  constant SubLangCroatianLatinBosniaAndHerzegovina (line 429) | SubLangCroatianLatinBosniaAndHerzegovina
  constant SubLangCzechCzechRepublic (line 431) | SubLangCzechCzechRepublic
  constant SubLangDanishDenmark (line 433) | SubLangDanishDenmark
  constant SubLangDariAfghanistan (line 435) | SubLangDariAfghanistan
  constant SubLangDivehiMaldives (line 437) | SubLangDivehiMaldives
  constant SubLangDutchBelgium (line 439) | SubLangDutchBelgium
  constant SubLangDutchNetherlands (line 441) | SubLangDutchNetherlands
  constant SubLangDzongkhaBhutan (line 443) | SubLangDzongkhaBhutan
  constant SubLangEnglishAustralia (line 445) | SubLangEnglishAustralia
  constant SubLangEnglishBelize (line 447) | SubLangEnglishBelize
  constant SubLangEnglishCanada (line 449) | SubLangEnglishCanada
  constant SubLangEnglishCaribbean (line 451) | SubLangEnglishCaribbean
  constant SubLangEnglishHongKong (line 453) | SubLangEnglishHongKong
  constant SubLangEnglishIndia (line 455) | SubLangEnglishIndia
  constant SubLangEnglishIreland (line 457) | SubLangEnglishIreland
  constant SubLangEnglishJamaica (line 459) | SubLangEnglishJamaica
  constant SubLangEnglishMalaysia (line 461) | SubLangEnglishMalaysia
  constant SubLangEnglishNewZealand (line 463) | SubLangEnglishNewZealand
  constant SubLangEnglishRepublicOfThePhilippines (line 465) | SubLangEnglishRepublicOfThePhilippines
  constant SubLangEnglishSingapore (line 467) | SubLangEnglishSingapore
  constant SubLangEnglishSouthAfrica (line 469) | SubLangEnglishSouthAfrica
  constant SubLangEnglishTrinidadAndTobago (line 471) | SubLangEnglishTrinidadAndTobago
  constant SubLangEnglishUnitedArabEmirates (line 473) | SubLangEnglishUnitedArabEmirates
  constant SubLangEnglishUnitedKingdom (line 475) | SubLangEnglishUnitedKingdom
  constant SubLangEnglishUnitedStates (line 477) | SubLangEnglishUnitedStates
  constant SubLangEnglishZimbabwe (line 479) | SubLangEnglishZimbabwe
  constant SubLangEstonianEstonia (line 481) | SubLangEstonianEstonia
  constant SubLangFaroeseFaroeIslands (line 483) | SubLangFaroeseFaroeIslands
  constant SubLangFilipinoPhilippines (line 485) | SubLangFilipinoPhilippines
  constant SubLangFinnishFinland (line 487) | SubLangFinnishFinland
  constant SubLangFrenchBelgium (line 489) | SubLangFrenchBelgium
  constant SubLangFrenchCameroon (line 491) | SubLangFrenchCameroon
  constant SubLangFrenchCanada (line 493) | SubLangFrenchCanada
  constant SubLangFrenchCaribbean (line 495) | SubLangFrenchCaribbean
  constant SubLangFrenchCongoDrc (line 497) | SubLangFrenchCongoDrc
  constant SubLangFrenchCôteDivoire (line 499) | SubLangFrenchCôteDivoire
  constant SubLangFrenchFrance (line 501) | SubLangFrenchFrance
  constant SubLangFrenchHaiti (line 503) | SubLangFrenchHaiti
  constant SubLangFrenchLuxembourg (line 505) | SubLangFrenchLuxembourg
  constant SubLangFrenchMali (line 507) | SubLangFrenchMali
  constant SubLangFrenchMorocco (line 509) | SubLangFrenchMorocco
  constant SubLangFrenchPrincipalityOfMonaco (line 511) | SubLangFrenchPrincipalityOfMonaco
  constant SubLangFrenchReunion (line 513) | SubLangFrenchReunion
  constant SubLangFrenchSenegal (line 515) | SubLangFrenchSenegal
  constant SubLangFrenchSwitzerland (line 517) | SubLangFrenchSwitzerland
  constant SubLangFrisianNetherlands (line 519) | SubLangFrisianNetherlands
  constant SubLangFulahNigeria (line 521) | SubLangFulahNigeria
  constant SubLangFulahLatinNigeria (line 523) | SubLangFulahLatinNigeria
  constant SubLangFulahSenegal (line 525) | SubLangFulahSenegal
  constant SubLangGalicianSpain (line 527) | SubLangGalicianSpain
  constant SubLangGeorgianGeorgia (line 529) | SubLangGeorgianGeorgia
  constant SubLangGermanAustria (line 531) | SubLangGermanAustria
  constant SubLangGermanGermany (line 533) | SubLangGermanGermany
  constant SubLangGermanLiechtenstein (line 535) | SubLangGermanLiechtenstein
  constant SubLangGermanLuxembourg (line 537) | SubLangGermanLuxembourg
  constant SubLangGermanSwitzerland (line 539) | SubLangGermanSwitzerland
  constant SubLangGreekGreece (line 541) | SubLangGreekGreece
  constant SubLangGreenlandicGreenland (line 543) | SubLangGreenlandicGreenland
  constant SubLangGuaraniParaguay (line 545) | SubLangGuaraniParaguay
  constant SubLangGujaratiIndia (line 547) | SubLangGujaratiIndia
  constant SubLangHausaLatin (line 549) | SubLangHausaLatin
  constant SubLangHausaLatinNigeria (line 551) | SubLangHausaLatinNigeria
  constant SubLangHawaiianUnitedStates (line 553) | SubLangHawaiianUnitedStates
  constant SubLangHebrewIsrael (line 555) | SubLangHebrewIsrael
  constant SubLangHindiIndia (line 557) | SubLangHindiIndia
  constant SubLangHungarianHungary (line 559) | SubLangHungarianHungary
  constant SubLangIcelandicIceland (line 561) | SubLangIcelandicIceland
  constant SubLangIgboNigeria (line 563) | SubLangIgboNigeria
  constant SubLangIndonesianIndonesia (line 565) | SubLangIndonesianIndonesia
  constant SubLangInuktitutLatin (line 567) | SubLangInuktitutLatin
  constant SubLangInuktitutLatinCanada (line 569) | SubLangInuktitutLatinCanada
  constant SubLangInuktitutSyllabics (line 571) | SubLangInuktitutSyllabics
  constant SubLangInuktitutSyllabicsCanada (line 573) | SubLangInuktitutSyllabicsCanada
  constant SubLangIrishIreland (line 575) | SubLangIrishIreland
  constant SubLangItalianItaly (line 577) | SubLangItalianItaly
  constant SubLangItalianSwitzerland (line 579) | SubLangItalianSwitzerland
  constant SubLangJapaneseJapan (line 581) | SubLangJapaneseJapan
  constant SubLangKannadaIndia (line 583) | SubLangKannadaIndia
  constant SubLangKanuriLatinNigeria (line 585) | SubLangKanuriLatinNigeria
  constant SubLangKashmiriPersoArabic (line 587) | SubLangKashmiriPersoArabic
  constant SubLangKashmiriDevanagariIndia (line 589) | SubLangKashmiriDevanagariIndia
  constant SubLangKazakhKazakhstan (line 591) | SubLangKazakhKazakhstan
  constant SubLangKhmerCambodia (line 593) | SubLangKhmerCambodia
  constant SubLangKicheGuatemala (line 595) | SubLangKicheGuatemala
  constant SubLangKinyarwandaRwanda (line 597) | SubLangKinyarwandaRwanda
  constant SubLangKiswahiliKenya (line 599) | SubLangKiswahiliKenya
  constant SubLangKonkaniIndia (line 601) | SubLangKonkaniIndia
  constant SubLangKoreanKorea (line 603) | SubLangKoreanKorea
  constant SubLangKyrgyzKyrgyzstan (line 605) | SubLangKyrgyzKyrgyzstan
  constant SubLangLaoLaoPdr (line 607) | SubLangLaoLaoPdr
  constant SubLangLatinVaticanCity (line 609) | SubLangLatinVaticanCity
  constant SubLangLatvianLatvia (line 611) | SubLangLatvianLatvia
  constant SubLangLithuanianLithuania (line 613) | SubLangLithuanianLithuania
  constant SubLangLowerSorbianGermany (line 615) | SubLangLowerSorbianGermany
  constant SubLangLuxembourgishLuxembourg (line 617) | SubLangLuxembourgishLuxembourg
  constant SubLangMacedonianNorthMacedonia (line 619) | SubLangMacedonianNorthMacedonia
  constant SubLangMalayBruneiDarussalam (line 621) | SubLangMalayBruneiDarussalam
  constant SubLangMalayMalaysia (line 623) | SubLangMalayMalaysia
  constant SubLangMalayalamIndia (line 625) | SubLangMalayalamIndia
  constant SubLangMalteseMalta (line 627) | SubLangMalteseMalta
  constant SubLangMaoriNewZealand (line 629) | SubLangMaoriNewZealand
  constant SubLangMapudungunChile (line 631) | SubLangMapudungunChile
  constant SubLangMarathiIndia (line 633) | SubLangMarathiIndia
  constant SubLangMohawkCanada (line 635) | SubLangMohawkCanada
  constant SubLangMongolianCyrillic (line 637) | SubLangMongolianCyrillic
  constant SubLangMongolianCyrillicMongolia (line 639) | SubLangMongolianCyrillicMongolia
  constant SubLangMongolianTraditionalMongolian (line 641) | SubLangMongolianTraditionalMongolian
  constant SubLangMongolianTraditionalMongolianPeoplesRepublicOfChina (line 643) | SubLangMongolianTraditionalMongolianPeoplesRepublicOfChina
  constant SubLangMongolianTraditionalMongolianMongolia (line 645) | SubLangMongolianTraditionalMongolianMongolia
  constant SubLangNepaliIndia (line 647) | SubLangNepaliIndia
  constant SubLangNepaliNepal (line 649) | SubLangNepaliNepal
  constant SubLangNorwegianBokmalNorway (line 651) | SubLangNorwegianBokmalNorway
  constant SubLangNorwegianNynorskNorway (line 653) | SubLangNorwegianNynorskNorway
  constant SubLangOccitanFrance (line 655) | SubLangOccitanFrance
  constant SubLangOdiaIndia (line 657) | SubLangOdiaIndia
  constant SubLangOromoEthiopia (line 659) | SubLangOromoEthiopia
  constant SubLangPashtoAfghanistan (line 661) | SubLangPashtoAfghanistan
  constant SubLangPersianIran (line 663) | SubLangPersianIran
  constant SubLangPolishPoland (line 665) | SubLangPolishPoland
  constant SubLangPortugueseBrazil (line 667) | SubLangPortugueseBrazil
  constant SubLangPortuguesePortugal (line 669) | SubLangPortuguesePortugal
  constant SubLangPseudoLanguagePseudoLocaleForEastAsianComplexScriptLocalizationTesting (line 671) | SubLangPseudoLanguagePseudoLocaleForEastAsianComplexScriptLocalizationTe...
  constant SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTesting (line 673) | SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTesting
  constant SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTestingOfMirroredLocales (line 675) | SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTestingOfMirroredLoc...
  constant SubLangPunjabi (line 677) | SubLangPunjabi
  constant SubLangPunjabiIndia (line 679) | SubLangPunjabiIndia
  constant SubLangPunjabiIslamicRepublicOfPakistan (line 681) | SubLangPunjabiIslamicRepublicOfPakistan
  constant SubLangQuechuaBolivia (line 683) | SubLangQuechuaBolivia
  constant SubLangQuechuaEcuador (line 685) | SubLangQuechuaEcuador
  constant SubLangQuechuaPeru (line 687) | SubLangQuechuaPeru
  constant SubLangRomanianMoldova (line 689) | SubLangRomanianMoldova
  constant SubLangRomanianRomania (line 691) | SubLangRomanianRomania
  constant SubLangRomanshSwitzerland (line 693) | SubLangRomanshSwitzerland
  constant SubLangRussianMoldova (line 695) | SubLangRussianMoldova
  constant SubLangRussianRussia (line 697) | SubLangRussianRussia
  constant SubLangSakhaRussia (line 699) | SubLangSakhaRussia
  constant SubLangSamiInariFinland (line 701) | SubLangSamiInariFinland
  constant SubLangSamiLuleNorway (line 703) | SubLangSamiLuleNorway
  constant SubLangSamiLuleSweden (line 705) | SubLangSamiLuleSweden
  constant SubLangSamiNorthernFinland (line 707) | SubLangSamiNorthernFinland
  constant SubLangSamiNorthernNorway (line 709) | SubLangSamiNorthernNorway
  constant SubLangSamiNorthernSweden (line 711) | SubLangSamiNorthernSweden
  constant SubLangSamiSkoltFinland (line 713) | SubLangSamiSkoltFinland
  constant SubLangSamiSouthernNorway (line 715) | SubLangSamiSouthernNorway
  constant SubLangSamiSouthernSweden (line 717) | SubLangSamiSouthernSweden
  constant SubLangSanskritIndia (line 719) | SubLangSanskritIndia
  constant SubLangScottishGaelicUnitedKingdom (line 721) | SubLangScottishGaelicUnitedKingdom
  constant SubLangSerbianCyrillic (line 723) | SubLangSerbianCyrillic
  constant SubLangSerbianCyrillicBosniaAndHerzegovina (line 725) | SubLangSerbianCyrillicBosniaAndHerzegovina
  constant SubLangSerbianCyrillicMontenegro (line 727) | SubLangSerbianCyrillicMontenegro
  constant SubLangSerbianCyrillicSerbia (line 729) | SubLangSerbianCyrillicSerbia
  constant SubLangSerbianCyrillicSerbiaAndMontenegroFormer (line 731) | SubLangSerbianCyrillicSerbiaAndMontenegroFormer
  constant SubLangSerbianLatin (line 733) | SubLangSerbianLatin
  constant SubLangSerbianLatinBosniaAndHerzegovina (line 735) | SubLangSerbianLatinBosniaAndHerzegovina
  constant SubLangSerbianLatinMontenegro (line 737) | SubLangSerbianLatinMontenegro
  constant SubLangSerbianLatinSerbia (line 739) | SubLangSerbianLatinSerbia
  constant SubLangSerbianLatinSerbiaAndMontenegroFormer (line 741) | SubLangSerbianLatinSerbiaAndMontenegroFormer
  constant SubLangSesothoSaLeboaSouthAfrica (line 743) | SubLangSesothoSaLeboaSouthAfrica
  constant SubLangSetswanaBotswana (line 745) | SubLangSetswanaBotswana
  constant SubLangSetswanaSouthAfrica (line 747) | SubLangSetswanaSouthAfrica
  constant SubLangSindhi (line 749) | SubLangSindhi
  constant SubLangSindhiIslamicRepublicOfPakistan (line 751) | SubLangSindhiIslamicRepublicOfPakistan
  constant SubLangSinhalaSriLanka (line 753) | SubLangSinhalaSriLanka
  constant SubLangSlovakSlovakia (line 755) | SubLangSlovakSlovakia
  constant SubLangSlovenianSlovenia (line 757) | SubLangSlovenianSlovenia
  constant SubLangSomaliSomalia (line 759) | SubLangSomaliSomalia
  constant SubLangSothoSouthAfrica (line 761) | SubLangSothoSouthAfrica
  constant SubLangSpanishArgentina (line 763) | SubLangSpanishArgentina
  constant SubLangSpanishBolivarianRepublicOfVenezuela (line 765) | SubLangSpanishBolivarianRepublicOfVenezuela
  constant SubLangSpanishBolivia (line 767) | SubLangSpanishBolivia
  constant SubLangSpanishChile (line 769) | SubLangSpanishChile
  constant SubLangSpanishColombia (line 771) | SubLangSpanishColombia
  constant SubLangSpanishCostaRica (line 773) | SubLangSpanishCostaRica
  constant SubLangSpanishCuba (line 775) | SubLangSpanishCuba
  constant SubLangSpanishDominicanRepublic (line 777) | SubLangSpanishDominicanRepublic
  constant SubLangSpanishEcuador (line 779) | SubLangSpanishEcuador
  constant SubLangSpanishElSalvador (line 781) | SubLangSpanishElSalvador
  constant SubLangSpanishGuatemala (line 783) | SubLangSpanishGuatemala
  constant SubLangSpanishHonduras (line 785) | SubLangSpanishHonduras
  constant SubLangSpanishLatinAmerica (line 787) | SubLangSpanishLatinAmerica
  constant SubLangSpanishMexico (line 789) | SubLangSpanishMexico
  constant SubLangSpanishNicaragua (line 791) | SubLangSpanishNicaragua
  constant SubLangSpanishPanama (line 793) | SubLangSpanishPanama
  constant SubLangSpanishParaguay (line 795) | SubLangSpanishParaguay
  constant SubLangSpanishPeru (line 797) | SubLangSpanishPeru
  constant SubLangSpanishPuertoRico (line 799) | SubLangSpanishPuertoRico
  constant SubLangSpanishSpainTraditional (line 801) | SubLangSpanishSpainTraditional
  constant SubLangSpanishSpain (line 803) | SubLangSpanishSpain
  constant SubLangSpanishUnitedStates (line 805) | SubLangSpanishUnitedStates
  constant SubLangSpanishUruguay (line 807) | SubLangSpanishUruguay
  constant SubLangSwedishFinland (line 809) | SubLangSwedishFinland
  constant SubLangSwedishSweden (line 811) | SubLangSwedishSweden
  constant SubLangSyriacSyria (line 813) | SubLangSyriacSyria
  constant SubLangTajikCyrillic (line 815) | SubLangTajikCyrillic
  constant SubLangTajikCyrillicTajikistan (line 817) | SubLangTajikCyrillicTajikistan
  constant SubLangTamazightLatin (line 819) | SubLangTamazightLatin
  constant SubLangTamazightLatinAlgeria (line 821) | SubLangTamazightLatinAlgeria
  constant SubLangTamilIndia (line 823) | SubLangTamilIndia
  constant SubLangTamilSriLanka (line 825) | SubLangTamilSriLanka
  constant SubLangTatarRussia (line 827) | SubLangTatarRussia
  constant SubLangTeluguIndia (line 829) | SubLangTeluguIndia
  constant SubLangThaiThailand (line 831) | SubLangThaiThailand
  constant SubLangTibetanPeoplesRepublicOfChina (line 833) | SubLangTibetanPeoplesRepublicOfChina
  constant SubLangTigrinyaEritrea (line 835) | SubLangTigrinyaEritrea
  constant SubLangTigrinyaEthiopia (line 837) | SubLangTigrinyaEthiopia
  constant SubLangTsongaSouthAfrica (line 839) | SubLangTsongaSouthAfrica
  constant SubLangTurkishTurkey (line 841) | SubLangTurkishTurkey
  constant SubLangTurkmenTurkmenistan (line 843) | SubLangTurkmenTurkmenistan
  constant SubLangUkrainianUkraine (line 845) | SubLangUkrainianUkraine
  constant SubLangUpperSorbianGermany (line 847) | SubLangUpperSorbianGermany
  constant SubLangUrduIndia (line 849) | SubLangUrduIndia
  constant SubLangUrduIslamicRepublicOfPakistan (line 851) | SubLangUrduIslamicRepublicOfPakistan
  constant SubLangUyghurPeoplesRepublicOfChina (line 853) | SubLangUyghurPeoplesRepublicOfChina
  constant SubLangUzbekCyrillic (line 855) | SubLangUzbekCyrillic
  constant SubLangUzbekCyrillicUzbekistan (line 857) | SubLangUzbekCyrillicUzbekistan
  constant SubLangUzbekLatin (line 859) | SubLangUzbekLatin
  constant SubLangUzbekLatinUzbekistan (line 861) | SubLangUzbekLatinUzbekistan
  constant SubLangValencianSpain (line 863) | SubLangValencianSpain
  constant SubLangVendaSouthAfrica (line 865) | SubLangVendaSouthAfrica
  constant SubLangVietnameseVietnam (line 867) | SubLangVietnameseVietnam
  constant SubLangWelshUnitedKingdom (line 869) | SubLangWelshUnitedKingdom
  constant SubLangWolofSenegal (line 871) | SubLangWolofSenegal
  constant SubLangXhosaSouthAfrica (line 873) | SubLangXhosaSouthAfrica
  constant SubLangYiPeoplesRepublicOfChina (line 875) | SubLangYiPeoplesRepublicOfChina
  constant SubLangYiddishWorld (line 877) | SubLangYiddishWorld
  constant SubLangYorubaNigeria (line 879) | SubLangYorubaNigeria
  constant SubLangZuluSouthAfrica (line 881) | SubLangZuluSouthAfrica
  constant maxAllowedEntries (line 885) | maxAllowedEntries = 0x1000
  constant RTCursor (line 890) | RTCursor       ResourceType = iota + 1
  constant RTBitmap (line 891) | RTBitmap                    = 2
  constant RTIcon (line 892) | RTIcon                      = 3
  constant RTMenu (line 893) | RTMenu                      = 4
  constant RTDialog (line 894) | RTDialog                    = 5
  constant RTString (line 895) | RTString                    = 6
  constant RTFontDir (line 896) | RTFontDir                   = 7
  constant RTFont (line 897) | RTFont                      = 8
  constant RTAccelerator (line 898) | RTAccelerator               = 9
  constant RTRCdata (line 899) | RTRCdata                    = 10
  constant RTMessageTable (line 900) | RTMessageTable              = 11
  constant RTGroupCursor (line 901) | RTGroupCursor               = RTCursor + 11
  constant RTGroupIcon (line 902) | RTGroupIcon                 = RTIcon + 11
  constant RTVersion (line 903) | RTVersion                   = 16
  constant RTDlgInclude (line 904) | RTDlgInclude                = 17
  constant RTPlugPlay (line 905) | RTPlugPlay                  = 19
  constant RTVxD (line 906) | RTVxD                       = 20
  constant RTAniCursor (line 907) | RTAniCursor                 = 21
  constant RTAniIcon (line 908) | RTAniIcon                   = 22
  constant RTHtml (line 909) | RTHtml                      = 23
  constant RTManifest (line 910) | RTManifest                  = 24
  type ImageResourceDirectory (line 916) | type ImageResourceDirectory struct
  type ImageResourceDirectoryEntry (line 942) | type ImageResourceDirectoryEntry struct
  type ImageResourceDataEntry (line 954) | type ImageResourceDataEntry struct
  type ResourceDirectory (line 971) | type ResourceDirectory struct
  type ResourceDirectoryEntry (line 980) | type ResourceDirectoryEntry struct
  type ResourceDataEntry (line 1007) | type ResourceDataEntry struct
  method parseResourceDataEntry (line 1019) | func (pe *File) parseResourceDataEntry(rva uint32) ImageResourceDataEntry {
  method parseResourceDirectoryEntry (line 1030) | func (pe *File) parseResourceDirectoryEntry(rva uint32) *ImageResourceDi...
  method doParseResourceDirectory (line 1058) | func (pe *File) doParseResourceDirectory(rva, size, baseRVA, level uint32,
  method parseResourceDirectory (line 1182) | func (pe *File) parseResourceDirectory(rva, size uint32) error {
  function PrettyResourceLang (line 1674) | func PrettyResourceLang(lang ResourceLang, subLang int) string {

FILE: resource_test.go
  type TestRsrcDir (line 12) | type TestRsrcDir struct
  function TestParseResourceDirectory (line 23) | func TestParseResourceDirectory(t *testing.T) {
  function TestResourceTypeString (line 140) | func TestResourceTypeString(t *testing.T) {
  function TestResourceLangString (line 168) | func TestResourceLangString(t *testing.T) {
  function TestResourceSubLangString (line 197) | func TestResourceSubLangString(t *testing.T) {
  function TestPrettyResourceLang (line 226) | func TestPrettyResourceLang(t *testing.T) {

FILE: richheader.go
  constant DansSignature (line 16) | DansSignature = 0x536E6144
  constant RichSignature (line 19) | RichSignature = "Rich"
  constant AnoDansSigNotFound (line 22) | AnoDansSigNotFound = "Rich Header found, but could not locate DanS " +
  constant AnoPaddingDwordNotZero (line 27) | AnoPaddingDwordNotZero = "Rich header found: 3 leading padding DWORDs " +
  type CompID (line 32) | type CompID struct
  type RichHeader (line 53) | type RichHeader struct
  method ParseRichHeader (line 61) | func (pe *File) ParseRichHeader() error {
  method RichHeaderChecksum (line 166) | func (pe *File) RichHeaderChecksum() uint32 {
  method RichHeaderHash (line 195) | func (pe *File) RichHeaderHash() string {
  function ProdIDtoStr (line 218) | func ProdIDtoStr(prodID uint16) string {
  function ProdIDtoVSversion (line 503) | func ProdIDtoVSversion(prodID uint16) string {

FILE: richheader_test.go
  type TestRichHeader (line 12) | type TestRichHeader struct
  function TestParseRichHeader (line 20) | func TestParseRichHeader(t *testing.T) {
  function TestRichHeaderHash (line 145) | func TestRichHeaderHash(t *testing.T) {

FILE: scripts/extract-rsrc-lang.py
  class Language (line 5) | class Language:
    method __str__ (line 12) | def __str__(self) -> str:
  function sanitize_lang (line 15) | def sanitize_lang(language):
  function read_lang_ids (line 28) | def read_lang_ids(filename):
  function parse_txt_file (line 40) | def parse_txt_file(filename, lang_ids):
  function generate_go_code (line 88) | def generate_go_code(languages : list[Language]):
  function generate_lang_string (line 108) | def generate_lang_string(languages : list[Language]):
  function generate_sub_lang_string (line 116) | def generate_sub_lang_string(languages : list[Language]):
  function generate_lang_sub_lang_map_string (line 124) | def generate_lang_sub_lang_map_string(languages : list[Language]):
  function write_generated_code (line 142) | def write_generated_code(code, filename):

FILE: section.go
  constant ImageSectionReserved1 (line 16) | ImageSectionReserved1 = 0x00000000
  constant ImageSectionReserved2 (line 19) | ImageSectionReserved2 = 0x00000001
  constant ImageSectionReserved3 (line 22) | ImageSectionReserved3 = 0x00000002
  constant ImageSectionReserved4 (line 25) | ImageSectionReserved4 = 0x00000004
  constant ImageSectionTypeNoPad (line 30) | ImageSectionTypeNoPad = 0x00000008
  constant ImageSectionReserved5 (line 33) | ImageSectionReserved5 = 0x00000010
  constant ImageSectionCntCode (line 36) | ImageSectionCntCode = 0x00000020
  constant ImageSectionCntInitializedData (line 40) | ImageSectionCntInitializedData = 0x00000040
  constant ImageSectionCntUninitializedData (line 44) | ImageSectionCntUninitializedData = 0x00000080
  constant ImageSectionLnkOther (line 47) | ImageSectionLnkOther = 0x00000100
  constant ImageSectionLnkInfo (line 52) | ImageSectionLnkInfo = 0x00000200
  constant ImageSectionReserved6 (line 55) | ImageSectionReserved6 = 0x00000400
  constant ImageSectionLnkRemove (line 59) | ImageSectionLnkRemove = 0x00000800
  constant ImageSectionLnkCOMDAT (line 64) | ImageSectionLnkCOMDAT = 0x00001000
  constant ImageSectionGpRel (line 68) | ImageSectionGpRel = 0x00008000
  constant ImageSectionMemPurgeable (line 71) | ImageSectionMemPurgeable = 0x00020000
  constant ImageSectionMem16Bit (line 74) | ImageSectionMem16Bit = 0x00020000
  constant ImageSectionMemLocked (line 77) | ImageSectionMemLocked = 0x00040000
  constant ImageSectionMemPreload (line 80) | ImageSectionMemPreload = 0x00080000
  constant ImageSectionAlign1Bytes (line 84) | ImageSectionAlign1Bytes = 0x00100000
  constant ImageSectionAlign2Bytes (line 88) | ImageSectionAlign2Bytes = 0x00200000
  constant ImageSectionAlign4Bytes (line 92) | ImageSectionAlign4Bytes = 0x00300000
  constant ImageSectionAlign8Bytes (line 96) | ImageSectionAlign8Bytes = 0x00400000
  constant ImageSectionAlign16Bytes (line 100) | ImageSectionAlign16Bytes = 0x00500000
  constant ImageSectionAlign32Bytes (line 104) | ImageSectionAlign32Bytes = 0x00600000
  constant ImageSectionAlign64Bytes (line 108) | ImageSectionAlign64Bytes = 0x00700000
  constant ImageSectionAlign128Bytes (line 112) | ImageSectionAlign128Bytes = 0x00800000
  constant ImageSectionAlign256Bytes (line 116) | ImageSectionAlign256Bytes = 0x00900000
  constant ImageSectionAlign512Bytes (line 120) | ImageSectionAlign512Bytes = 0x00A00000
  constant ImageSectionAlign1024Bytes (line 124) | ImageSectionAlign1024Bytes = 0x00B00000
  constant ImageSectionAlign2048Bytes (line 128) | ImageSectionAlign2048Bytes = 0x00C00000
  constant ImageSectionAlign4096Bytes (line 132) | ImageSectionAlign4096Bytes = 0x00D00000
  constant ImageSectionAlign8192Bytes (line 136) | ImageSectionAlign8192Bytes = 0x00E00000
  constant ImageSectionLnkNRelocOvfl (line 140) | ImageSectionLnkNRelocOvfl = 0x01000000
  constant ImageSectionMemDiscardable (line 143) | ImageSectionMemDiscardable = 0x02000000
  constant ImageSectionMemNotCached (line 146) | ImageSectionMemNotCached = 0x04000000
  constant ImageSectionMemNotPaged (line 149) | ImageSectionMemNotPaged = 0x08000000
  constant ImageSectionMemShared (line 152) | ImageSectionMemShared = 0x10000000
  constant ImageSectionMemExecute (line 155) | ImageSectionMemExecute = 0x20000000
  constant ImageSectionMemRead (line 158) | ImageSectionMemRead = 0x40000000
  constant ImageSectionMemWrite (line 161) | ImageSectionMemWrite = 0x80000000
  type ImageSectionHeader (line 169) | type ImageSectionHeader struct
  type Section (line 231) | type Section struct
    method String (line 377) | func (section *Section) String() string {
    method NextHeaderAddr (line 382) | func (section *Section) NextHeaderAddr(pe *File) uint32 {
    method Contains (line 397) | func (section *Section) Contains(rva uint32, pe *File) bool {
    method Data (line 426) | func (section *Section) Data(start, length uint32, pe *File) []byte {
    method CalculateEntropy (line 467) | func (section *Section) CalculateEntropy(pe *File) float64 {
    method PrettySectionFlags (line 514) | func (section *Section) PrettySectionFlags() []string {
  method ParseSectionHeader (line 244) | func (pe *File) ParseSectionHeader() (err error) {
  type byVirtualAddress (line 495) | type byVirtualAddress
    method Len (line 497) | func (s byVirtualAddress) Len() int      { return len(s) }
    method Swap (line 498) | func (s byVirtualAddress) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    method Less (line 499) | func (s byVirtualAddress) Less(i, j int) bool {
  type byPointerToRawData (line 504) | type byPointerToRawData
    method Len (line 506) | func (s byPointerToRawData) Len() int      { return len(s) }
    method Swap (line 507) | func (s byPointerToRawData) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    method Less (line 508) | func (s byPointerToRawData) Less(i, j int) bool {

FILE: section_test.go
  type TestSection (line 13) | type TestSection struct
  function TestParseSectionHeaders (line 22) | func TestParseSectionHeaders(t *testing.T) {

FILE: security.go
  constant WinCertRevision1_0 (line 37) | WinCertRevision1_0 = 0x0100
  constant WinCertRevision2_0 (line 41) | WinCertRevision2_0 = 0x0200
  constant WinCertTypeX509 (line 49) | WinCertTypeX509 = 0x0001
  constant WinCertTypePKCSSignedData (line 52) | WinCertTypePKCSSignedData = 0x0002
  constant WinCertTypeReserved1 (line 55) | WinCertTypeReserved1 = 0x0003
  constant WinCertTypeTSStackSigned (line 58) | WinCertTypeTSStackSigned = 0x0004
  type CertificateSection (line 73) | type CertificateSection struct
  type Certificate (line 92) | type Certificate struct
  type WinCertificate (line 114) | type WinCertificate struct
  type CertInfo (line 127) | type CertInfo struct
  type RelRange (line 159) | type RelRange struct
  type byStart (line 164) | type byStart
    method Len (line 166) | func (s byStart) Len() int      { return len(s) }
    method Swap (line 167) | func (s byStart) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    method Less (line 168) | func (s byStart) Less(i, j int) bool {
  type Range (line 172) | type Range struct
  method parseLocations (line 177) | func (pe *File) parseLocations() (map[string]*RelRange, error) {
  method Authentihash (line 279) | func (pe *File) Authentihash() []byte {
  method AuthentihashExt (line 292) | func (pe *File) AuthentihashExt(hashers ...hash.Hash) [][]byte {
  method parseSecurityDirectory (line 344) | func (pe *File) parseSecurityDirectory(rva, size uint32) error {
  function loadSystemRoots (line 476) | func loadSystemRoots() (*x509.CertPool, error) {
  type SpcIndirectDataContent (line 534) | type SpcIndirectDataContent struct
  type SpcAttributeTypeAndOptionalValue (line 539) | type SpcAttributeTypeAndOptionalValue struct
  type SpcPeImageData (line 544) | type SpcPeImageData struct
  type DigestInfo (line 549) | type DigestInfo struct
  function parseHashAlgorithm (line 555) | func parseHashAlgorithm(identifier pkix.AlgorithmIdentifier) (crypto.Has...
  type AuthenticodeContent (line 584) | type AuthenticodeContent struct
  function parseAuthenticodeContent (line 590) | func parseAuthenticodeContent(content []byte) (AuthenticodeContent, erro...
  function formatPkixName (line 611) | func formatPkixName(name pkix.Name) string {

FILE: security_linux_mac.go
  function hideWindow (line 8) | func hideWindow(cmd *exec.Cmd) {

FILE: security_test.go
  type TestSecurityEntry (line 17) | type TestSecurityEntry struct
  function TestParseSecurityDirectory (line 23) | func TestParseSecurityDirectory(t *testing.T) {
  function TestAuthentihash (line 212) | func TestAuthentihash(t *testing.T) {

FILE: security_windows.go
  function hideWindow (line 11) | func hideWindow(cmd *exec.Cmd) {

FILE: symbol.go
  constant MaxDefaultCOFFSymbolsCount (line 20) | MaxDefaultCOFFSymbolsCount = 0x10000
  constant MaxCOFFSymStrLength (line 24) | MaxCOFFSymStrLength = 0x50
  constant ImageSymTypeNull (line 32) | ImageSymTypeNull = 0
  constant ImageSymTypeVoid (line 35) | ImageSymTypeVoid = 1
  constant ImageSymTypeChar (line 38) | ImageSymTypeChar = 2
  constant ImageSymTypeShort (line 41) | ImageSymTypeShort = 3
  constant ImageSymTypeInt (line 45) | ImageSymTypeInt = 4
  constant ImageSymTypeLong (line 48) | ImageSymTypeLong = 5
  constant ImageSymTypeFloat (line 51) | ImageSymTypeFloat = 6
  constant ImageSymTypeDouble (line 54) | ImageSymTypeDouble = 7
  constant ImageSymTypeStruct (line 57) | ImageSymTypeStruct = 8
  constant ImageSymTypeUnion (line 60) | ImageSymTypeUnion = 9
  constant ImageSymTypeEnum (line 63) | ImageSymTypeEnum = 10
  constant ImageSymTypeMoe (line 66) | ImageSymTypeMoe = 11
  constant ImageSymTypeByte (line 69) | ImageSymTypeByte = 12
  constant ImageSymTypeWord (line 72) | ImageSymTypeWord = 13
  constant ImageSymTypeUint (line 76) | ImageSymTypeUint = 14
  constant ImageSymTypeDword (line 79) | ImageSymTypeDword = 15
  constant ImageSymClassEndOfFunction (line 87) | ImageSymClassEndOfFunction = 0xff
  constant ImageSymClassNull (line 90) | ImageSymClassNull = 0
  constant ImageSymClassAutomatic (line 94) | ImageSymClassAutomatic = 1
  constant ImageSymClassExternal (line 100) | ImageSymClassExternal = 2
  constant ImageSymClassStatic (line 105) | ImageSymClassStatic = 3
  constant ImageSymClassRegister (line 109) | ImageSymClassRegister = 4
  constant ImageSymClassExternalDef (line 112) | ImageSymClassExternalDef = 5
  constant ImageSymClassLabel (line 117) | ImageSymClassLabel = 6
  constant ImageSymClassUndefinedLabel (line 121) | ImageSymClassUndefinedLabel = 7
  constant ImageSymClassMemberOfStruct (line 125) | ImageSymClassMemberOfStruct = 8
  constant ImageSymClassArgument (line 129) | ImageSymClassArgument = 9
  constant ImageSymClassStructTag (line 132) | ImageSymClassStructTag = 10
  constant ImageSymClassMemberOfUnion (line 136) | ImageSymClassMemberOfUnion = 11
  constant ImageSymClassUnionTag (line 139) | ImageSymClassUnionTag = 12
  constant ImageSymClassTypeDefinition (line 142) | ImageSymClassTypeDefinition = 13
  constant ImageSymClassUndefinedStatic (line 145) | ImageSymClassUndefinedStatic = 14
  constant ImageSymClassEnumTag (line 148) | ImageSymClassEnumTag = 15
  constant ImageSymClassMemberOfEnum (line 152) | ImageSymClassMemberOfEnum = 16
  constant ImageSymClassRegisterParam (line 155) | ImageSymClassRegisterParam = 17
  constant ImageSymClassBitField (line 159) | ImageSymClassBitField = 18
  constant ImageSymClassBlock (line 164) | ImageSymClassBlock = 100
  constant ImageSymClassFunction (line 172) | ImageSymClassFunction = 101
  constant ImageSymClassEndOfStruct (line 175) | ImageSymClassEndOfStruct = 102
  constant ImageSymClassFile (line 180) | ImageSymClassFile = 103
  constant ImageSymClassSsection (line 184) | ImageSymClassSsection = 104
  constant ImageSymClassWeakExternal (line 188) | ImageSymClassWeakExternal = 24
  constant ImageSymClassClrToken (line 193) | ImageSymClassClrToken = 25
  constant ImageSymUndefined (line 203) | ImageSymUndefined = 0
  constant ImageSymAbsolute (line 207) | ImageSymAbsolute = -1
  constant ImageSymDebug (line 212) | ImageSymDebug = -2
  type COFFSymbol (line 230) | type COFFSymbol struct
    method String (line 381) | func (symbol *COFFSymbol) String(pe *File) (string, error) {
    method SectionNumberName (line 411) | func (symbol *COFFSymbol) SectionNumberName(pe *File) string {
  type COFF (line 267) | type COFF struct
  method ParseCOFFSymbolTable (line 282) | func (pe *File) ParseCOFFSymbolTable() error {
  method COFFStringTable (line 325) | func (pe *File) COFFStringTable() error {
  method PrettyCOFFTypeRepresentation (line 435) | func (pe *File) PrettyCOFFTypeRepresentation(k uint16) string {

FILE: symbol_test.go
  type TestCOFFSymbol (line 9) | type TestCOFFSymbol struct
  function TestParseCOFFSymbolTable (line 78) | func TestParseCOFFSymbolTable(t *testing.T) {

FILE: tls.go
  type TLSDirectoryCharacteristicsType (line 13) | type TLSDirectoryCharacteristicsType
    method String (line 164) | func (characteristics TLSDirectoryCharacteristicsType) String() string {
  type TLSDirectory (line 16) | type TLSDirectory struct
  type ImageTLSDirectory32 (line 27) | type ImageTLSDirectory32 struct
  type ImageTLSDirectory64 (line 62) | type ImageTLSDirectory64 struct
  method parseTLSDirectory (line 99) | func (pe *File) parseTLSDirectory(rva, size uint32) error {

FILE: tls_test.go
  function TestParseTLSDirectory (line 12) | func TestParseTLSDirectory(t *testing.T) {
  function TestTLSDirectoryCharacteristics (line 85) | func TestTLSDirectoryCharacteristics(t *testing.T) {

FILE: version.go
  constant VersionResourceType (line 15) | VersionResourceType = 16
  constant VsVersionInfoString (line 18) | VsVersionInfoString = "VS_VERSION_INFO"
  constant VsFileInfoSignature (line 21) | VsFileInfoSignature uint32 = 0xFEEF04BD
  constant StringFileInfoString (line 24) | StringFileInfoString = "StringFileInfo"
  constant VarFileInfoString (line 26) | VarFileInfoString = "VarFileInfo"
  constant VsVersionInfoStringLength (line 29) | VsVersionInfoStringLength uint32 = 6
  constant StringFileInfoLength (line 31) | StringFileInfoLength uint32 = 6
  constant StringTableLength (line 33) | StringTableLength uint32 = 6
  constant StringLength (line 35) | StringLength uint32 = 6
  constant LangIDLength (line 38) | LangIDLength uint32 = 8*2 + 1
  type VsVersionInfo (line 44) | type VsVersionInfo struct
  method parseVersionInfo (line 60) | func (pe *File) parseVersionInfo(e ResourceDirectoryEntry) (*VsVersionIn...
  type VsFixedFileInfo (line 86) | type VsFixedFileInfo struct
    method Size (line 127) | func (f *VsFixedFileInfo) Size() uint32 { return uint32(binary.Size(f)) }
    method GetStringFileInfoOffset (line 129) | func (f *VsFixedFileInfo) GetStringFileInfoOffset(e ResourceDirectoryE...
    method GetOffset (line 133) | func (f *VsFixedFileInfo) GetOffset(e ResourceDirectoryEntry, pe *File...
  method parseFixedFileInfo (line 139) | func (pe *File) parseFixedFileInfo(e ResourceDirectoryEntry) (*VsFixedFi...
  type StringFileInfo (line 158) | type StringFileInfo struct
    method GetStringTableOffset (line 164) | func (s *StringFileInfo) GetStringTableOffset(offset uint32) uint32 {
    method GetOffset (line 168) | func (s *StringFileInfo) GetOffset(rva uint32, e ResourceDirectoryEntr...
  method parseStringFileInfo (line 173) | func (pe *File) parseStringFileInfo(rva uint32, e ResourceDirectoryEntry...
  type StringTable (line 194) | type StringTable struct
    method GetStringOffset (line 200) | func (s *StringTable) GetStringOffset(offset uint32, e ResourceDirecto...
    method GetOffset (line 204) | func (s *StringTable) GetOffset(rva uint32, e ResourceDirectoryEntry, ...
  method parseStringTable (line 209) | func (pe *File) parseStringTable(rva uint32, e ResourceDirectoryEntry) (...
  type String (line 243) | type String struct
    method GetOffset (line 249) | func (s *String) GetOffset(rva uint32, e ResourceDirectoryEntry, pe *F...
    method getOffsetAndPadding (line 257) | func (s *String) getOffsetAndPadding(rva uint32, e ResourceDirectoryEn...
  method parseString (line 263) | func (pe *File) parseString(rva uint32, e ResourceDirectoryEntry) (strin...
  method ParseVersionResources (line 305) | func (pe *File) ParseVersionResources() (map[string]string, error) {
  method parseVersionEntry (line 330) | func (pe *File) parseVersionEntry(e ResourceDirectoryEntry, vers map[str...
  method ParseVersionResourcesForEntries (line 396) | func (pe *File) ParseVersionResourcesForEntries() ([]map[string]string, ...

FILE: version_test.go
  function TestParseVersionResources (line 53) | func TestParseVersionResources(t *testing.T) {
Condensed preview — 91 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (864K chars).
[
  {
    "path": ".editorconfig",
    "chars": 354,
    "preview": "; https://editorconfig.org/\n\nroot = true\n\n[*]\ninsert_final_newline = true\ncharset = utf-8\ntrim_trailing_whitespace = tru"
  },
  {
    "path": ".gitattributes",
    "chars": 639,
    "preview": "# Treat all files in the Go repo as binary, with no git magic updating\n# line endings. This produces predictable results"
  },
  {
    "path": ".github/FUNDING.YML",
    "chars": 22,
    "preview": "github: LordNoteworthy"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "chars": 1365,
    "preview": "name: Build & Test\n\non: [push]\n\njobs:\n  test:\n    name: Build & Test\n    strategy:\n      fail-fast: false\n      matrix:\n"
  },
  {
    "path": ".gitignore",
    "chars": 405,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 8476,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3217,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2021 Saferwall\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 9816,
    "preview": "<a href=\"https://saferwall.com\" target=\"_blank\" rel=\"noopener noreferrer\"><img align=\"right\" width=\"300\" src=\".github/as"
  },
  {
    "path": "anomaly.go",
    "chars": 9150,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "anomaly_test.go",
    "chars": 1265,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "arch.go",
    "chars": 380,
    "preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "boundimports.go",
    "chars": 5412,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "boundimports_test.go",
    "chars": 2799,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "cmd/dump.go",
    "chars": 38742,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "cmd/main.go",
    "chars": 4419,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "cmd/size.go",
    "chars": 4060,
    "preview": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"strconv\"\r\n\t\"strings\"\r\n)\r\n\r\n// See: http://en.wikipedia.org/wiki/Binary_prefix\r\nconst"
  },
  {
    "path": "cmd/size_test.go",
    "chars": 8356,
    "preview": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"reflect\"\r\n\t\"runtime\"\r\n\t\"strings\"\r\n\t\"testing\"\r\n)\r\n\r\nfunc ExampleBytesSize() {\r\n\tfmt.P"
  },
  {
    "path": "debug.go",
    "chars": 25355,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "debug_test.go",
    "chars": 16929,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "delayimports.go",
    "chars": 5648,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "delayimports_test.go",
    "chars": 2879,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "dosheader.go",
    "chars": 3134,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "dosheader_test.go",
    "chars": 2227,
    "preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "dotnet.go",
    "chars": 27669,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "dotnet_helper.go",
    "chars": 3685,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "dotnet_metadata_tables.go",
    "chars": 41741,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "dotnet_test.go",
    "chars": 20861,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "exception.go",
    "chars": 21226,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "exception_test.go",
    "chars": 3668,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "exports.go",
    "chars": 10560,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "exports_test.go",
    "chars": 4178,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "file.go",
    "chars": 12067,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "file_test.go",
    "chars": 3155,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "globalptr.go",
    "chars": 1130,
    "preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "go.mod",
    "chars": 151,
    "preview": "module github.com/saferwall/pe\n\ngo 1.15\n\nrequire (\n\tgithub.com/ayoubfaouzi/pkcs7 v0.2.3\n\tgithub.com/edsrzf/mmap-go v1.1."
  },
  {
    "path": "go.sum",
    "chars": 6406,
    "preview": "github.com/ayoubfaouzi/pkcs7 v0.2.3 h1:XGCYHteXgclHnNlPdCF8aFyoUKwP9VhLQp+VX+hBZ3U=\ngithub.com/ayoubfaouzi/pkcs7 v0.2.3/"
  },
  {
    "path": "helper.go",
    "chars": 20168,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "helper_test.go",
    "chars": 1994,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "iat.go",
    "chars": 1874,
    "preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "imports.go",
    "chars": 25164,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "imports_test.go",
    "chars": 4246,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "loadconfig.go",
    "chars": 57033,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "loadconfig_test.go",
    "chars": 29890,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "log/README.md",
    "chars": 1026,
    "preview": "# Logger\n\nThis code was taken from the go microservice framework [kratos](https://github.com/go-kratos/kratos).\n\n## Usag"
  },
  {
    "path": "log/filter.go",
    "chars": 2097,
    "preview": "package log\n\n// FilterOption is filter option.\ntype FilterOption func(*Filter)\n\nconst fuzzyStr = \"***\"\n\n// FilterLevel w"
  },
  {
    "path": "log/filter_test.go",
    "chars": 3512,
    "preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"testing\"\n)\n\nfunc TestFilterAll(t *testing.T) {\n\tlogger := With(DefaultLogger, \"ts"
  },
  {
    "path": "log/global.go",
    "chars": 2650,
    "preview": "package log\n\nimport (\n\t\"sync\"\n)\n\n// globalLogger is designed as a global logger in current process.\nvar global = &logger"
  },
  {
    "path": "log/global_test.go",
    "chars": 1895,
    "preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestGlobalLog(t *testing.T) {\n\tbuffer := &byte"
  },
  {
    "path": "log/helper.go",
    "chars": 3290,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n)\n\n// DefaultMessageKey default message key.\nvar DefaultMessageKey = \"msg\""
  },
  {
    "path": "log/helper_test.go",
    "chars": 1746,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestHelper(t *testing.T) {\n\tlogger := With(DefaultLogger"
  },
  {
    "path": "log/level.go",
    "chars": 970,
    "preview": "package log\n\nimport \"strings\"\n\n// Level is a logger level.\ntype Level int8\n\n// LevelKey is logger level key.\nconst Level"
  },
  {
    "path": "log/level_test.go",
    "chars": 1375,
    "preview": "package log\n\nimport \"testing\"\n\nfunc TestLevel_String(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n\t\tl    Level\n\t\tw"
  },
  {
    "path": "log/log.go",
    "chars": 1590,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"log\"\n)\n\n// DefaultLogger is default logger.\nvar DefaultLogger = NewStdLogger(log.Writ"
  },
  {
    "path": "log/log_test.go",
    "chars": 528,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestInfo(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = Wi"
  },
  {
    "path": "log/std.go",
    "chars": 871,
    "preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"sync\"\n)\n\nvar _ Logger = (*stdLogger)(nil)\n\ntype stdLogger struct {\n"
  },
  {
    "path": "log/std_test.go",
    "chars": 452,
    "preview": "package log\n\nimport \"testing\"\n\nfunc TestStdLogger(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = With(logger, \"calle"
  },
  {
    "path": "log/value.go",
    "chars": 1618,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar (\n\tdefaultDepth = 3\n\t// DefaultCaller i"
  },
  {
    "path": "log/value_test.go",
    "chars": 637,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestValue(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = With(lo"
  },
  {
    "path": "ntheader.go",
    "chars": 25005,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "ntheader_test.go",
    "chars": 3332,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "ordlookup.go",
    "chars": 13129,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "overlay.go",
    "chars": 992,
    "preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "overlay_test.go",
    "chars": 1305,
    "preview": "package pe\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"testing\"\n)\n\ntype TestOverlay struct {\n\toverlayOffset int64\n\toverlay"
  },
  {
    "path": "pe.go",
    "chars": 11089,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "reloc.go",
    "chars": 10512,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "reloc_test.go",
    "chars": 7189,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "resource.go",
    "chars": 79479,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "resource_test.go",
    "chars": 5861,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "richheader.go",
    "chars": 15697,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "richheader_test.go",
    "chars": 4210,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "scripts/extract-rsrc-lang.py",
    "chars": 5466,
    "preview": "# Text file containing languages and sub-languages extracted from:\r\n# Language Identifier Constants and Strings for Micr"
  },
  {
    "path": "scripts/ms-lcid.txt",
    "chars": 25250,
    "preview": "Afar 0x1000 aa\r\nAfar Djibouti 0x1000 aa-DJ\r\nAfar Eritrea 0x1000 aa-ER\r\nAfar Ethiopia 0x1000 aa-ET\r\nAfrikaans 0x0036 af\r\n"
  },
  {
    "path": "section.go",
    "chars": 20170,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "section_test.go",
    "chars": 2370,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "security.go",
    "chars": 19890,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "security_linux_mac.go",
    "chars": 114,
    "preview": "//go:build !windows\r\n// +build !windows\r\n\r\npackage pe\r\n\r\nimport \"os/exec\"\r\n\r\nfunc hideWindow(cmd *exec.Cmd) {\r\n}\r\n"
  },
  {
    "path": "security_test.go",
    "chars": 8435,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "security_windows.go",
    "chars": 190,
    "preview": "//go:build windows\r\n// +build windows\r\n\r\npackage pe\r\n\r\nimport (\r\n\t\"os/exec\"\r\n\t\"syscall\"\r\n)\r\n\r\nfunc hideWindow(cmd *exec."
  },
  {
    "path": "staticcheck.conf",
    "chars": 48,
    "preview": "checks = [\"all\", \"-ST1000\", \"-U1000\", \"-SA1019\"]"
  },
  {
    "path": "symbol.go",
    "chars": 15266,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "symbol_test.go",
    "chars": 3896,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "tls.go",
    "chars": 6977,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "tls_test.go",
    "chars": 2753,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
  },
  {
    "path": "version.go",
    "chars": 14830,
    "preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  },
  {
    "path": "version_test.go",
    "chars": 3335,
    "preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
  }
]

// ... and 5 more files (download for full content)

About this extraction

This page contains the full source code of the saferwall/pe GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 91 files (765.7 KB), approximately 233.6k tokens, and a symbol index with 1452 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!