├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── CI.yml │ ├── check_wsl.yml │ └── nuget_org_only.config ├── .gitignore ├── doc ├── PE.png ├── ar_class_diagram.png ├── elf_class_diagram.png └── readme.md ├── img ├── banner.png ├── libobjectfile.pdn └── libobjectfile.png ├── license.txt ├── readme.md └── src ├── .dockerignore ├── Directory.Build.props ├── Directory.Packages.props ├── Dockerfile ├── LibObjectFile.Bench ├── LibObjectFile.Bench.csproj └── Program.cs ├── LibObjectFile.CodeGen ├── LibObjectFile.CodeGen.csproj ├── Program.Dwarf.cs ├── Program.cs ├── dwarf.h └── elf.h ├── LibObjectFile.Tests ├── Ar │ ├── ArTestBase.cs │ └── ArTests.cs ├── ByteArrayAssert.cs ├── Dwarf │ └── DwarfTests.cs ├── Elf │ ├── ElfSimpleTests.cs │ ├── ElfTestBase.cs │ ├── compile_files.sh │ ├── helloworld │ ├── helloworld.cpp │ ├── helloworld.o │ ├── helloworld_debug │ ├── lib_a.cpp │ ├── lib_b.cpp │ ├── lib_debug.so │ ├── libhelloworld.a │ ├── libstdc++.so │ ├── multiple_functions.cpp │ ├── multiple_functions_debug.o │ ├── small.cpp │ └── small_debug.o ├── IO │ └── TestBatchDataReaderWriter.cs ├── LibObjectFile.Tests.csproj ├── LinuxUtil.cs ├── PE │ ├── NativeConsole2Win64.exe │ ├── NativeConsoleWin64.exe │ ├── NativeLibraryWin64.dll │ ├── PEReaderTests.cs │ └── RawNativeConsoleWin64.exe ├── TestFiles │ └── cmnlib.b00 ├── TestsInitializer.cs └── Verified │ ├── ArTests.CheckCreateArLibrary.verified.txt │ ├── ElfSimpleTests.SimpleCodeSection.verified.txt │ ├── ElfSimpleTests.SimpleCodeSectionAndSymbolSection.verified.txt │ ├── ElfSimpleTests.SimpleEmpty.verified.txt │ ├── ElfSimpleTests.SimpleEmptyWithDefaultSections.verified.txt │ ├── ElfSimpleTests.SimpleProgramHeaderAndCodeSectionAndSymbolSection.verified.txt │ ├── ElfSimpleTests.SimpleProgramHeaderAndCodeSectionAndSymbolSectionAndRelocation.verified.txt │ ├── ElfSimpleTests.TestAlignedSection.verified.txt │ ├── ElfSimpleTests.TestBss.verified.txt │ ├── ElfSimpleTests.TestElf_name=helloworld.verified.txt │ ├── ElfSimpleTests.TestElf_name=helloworld_debug.verified.txt │ ├── ElfSimpleTests.TestElf_name=lib_debug.so.verified.txt │ ├── ElfSimpleTests.TestElf_name=libstdc++.so.verified.txt │ ├── ElfSimpleTests.TestElf_name=multiple_functions_debug.o.verified.txt │ ├── ElfSimpleTests.TestElf_name=small_debug.o.verified.txt │ ├── PEReaderTests.TestPrinter_name=NativeConsole2Win64.exe.verified.txt │ ├── PEReaderTests.TestPrinter_name=NativeConsoleWin64.exe.verified.txt │ ├── PEReaderTests.TestPrinter_name=NativeLibraryWin64.dll.verified.txt │ ├── PEReaderTests.TestPrinter_name=RawNativeConsoleWin64.exe.verified.txt │ └── PEReaderTests.TestTinyExe97Bytes.verified.txt ├── LibObjectFile.sln ├── LibObjectFile.sln.DotSettings ├── LibObjectFile ├── Ar │ ├── Ar.cd │ ├── ArArchiveFile.cs │ ├── ArArchiveFileReader.cs │ ├── ArArchiveFileReaderOptions.cs │ ├── ArArchiveFileWriter.cs │ ├── ArArchiveKind.cs │ ├── ArBinaryFile.cs │ ├── ArElfFile.cs │ ├── ArFile.cs │ ├── ArFileEntry.Constants.cs │ ├── ArLongNamesTable.cs │ ├── ArObject.cs │ ├── ArSymbol.cs │ ├── ArSymbolTable.cs │ └── ArVisitorContext.cs ├── Collections │ ├── ObjectList.cs │ ├── ReadOnlyList.cs │ ├── SortedObjectList.cs │ └── TempSpan.cs ├── Diagnostics │ ├── DiagnosticBag.cs │ ├── DiagnosticId.cs │ ├── DiagnosticKind.cs │ └── DiagnosticMessage.cs ├── Dwarf │ ├── DwarfAbbreviation.cs │ ├── DwarfAbbreviationItem.cs │ ├── DwarfAbbreviationItemKey.cs │ ├── DwarfAbbreviationTable.cs │ ├── DwarfAccessibility.cs │ ├── DwarfAddressRange.cs │ ├── DwarfAddressRangeTable.cs │ ├── DwarfAddressSize.cs │ ├── DwarfArrayOrderingKind.cs │ ├── DwarfAttribute.cs │ ├── DwarfAttributeDescriptor.cs │ ├── DwarfAttributeDescriptors.cs │ ├── DwarfAttributeEncoding.cs │ ├── DwarfAttributeFormEx.cs │ ├── DwarfAttributeKindEx.cs │ ├── DwarfAttributeValue.cs │ ├── DwarfCallingConventionEx.cs │ ├── DwarfCompilationUnit.cs │ ├── DwarfConstant.cs │ ├── DwarfContainer.cs │ ├── DwarfDIE.cs │ ├── DwarfDIEDeclaration.cs │ ├── DwarfDiscriminantListKind.cs │ ├── DwarfElfContext.cs │ ├── DwarfExpression.cs │ ├── DwarfFile.cs │ ├── DwarfFileName.cs │ ├── DwarfHelper.cs │ ├── DwarfIdentifierCaseKind.cs │ ├── DwarfInfoSection.cs │ ├── DwarfInlineKind.cs │ ├── DwarfInteger.cs │ ├── DwarfLanguageKindEx.cs │ ├── DwarfLayoutConfig.cs │ ├── DwarfLayoutContext.cs │ ├── DwarfLine.cs │ ├── DwarfLineProgramTable.cs │ ├── DwarfLineSection.cs │ ├── DwarfLineSequence.cs │ ├── DwarfLineState.cs │ ├── DwarfLocation.cs │ ├── DwarfLocationList.cs │ ├── DwarfLocationListEntry.cs │ ├── DwarfLocationSection.cs │ ├── DwarfObject.cs │ ├── DwarfOperation.cs │ ├── DwarfOperationKindEx.cs │ ├── DwarfPrinter.cs │ ├── DwarfReader.cs │ ├── DwarfReaderContext.cs │ ├── DwarfReaderWriter.cs │ ├── DwarfReaderWriterContext.cs │ ├── DwarfRelocatableSection.cs │ ├── DwarfRelocation.cs │ ├── DwarfRelocationTarget.cs │ ├── DwarfSection.cs │ ├── DwarfSectionLink.cs │ ├── DwarfStreamExtensions.cs │ ├── DwarfStringTable.cs │ ├── DwarfTagEx.cs │ ├── DwarfUnit.cs │ ├── DwarfUnitKind.cs │ ├── DwarfVirtuality.cs │ ├── DwarfVisibility.cs │ ├── DwarfWriter.cs │ └── DwarfWriterContext.cs ├── Elf │ ├── Elf.cd │ ├── ElfArch.cs │ ├── ElfContent.cs │ ├── ElfContentData.cs │ ├── ElfContentRange.cs │ ├── ElfDecoderDirect.cs │ ├── ElfDecoderSwap.cs │ ├── ElfEncoderDirect.cs │ ├── ElfEncoderSwap.cs │ ├── ElfEncoding.cs │ ├── ElfFile.Read.cs │ ├── ElfFile.Write.cs │ ├── ElfFile.cs │ ├── ElfFileClass.cs │ ├── ElfFileLayout.cs │ ├── ElfFileType.cs │ ├── ElfHeaderContent.cs │ ├── ElfHeaderFlags.cs │ ├── ElfNativeExtensions.cs │ ├── ElfOSABIEx.cs │ ├── ElfObjectFileExtensions.cs │ ├── ElfOffsetCalculationMode.cs │ ├── ElfPrinter.cs │ ├── ElfProgramHeaderTable.cs │ ├── ElfProgramHeaderTable32.cs │ ├── ElfProgramHeaderTable64.cs │ ├── ElfReader.cs │ ├── ElfReaderDirect.cs │ ├── ElfReaderOptions.cs │ ├── ElfReaderSwap.cs │ ├── ElfReader{TDecoder}.cs │ ├── ElfSection.cs │ ├── ElfSectionExtension.cs │ ├── ElfSectionFlags.cs │ ├── ElfSectionHeaderTable.cs │ ├── ElfSectionLink.cs │ ├── ElfSectionSpecialType.cs │ ├── ElfSectionType.cs │ ├── ElfSegment.cs │ ├── ElfSegmentFlags.cs │ ├── ElfSegmentFlagsCore.cs │ ├── ElfSegmentType.cs │ ├── ElfSegmentTypeCore.cs │ ├── ElfStreamContentData.cs │ ├── ElfString.cs │ ├── ElfVisitorContext.cs │ ├── ElfWriter.cs │ ├── ElfWriterDirect.cs │ ├── ElfWriterSwap.cs │ ├── ElfWriter{TEncoder}.cs │ ├── IElfDecoder.cs │ ├── IElfEncoder.cs │ └── Sections │ │ ├── ElfCustomNote.cs │ │ ├── ElfGnuNote.cs │ │ ├── ElfGnuNoteABITag.cs │ │ ├── ElfGnuNoteBuildId.cs │ │ ├── ElfGnuNoteOSKind.cs │ │ ├── ElfNoBitsSection.cs │ │ ├── ElfNote.cs │ │ ├── ElfNoteTable.cs │ │ ├── ElfNoteType.cs │ │ ├── ElfNullSection.cs │ │ ├── ElfRelocation.cs │ │ ├── ElfRelocationContext.cs │ │ ├── ElfRelocationTable.cs │ │ ├── ElfRelocationTableExtensions.cs │ │ ├── ElfRelocationType.cs │ │ ├── ElfSectionHeaderStringTable.cs │ │ ├── ElfStreamSection.cs │ │ ├── ElfStringTable.cs │ │ ├── ElfSymbol.cs │ │ ├── ElfSymbolBind.cs │ │ ├── ElfSymbolTable.cs │ │ ├── ElfSymbolTableSectionHeaderIndices.cs │ │ ├── ElfSymbolType.cs │ │ └── ElfSymbolVisibility.cs ├── IO │ ├── BatchDataReader.cs │ ├── BatchDataWriter.cs │ ├── StreamExtensions.cs │ ├── SubStream.cs │ └── TextWriterIndenter.cs ├── LibObjectFile.csproj ├── LibObjectFile.csproj.DotSettings ├── ObjectElement.cs ├── ObjectFileElement.cs ├── ObjectFileElementHolder.cs ├── ObjectFileException.cs ├── ObjectFileReaderWriter.cs ├── PE │ ├── DataDirectory │ │ ├── PEArchitectureDirectory.cs │ │ ├── PEBaseRelocation.cs │ │ ├── PEBaseRelocationBlock.cs │ │ ├── PEBaseRelocationDirectory.cs │ │ ├── PEBaseRelocationType.cs │ │ ├── PEBlobDataLink.cs │ │ ├── PEBoundImportAddressTable.cs │ │ ├── PEBoundImportAddressTable32.cs │ │ ├── PEBoundImportAddressTable64.cs │ │ ├── PEBoundImportDirectory.cs │ │ ├── PEBoundImportDirectoryEntry.cs │ │ ├── PEBoundImportForwarderRef.cs │ │ ├── PEClrMetadata.cs │ │ ├── PECompositeSectionData.cs │ │ ├── PEDataDirectory.cs │ │ ├── PEDataDirectoryKind.cs │ │ ├── PEDebugDirectory.cs │ │ ├── PEDebugDirectoryEntry.cs │ │ ├── PEDebugKnownType.cs │ │ ├── PEDebugSectionData.cs │ │ ├── PEDebugSectionDataRSDS.cs │ │ ├── PEDebugStreamExtraData.cs │ │ ├── PEDebugStreamSectionData.cs │ │ ├── PEDebugType.cs │ │ ├── PEDelayImportDirectory.cs │ │ ├── PEDelayImportDirectoryEntry.cs │ │ ├── PEDirectoryTable.cs │ │ ├── PEExceptionDirectory.cs │ │ ├── PEExceptionFunctionEntry.cs │ │ ├── PEExceptionFunctionEntryArm.cs │ │ ├── PEExceptionFunctionEntryX86.cs │ │ ├── PEExportAddressTable.cs │ │ ├── PEExportDirectory.cs │ │ ├── PEExportFunctionEntry.cs │ │ ├── PEExportNameTable.cs │ │ ├── PEExportOrdinalTable.cs │ │ ├── PEGlobalPointerDirectory.cs │ │ ├── PEGuardFlags.cs │ │ ├── PEImportAddressTable.cs │ │ ├── PEImportAddressTable32.cs │ │ ├── PEImportAddressTable64.cs │ │ ├── PEImportAddressTableDirectory.cs │ │ ├── PEImportDirectory.cs │ │ ├── PEImportDirectoryEntry.cs │ │ ├── PEImportFunctionEntry.cs │ │ ├── PEImportFunctionTable.cs │ │ ├── PEImportLookupTable.cs │ │ ├── PEImportLookupTable32.cs │ │ ├── PEImportLookupTable64.cs │ │ ├── PELoadConfigCodeIntegrity.cs │ │ ├── PELoadConfigDirectory.cs │ │ ├── PELoadConfigDirectory32.cs │ │ ├── PELoadConfigDirectory64.cs │ │ ├── PELoadConfigDirectoryData32.cs │ │ ├── PELoadConfigDirectoryData64.cs │ │ ├── PERawDataDirectory.cs │ │ ├── PEResourceData.cs │ │ ├── PEResourceDataEntry.cs │ │ ├── PEResourceDirectory.cs │ │ ├── PEResourceDirectoryEntry.cs │ │ ├── PEResourceDirectoryEntryById.cs │ │ ├── PEResourceDirectoryEntryByName.cs │ │ ├── PEResourceEntry.cs │ │ ├── PEResourceId.cs │ │ ├── PEResourceString.cs │ │ ├── PESectionVirtualSizeMode.cs │ │ ├── PESecurityCertificate.cs │ │ ├── PESecurityCertificateDirectory.cs │ │ ├── PESecurityCertificateRevision.cs │ │ ├── PESecurityCertificateType.cs │ │ ├── PEThunkAddressTable.cs │ │ ├── PETlsCharacteristics.cs │ │ ├── PETlsDirectory.cs │ │ ├── PETlsDirectory32.cs │ │ ├── PETlsDirectory64.cs │ │ ├── PETlsDirectoryData32.cs │ │ ├── PETlsDirectoryData64.cs │ │ └── PEUnknownDirectory.cs │ ├── IPELink.cs │ ├── Internal │ │ ├── RawDelayLoadDescriptor.cs │ │ ├── RawExceptionFunctionEntryARM.cs │ │ ├── RawExceptionFunctionEntryX86.cs │ │ ├── RawImageDataDirectory.cs │ │ ├── RawImageDataDirectoryArray.cs │ │ ├── RawImageDebugDirectory.cs │ │ ├── RawImageOptionalHeader32.cs │ │ ├── RawImageOptionalHeader64.cs │ │ ├── RawImageOptionalHeaderBase32.cs │ │ ├── RawImageOptionalHeaderBase64.cs │ │ ├── RawImageOptionalHeaderCommonPart1.cs │ │ ├── RawImageOptionalHeaderCommonPart2.cs │ │ ├── RawImageOptionalHeaderCommonPart3.cs │ │ ├── RawImageOptionalHeaderSize32.cs │ │ ├── RawImageOptionalHeaderSize64.cs │ │ ├── RawImageResourceDirectoryEntry.cs │ │ ├── RawImageSectionHeader.cs │ │ ├── RawImportDirectoryEntry.cs │ │ ├── RawImportFunctionEntry32.cs │ │ ├── RawImportFunctionEntry64.cs │ │ ├── RawPEBoundImportDirectory.cs │ │ └── RawPEBoundImportForwarderRef.cs │ ├── PE.cd │ ├── PEAsciiStringLink.cs │ ├── PECoffHeader.cs │ ├── PEDosHeader.cs │ ├── PEDosMagic.cs │ ├── PEExtraData.cs │ ├── PEFile.Layout.cs │ ├── PEFile.Read.cs │ ├── PEFile.Relocate.cs │ ├── PEFile.Verify.cs │ ├── PEFile.Write.cs │ ├── PEFile.cs │ ├── PEFunctionAddressLink.cs │ ├── PEImageReader.cs │ ├── PEImageReaderOptions.cs │ ├── PEImageWriter.cs │ ├── PEImageWriterOptions.cs │ ├── PEImportHintName.cs │ ├── PEImportHintNameLink.cs │ ├── PEModuleHandleLink.cs │ ├── PEObject.cs │ ├── PEObjectBase.cs │ ├── PEObjectBaseExtensions.cs │ ├── PEObjectExtensions.cs │ ├── PEOptionalHeader.cs │ ├── PEOptionalHeaderMagic.cs │ ├── PEPrinter.cs │ ├── PESection.cs │ ├── PESectionData.cs │ ├── PESectionDataExtensions.cs │ ├── PESectionDataLink.cs │ ├── PESectionLink.cs │ ├── PESectionName.Defaults.cs │ ├── PESectionName.cs │ ├── PESignature.cs │ ├── PEStreamExtraData.cs │ ├── PEStreamSectionData.cs │ ├── PEVisitorContext.cs │ ├── RVA.cs │ ├── RVO.cs │ ├── VA32.cs │ └── VA64.cs ├── Utils │ ├── AlignHelper.cs │ └── DataUtils.cs ├── VisitorContextBase.cs └── generated │ ├── LibObjectFile.Dwarf.generated.cs │ └── LibObjectFile.Elf.generated.cs ├── dotnet-releaser.toml ├── global.json ├── native └── Win64 │ └── NativeProjects │ ├── NativeConsole2Win64 │ ├── NativeConsole2Win64.cpp │ ├── NativeConsole2Win64.vcxproj │ └── NativeConsole2Win64.vcxproj.filters │ ├── NativeConsoleWin64 │ ├── NativeConsoleWin64.cpp │ ├── NativeConsoleWin64.vcxproj │ └── NativeConsoleWin64.vcxproj.filters │ ├── NativeLibraryWin64 │ ├── NativeLibraryWin64.vcxproj │ ├── NativeLibraryWin64.vcxproj.filters │ ├── dllmain.cpp │ ├── framework.h │ ├── pch.cpp │ └── pch.h │ ├── NativeProjects.sln │ └── RawNativeConsoleWin64 │ ├── RawNativeConsoleWin64.cpp │ ├── RawNativeConsoleWin64.vcxproj │ └── RawNativeConsoleWin64.vcxproj.filters ├── objdasm ├── ObjDisasmApp.cs ├── Program.cs └── objdasm.csproj └── test-with-docker.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | *.sh text eol=lf 4 | *.verified.txt text eol=lf working-tree-encoding=UTF-8 5 | *.verified.xml text eol=lf working-tree-encoding=UTF-8 6 | *.verified.json text eol=lf working-tree-encoding=UTF-8 -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [xoofx] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'doc/**' 7 | - 'changelog.md' 8 | - 'readme.md' 9 | pull_request: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - name: "Build, Test, Pack and Publish" 16 | uses: xoofx/.github/.github/actions/dotnet-releaser-action@main 17 | with: 18 | NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/check_wsl.yml: -------------------------------------------------------------------------------- 1 | name: check_wsl 2 | on: 3 | # Run this workflow only manually 4 | workflow_dispatch: 5 | jobs: 6 | build: 7 | runs-on: windows-latest 8 | steps: 9 | - uses: Vampire/setup-wsl@v3 10 | with: 11 | distribution: Ubuntu-22.04 12 | - name: List installed WSL distributions 13 | run: wsl -l -v 14 | -------------------------------------------------------------------------------- /.github/workflows/nuget_org_only.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /doc/PE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/doc/PE.png -------------------------------------------------------------------------------- /doc/ar_class_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/doc/ar_class_diagram.png -------------------------------------------------------------------------------- /doc/elf_class_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/doc/elf_class_diagram.png -------------------------------------------------------------------------------- /img/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/img/banner.png -------------------------------------------------------------------------------- /img/libobjectfile.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/img/libobjectfile.pdn -------------------------------------------------------------------------------- /img/libobjectfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/img/libobjectfile.png -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Alexandre Mutel 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification 5 | , are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .dockerignore 3 | **/bin/ 4 | **/obj/ -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | True 4 | True 5 | $(NoWarn);CS1591;CS1573;CS1574;CS1734;CS0419 6 | 7 | -------------------------------------------------------------------------------- /src/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | RUN apt-get update && apt-get -y install \ 4 | # .NET Core SDK needs: https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?pivots=os-linux&tabs=netcore31#supported-operating-systems 5 | curl libcurl4 libssl1.0.0 zlib1g libicu60 libkrb5-3 liblttng-ust0 \ 6 | # Tests need: 7 | build-essential gcc 8 | 9 | ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 10 | RUN curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --version 3.0.100 11 | 12 | ENV PATH="/root/.dotnet:${PATH}" 13 | RUN dotnet --info 14 | 15 | WORKDIR /src 16 | 17 | CMD dotnet test -------------------------------------------------------------------------------- /src/LibObjectFile.Bench/LibObjectFile.Bench.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/LibObjectFile.CodeGen/LibObjectFile.CodeGen.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | Exe 5 | false 6 | $(NETCoreSdkRuntimeIdentifier) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | PreserveNewest 18 | 19 | 20 | PreserveNewest 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Ar/ArTestBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using LibObjectFile.Diagnostics; 7 | using LibObjectFile.Tests.Elf; 8 | 9 | namespace LibObjectFile.Tests.Ar; 10 | 11 | public abstract class ArTestBase : ElfTestBase 12 | { 13 | protected static void ExpectNoDiagnostics(DiagnosticBag diagnostics) 14 | { 15 | if (diagnostics.Messages.Count != 0) 16 | { 17 | Console.WriteLine(diagnostics); 18 | Assert.AreEqual(0, diagnostics.Messages.Count, $"Invalid number of diagnostics found, expecting no diagnostics"); 19 | } 20 | } 21 | 22 | protected static void ExpectDiagnostics(DiagnosticBag diagnostics, params DiagnosticId[] ids) 23 | { 24 | if (diagnostics.Messages.Count != ids.Length) 25 | { 26 | Console.WriteLine(diagnostics); 27 | Assert.AreEqual(ids.Length, diagnostics.Messages.Count, $"Invalid number of diagnostics found, expecting {ids.Length} entries [{string.Join(", ", ids)}]"); 28 | } 29 | 30 | for (var i = 0; i < diagnostics.Messages.Count; i++) 31 | { 32 | var diagnosticsMessage = diagnostics.Messages[i]; 33 | var expectedId = ids[i]; 34 | 35 | if (expectedId != diagnosticsMessage.Id) 36 | { 37 | Console.WriteLine(diagnostics); 38 | Assert.AreEqual(expectedId, diagnosticsMessage.Id, $"Invalid Id {diagnosticsMessage.Id} found for diagnostics [{i}] while expecting {expectedId} from entries [{string.Join(", ", ids)}]"); 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/compile_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gcc helloworld.cpp -o helloworld 3 | gcc helloworld.cpp -c -o helloworld.o 4 | ar rcs libhelloworld.a helloworld.o 5 | gcc helloworld.cpp -gdwarf-4 -o helloworld_debug 6 | gcc lib_a.cpp lib_b.cpp -gdwarf-4 -shared -o lib_debug.so 7 | gcc small.cpp -gdwarf-4 -c -o small_debug.o 8 | gcc multiple_functions.cpp -gdwarf-4 -c -o multiple_functions_debug.o 9 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/helloworld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/helloworld -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/helloworld.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char** argv) 3 | { 4 | printf("HelloWorld!\n"); 5 | } 6 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/helloworld.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/helloworld.o -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/helloworld_debug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/helloworld_debug -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/lib_a.cpp: -------------------------------------------------------------------------------- 1 | int process_add(int a, int b) 2 | { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/lib_b.cpp: -------------------------------------------------------------------------------- 1 | float process_add2(float a, float b) 2 | { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/lib_debug.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/lib_debug.so -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/libhelloworld.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/libhelloworld.a -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/libstdc++.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/libstdc++.so -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/multiple_functions.cpp: -------------------------------------------------------------------------------- 1 | int process_add(int a, int b) 2 | { 3 | return a + b; 4 | } 5 | 6 | float process_add2(float a, float b) 7 | { 8 | return a + b; 9 | } 10 | 11 | float process_both(int a, float b) 12 | { 13 | return (float)process_add(a, (int)b) + process_add2((float)a, b); 14 | } 15 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/multiple_functions_debug.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/multiple_functions_debug.o -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/small.cpp: -------------------------------------------------------------------------------- 1 | struct MyStruct 2 | { 3 | unsigned char* str; 4 | 5 | int count; 6 | }; 7 | 8 | typedef char (*TransformCharDelegate)(char); 9 | 10 | int ProcessStructs(MyStruct* input, MyStruct* output, TransformCharDelegate transform) 11 | { 12 | int acc = 0; 13 | for(int i = 0; i < input->count; i++) 14 | { 15 | auto value1 = input->str[i]; 16 | auto value2 = output->str[i]; 17 | auto value3 = transform(value1) + transform(value2); 18 | 19 | acc += value1 + value2 + value3; 20 | } 21 | return acc; 22 | } 23 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Elf/small_debug.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/Elf/small_debug.o -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/PE/NativeConsole2Win64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/PE/NativeConsole2Win64.exe -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/PE/NativeConsoleWin64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/PE/NativeConsoleWin64.exe -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/PE/NativeLibraryWin64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/PE/NativeLibraryWin64.dll -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/PE/RawNativeConsoleWin64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/PE/RawNativeConsoleWin64.exe -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/TestFiles/cmnlib.b00: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoofx/LibObjectFile/1d110e2181af9f4792a0b52b84faafe9df43c433/src/LibObjectFile.Tests/TestFiles/cmnlib.b00 -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/TestsInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Runtime.CompilerServices; 3 | using VerifyMSTest; 4 | using VerifyTests; 5 | using VerifyTests.DiffPlex; 6 | 7 | namespace LibObjectFile.Tests; 8 | 9 | internal static class TestsInitializer 10 | { 11 | [ModuleInitializer] 12 | public static void Initialize() 13 | { 14 | VerifyDiffPlex.Initialize(OutputType.Compact); 15 | CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; 16 | Verifier.UseProjectRelativeDirectory("Verified"); 17 | DiffEngine.DiffRunner.Disabled = true; 18 | VerifierSettings.DontScrubSolutionDirectory(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Verified/ArTests.CheckCreateArLibrary.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | filenames: 3 | file2.txt 4 | file3.txt 5 | file4.txt 6 | file5.txt 7 | long_file_name_large_file6.txt, 8 | filecontent: this is filethis is file3this is file4this is file5this is file6 yoyo 9 | } -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Verified/ElfSimpleTests.SimpleEmpty.verified.txt: -------------------------------------------------------------------------------- 1 | ELF Header: 2 | Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 3 | Class: ELF64 4 | Data: 2's complement, little endian 5 | Version: 1 (current) 6 | OS/ABI: UNIX - System V 7 | ABI Version: 0 8 | Type: REL (Relocatable file) 9 | Machine: Advanced Micro Devices X86-64 10 | Version: 0x1 11 | Entry point address: 0x0 12 | Start of program headers: 0 (bytes into file) 13 | Start of section headers: 0 (bytes into file) 14 | Flags: 0x0 15 | Size of this header: 0 (bytes) 16 | Size of program headers: 0 (bytes) 17 | Number of program headers: 0 18 | Size of section headers: 0 (bytes) 19 | Number of section headers: 0 20 | Section header string table index: 0 21 | 22 | There are no sections in this file. 23 | 24 | There are no section groups in this file. 25 | 26 | There are no program headers in this file. 27 | 28 | There is no dynamic section in this file. 29 | 30 | There are no relocations in this file. 31 | No processor specific unwind information to decode 32 | 33 | Dynamic symbol information is not available for displaying symbols. 34 | 35 | No version information found in this file. 36 | -------------------------------------------------------------------------------- /src/LibObjectFile.Tests/Verified/ElfSimpleTests.SimpleEmptyWithDefaultSections.verified.txt: -------------------------------------------------------------------------------- 1 | ELF Header: 2 | Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 3 | Class: ELF64 4 | Data: 2's complement, little endian 5 | Version: 1 (current) 6 | OS/ABI: UNIX - System V 7 | ABI Version: 0 8 | Type: REL (Relocatable file) 9 | Machine: Advanced Micro Devices X86-64 10 | Version: 0x1 11 | Entry point address: 0x0 12 | Start of program headers: 0 (bytes into file) 13 | Start of section headers: 0 (bytes into file) 14 | Flags: 0x0 15 | Size of this header: 0 (bytes) 16 | Size of program headers: 0 (bytes) 17 | Number of program headers: 0 18 | Size of section headers: 0 (bytes) 19 | Number of section headers: 1 20 | Section header string table index: 0 21 | 22 | Section Header: 23 | [Nr] Name Type Address Off Size ES Flg Lk Inf Al 24 | [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 25 | Key to Flags: 26 | W (write), A (alloc), X (execute), M (merge), S (strings), I (info), 27 | L (link order), O (extra OS processing required), G (group), T (TLS), 28 | C (compressed), x (unknown), o (OS specific), E (exclude), 29 | D (mbind), l (large), p (processor specific) 30 | 31 | There are no section groups in this file. 32 | 33 | There are no program headers in this file. 34 | 35 | There is no dynamic section in this file. 36 | 37 | There are no relocations in this file. 38 | No processor specific unwind information to decode 39 | 40 | No version information found in this file. 41 | -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArArchiveFileReaderOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Ar; 6 | 7 | /// 8 | /// Reader options used by and other methods. 9 | /// 10 | public class ArArchiveFileReaderOptions 11 | { 12 | /// 13 | /// Initializes a new instance. 14 | /// 15 | /// Type of the 'ar' file to load (GNU, BSD...) 16 | public ArArchiveFileReaderOptions(ArArchiveKind archiveKind) 17 | { 18 | ArchiveKind = archiveKind; 19 | ProcessObjectFiles = true; 20 | } 21 | 22 | /// 23 | /// Gets or sets a boolean indicating if the file entries must keep a readonly view 24 | /// on the original stream for the content of the file entries, or it should copy 25 | /// them to modifiable . 26 | /// 27 | public bool IsReadOnly { get; set; } 28 | 29 | /// 30 | /// Gets or sets the type of file to load 31 | /// 32 | public ArArchiveKind ArchiveKind { get; set; } 33 | 34 | /// 35 | /// Gets or sets a boolean indicating if object files are being processed to return 36 | /// typed entries () instead of generic binary file entry (). 37 | /// Default is true 38 | /// 39 | public bool ProcessObjectFiles { get; set; } 40 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArArchiveKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Ar; 6 | 7 | /// 8 | /// The type of archive. 9 | /// 10 | public enum ArArchiveKind 11 | { 12 | /// 13 | /// The common variant, used for example by 'deb' package files. 14 | /// Supports only file names up to 16 characters. 15 | /// 16 | Common, 17 | 18 | /// 19 | /// The GNU variant, used by the `ar` utility on GNU and other systems (including Windows) 20 | /// Based on file format, but using a different strategy 21 | /// for storing long file names, incompatible with format. 22 | /// 23 | GNU, 24 | 25 | /// 26 | /// The BSD variant, used by the `ar` utility on BSD systems (including MacOS) 27 | /// Based on file format and backward compatible with it, 28 | /// but allows to store longer file names and file names containing space. 29 | /// 30 | BSD, 31 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArBinaryFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Ar; 8 | 9 | /// 10 | /// An binary stream . 11 | /// 12 | public sealed class ArBinaryFile : ArFile 13 | { 14 | /// 15 | /// Gets or sets the stream associated to this entry. 16 | /// 17 | public Stream? Stream { get; set; } 18 | 19 | public override void Read(ArArchiveFileReader reader) 20 | { 21 | Stream = reader.ReadAsStream(Size); 22 | } 23 | 24 | public override void Write(ArArchiveFileWriter writer) 25 | { 26 | if (Stream != null) 27 | { 28 | writer.Write(Stream); 29 | } 30 | } 31 | 32 | protected override void UpdateLayoutCore(ArVisitorContext context) 33 | { 34 | Size = Stream != null ? (ulong) Stream.Length : 0; 35 | } 36 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArElfFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Elf; 6 | using LibObjectFile.IO; 7 | 8 | namespace LibObjectFile.Ar; 9 | 10 | /// 11 | /// An ELF file entry. 12 | /// 13 | public sealed class ArElfFile : ArFile 14 | { 15 | public ArElfFile() 16 | { 17 | } 18 | 19 | public ArElfFile(ElfFile elfFile) 20 | { 21 | ElfFile = elfFile; 22 | } 23 | 24 | /// 25 | /// Gets or sets the ELF object file. 26 | /// 27 | public ElfFile? ElfFile { get; set; } 28 | 29 | public override void Read(ArArchiveFileReader reader) 30 | { 31 | var startPosition = reader.Stream.Position; 32 | var endPosition = startPosition + (long) Size; 33 | ElfFile = ElfFile.Read(new SubStream(reader.Stream, reader.Stream.Position, (long)Size)); 34 | reader.Stream.Position = endPosition; 35 | } 36 | 37 | public override void Write(ArArchiveFileWriter writer) 38 | { 39 | if (ElfFile != null) 40 | { 41 | ElfFile.TryWrite(writer.Stream, out var diagnostics); 42 | diagnostics.CopyTo(writer.Diagnostics); 43 | } 44 | } 45 | 46 | protected override void UpdateLayoutCore(ArVisitorContext context) 47 | { 48 | Size = 0; 49 | 50 | if (ElfFile != null) 51 | { 52 | ElfFile.UpdateLayout(context.Diagnostics); 53 | if (!context.HasErrors) 54 | { 55 | Size = ElfFile.Layout.TotalSize; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | using LibObjectFile.Elf; 8 | 9 | namespace LibObjectFile.Ar; 10 | 11 | public abstract class ArObjectBase : ObjectFileElement 12 | { 13 | } 14 | 15 | public abstract class ArObject : ArObjectBase 16 | { 17 | /// 18 | /// Gets the containing . Might be null if this section or segment 19 | /// does not belong to an existing . 20 | /// 21 | [DebuggerBrowsable(DebuggerBrowsableState.Never)] 22 | public new ArArchiveFile? Parent 23 | { 24 | get => (ArArchiveFile?)base.Parent; 25 | internal set => base.Parent = value; 26 | } 27 | 28 | protected override void ValidateParent(ObjectElement parent) 29 | { 30 | if (!(parent is ArArchiveFile)) 31 | { 32 | throw new ArgumentException($"Parent must inherit from type {nameof(ArArchiveFile)}"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArSymbol.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Ar; 6 | 7 | /// 8 | /// A symbol stored in a 9 | /// 10 | public struct ArSymbol 11 | { 12 | /// 13 | /// Initializes a new instance. 14 | /// 15 | /// The name of the symbol. 16 | /// The associated file entry this symbol is coming from . 17 | public ArSymbol(string name, ArFile file) : this() 18 | { 19 | Name = name; 20 | File = file; 21 | } 22 | 23 | /// 24 | /// Gets or sets the name of this symbol. 25 | /// 26 | public string Name { get; set; } 27 | 28 | /// 29 | /// Internal offset for the name (used for reading) 30 | /// 31 | internal uint NameOffset { get; set; } 32 | 33 | /// 34 | /// Gets or sets the associated file entry this symbol is coming from . 35 | /// 36 | public ArFile File { get; set; } 37 | 38 | /// 39 | /// Internal offset of the file (used for reading) 40 | /// 41 | internal ulong FileOffset { get; set; } 42 | 43 | public override string ToString() 44 | { 45 | return $"Symbol: {Name} => {nameof(File)}: {File}"; 46 | } 47 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Ar/ArVisitorContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | 7 | namespace LibObjectFile.Ar; 8 | 9 | public class ArVisitorContext : VisitorContextBase 10 | { 11 | internal ArVisitorContext(ArArchiveFile file, DiagnosticBag diagnostics) : base(file, diagnostics) 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Diagnostics/DiagnosticKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Diagnostics; 6 | 7 | /// 8 | /// Defines the kind of a 9 | /// 10 | public enum DiagnosticKind 11 | { 12 | /// 13 | /// A warning message. 14 | /// 15 | Warning, 16 | 17 | /// 18 | /// An error message. 19 | /// 20 | Error, 21 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Diagnostics/DiagnosticMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.Diagnostics; 8 | 9 | /// 10 | /// A diagnostic message. 11 | /// 12 | public readonly struct DiagnosticMessage 13 | { 14 | public DiagnosticMessage(DiagnosticKind kind, DiagnosticId id, string message) 15 | { 16 | Kind = kind; 17 | Id = id; 18 | Context = null; 19 | Message = message; 20 | } 21 | 22 | public DiagnosticMessage(DiagnosticKind kind, DiagnosticId id, string message, object? context) 23 | { 24 | Kind = kind; 25 | Id = id; 26 | Context = context; 27 | Message = message; 28 | } 29 | 30 | /// 31 | /// Gets the kind of this message. 32 | /// 33 | public DiagnosticKind Kind { get; } 34 | 35 | /// 36 | /// Gets the id of this message. 37 | /// 38 | public DiagnosticId Id { get; } 39 | 40 | /// 41 | /// Gets the context of this message. 42 | /// 43 | public object? Context { get; } 44 | 45 | /// 46 | /// Gets the associated text of this message. 47 | /// 48 | public string Message { get; } 49 | 50 | /// 51 | /// Gets the associated stack trace of this message. 52 | /// 53 | public StackTrace? StackTrace { get; init; } 54 | 55 | public override string ToString() 56 | { 57 | if (StackTrace is not null) 58 | { 59 | return $"{Kind} LB{(uint)Id:0000}: {Message}\n{StackTrace}"; 60 | } 61 | else 62 | { 63 | return $"{Kind} LB{(uint)Id:0000}: {Message}"; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAccessibility.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfAccessibility : byte 8 | { 9 | Public = DwarfNative.DW_ACCESS_public, 10 | 11 | Private = DwarfNative.DW_ACCESS_private, 12 | 13 | Protected = DwarfNative.DW_ACCESS_protected, 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAddressRange.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public struct DwarfAddressRange 8 | { 9 | public DwarfAddressRange(ulong segment, ulong address, ulong length) 10 | { 11 | Segment = segment; 12 | Address = address; 13 | Length = length; 14 | } 15 | 16 | public ulong Segment { get; set; } 17 | 18 | public ulong Address { get; set; } 19 | 20 | public ulong Length { get; set; } 21 | 22 | public override string ToString() 23 | { 24 | return $"{nameof(Segment)}: 0x{Segment:x16}, {nameof(Address)}: 0x{Address:x16}, {nameof(Length)}: 0x{Length:x16}"; 25 | } 26 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAddressSize.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfAddressSize : byte 8 | { 9 | None = 0, 10 | 11 | Bit8 = 1, 12 | 13 | Bit16 = 2, 14 | 15 | Bit32 = 4, 16 | 17 | Bit64 = 8, 18 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfArrayOrderingKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfArrayOrderingKind : byte 8 | { 9 | RowMajor = DwarfNative.DW_ORD_row_major, 10 | 11 | ColumnMajor = DwarfNative.DW_ORD_col_major, 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAttributeDescriptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | 8 | namespace LibObjectFile.Dwarf; 9 | 10 | [DebuggerDisplay("{Kind} {Form}")] 11 | public readonly struct DwarfAttributeDescriptor : IEquatable 12 | { 13 | public static readonly DwarfAttributeDescriptor Empty = new DwarfAttributeDescriptor(); 14 | 15 | public DwarfAttributeDescriptor(DwarfAttributeKindEx kind, DwarfAttributeFormEx form) 16 | { 17 | Kind = kind; 18 | Form = form; 19 | } 20 | 21 | public readonly DwarfAttributeKindEx Kind; 22 | 23 | public readonly DwarfAttributeFormEx Form; 24 | 25 | public bool IsNull => Kind.Value == 0 && Form.Value == 0; 26 | 27 | public bool Equals(DwarfAttributeDescriptor other) 28 | { 29 | return Kind.Equals(other.Kind) && Form.Equals(other.Form); 30 | } 31 | 32 | public override bool Equals(object? obj) 33 | { 34 | return obj is DwarfAttributeDescriptor other && Equals(other); 35 | } 36 | 37 | public override int GetHashCode() 38 | { 39 | unchecked 40 | { 41 | return (Kind.GetHashCode() * 397) ^ Form.GetHashCode(); 42 | } 43 | } 44 | 45 | public static bool operator ==(DwarfAttributeDescriptor left, DwarfAttributeDescriptor right) 46 | { 47 | return left.Equals(right); 48 | } 49 | 50 | public static bool operator !=(DwarfAttributeDescriptor left, DwarfAttributeDescriptor right) 51 | { 52 | return !left.Equals(right); 53 | } 54 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAttributeEncoding.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | [Flags] 10 | public enum DwarfAttributeEncoding 11 | { 12 | None, 13 | 14 | Address = 1, 15 | 16 | Block = 1 << 1, 17 | 18 | Constant = 1 << 2, 19 | 20 | ExpressionLocation = 1 << 3, 21 | 22 | Flag = 1 << 4, 23 | 24 | LinePointer = 1 << 5, 25 | 26 | LocationListPointer = 1 << 6, 27 | 28 | MacroPointer = 1 << 7, 29 | 30 | RangeListPointer = 1 << 8, 31 | 32 | Reference = 1 << 9, 33 | 34 | String = 1 << 10, 35 | 36 | RangeList = 1 << 11, 37 | 38 | Indirect = 1 << 12, 39 | 40 | LocationList = 1 << 13, 41 | 42 | AddressPointer = 1 << 14, 43 | 44 | LocationListsPointer = 1 << 15, 45 | 46 | RangeListsPointer = 1 << 16, 47 | 48 | StringOffsetPointer = 1 << 17, 49 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfAttributeValue.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public class DwarfAttributeValue 8 | { 9 | public DwarfAttributeValue(object value) 10 | { 11 | Value = value; 12 | } 13 | 14 | public object Value { get; set; } 15 | 16 | public override string ToString() 17 | { 18 | return $"{nameof(Value)}: {Value}"; 19 | } 20 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfCallingConventionEx.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public readonly partial struct DwarfCallingConventionEx : IEquatable 10 | { 11 | public DwarfCallingConventionEx(byte value) 12 | { 13 | Value = (DwarfCallingConvention)value; 14 | } 15 | 16 | public DwarfCallingConventionEx(DwarfCallingConvention value) 17 | { 18 | Value = value; 19 | } 20 | 21 | public readonly DwarfCallingConvention Value; 22 | 23 | public override string ToString() 24 | { 25 | return ToStringInternal() ?? $"Unknown {nameof(DwarfCallingConvention)} (0x{Value:x2})"; 26 | } 27 | 28 | public bool Equals(DwarfCallingConventionEx other) 29 | { 30 | return Value == other.Value; 31 | } 32 | 33 | public override bool Equals(object? obj) 34 | { 35 | return obj is DwarfCallingConventionEx other && Equals(other); 36 | } 37 | 38 | public override int GetHashCode() 39 | { 40 | return Value.GetHashCode(); 41 | } 42 | 43 | public static bool operator ==(DwarfCallingConventionEx left, DwarfCallingConventionEx right) 44 | { 45 | return left.Equals(right); 46 | } 47 | 48 | public static bool operator !=(DwarfCallingConventionEx left, DwarfCallingConventionEx right) 49 | { 50 | return !left.Equals(right); 51 | } 52 | 53 | public static explicit operator uint(DwarfCallingConventionEx callConv) => (uint)callConv.Value; 54 | 55 | public static implicit operator DwarfCallingConventionEx(DwarfCallingConvention callConv) => new DwarfCallingConventionEx(callConv); 56 | 57 | public static implicit operator DwarfCallingConvention(DwarfCallingConventionEx callConv) => callConv.Value; 58 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public abstract class DwarfContainer : DwarfObject 8 | { 9 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfDIEDeclaration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public abstract class DwarfDIEDeclaration : DwarfDIE 8 | { 9 | // DW_AT_decl_column, DW_AT_decl_file, and DW_AT_decl_line 10 | public ulong? DeclColumn 11 | { 12 | get => GetAttributeValueOpt(DwarfAttributeKind.DeclColumn); 13 | set => SetAttributeValueOpt(DwarfAttributeKind.DeclColumn, value); 14 | } 15 | 16 | public DwarfFileName? DeclFile 17 | { 18 | get => GetAttributeValue(DwarfAttributeKind.DeclFile); 19 | set => SetAttributeValue(DwarfAttributeKind.DeclFile, value); 20 | } 21 | 22 | public ulong? DeclLine 23 | { 24 | get => GetAttributeValueOpt(DwarfAttributeKind.DeclLine); 25 | set => SetAttributeValueOpt(DwarfAttributeKind.DeclLine, value); 26 | } 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfDiscriminantListKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfDiscriminantListKind : byte 8 | { 9 | Label = DwarfNative.DW_DSC_label, 10 | 11 | Range = DwarfNative.DW_DSC_range, 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfFileName.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public sealed class DwarfFileName 10 | { 11 | public DwarfFileName(string name) 12 | { 13 | Name = name; 14 | } 15 | 16 | public string Name { get; } 17 | 18 | public string? Directory { get; set; } 19 | 20 | public ulong Time { get; set; } 21 | 22 | public ulong Size { get; set; } 23 | 24 | public override string ToString() 25 | { 26 | if (Directory != null) 27 | { 28 | return Directory.Contains(Path.AltDirectorySeparatorChar) ? $"{Directory}{Path.AltDirectorySeparatorChar}{Name}" : $"{Directory}{Path.DirectorySeparatorChar}{Name}"; 29 | } 30 | 31 | return Name; 32 | } 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfIdentifierCaseKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfIdentifierCaseKind : byte 8 | { 9 | Sensitive = DwarfNative.DW_ID_case_sensitive, 10 | 11 | UpCase = DwarfNative.DW_ID_up_case, 12 | 13 | DownCase = DwarfNative.DW_ID_down_case, 14 | 15 | Insensitive = DwarfNative.DW_ID_case_insensitive, 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfInlineKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfInlineKind : byte 8 | { 9 | NotInlined = DwarfNative.DW_INL_not_inlined, 10 | 11 | Inlined = DwarfNative.DW_INL_inlined, 12 | 13 | DeclaredNotInlined = DwarfNative.DW_INL_declared_not_inlined, 14 | 15 | DeclaredInlined = DwarfNative.DW_INL_declared_inlined, 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfInteger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | [StructLayout(LayoutKind.Explicit)] 10 | public struct DwarfInteger 11 | { 12 | [FieldOffset(0)] 13 | public ulong U64; 14 | 15 | [FieldOffset(0)] 16 | public long I64; 17 | 18 | [FieldOffset(0)] 19 | public sbyte I8; 20 | 21 | [FieldOffset(0)] 22 | public byte U8; 23 | 24 | [FieldOffset(0)] 25 | public short I16; 26 | 27 | [FieldOffset(0)] 28 | public ushort U16; 29 | 30 | [FieldOffset(0)] 31 | public int I32; 32 | 33 | [FieldOffset(0)] 34 | public uint U32; 35 | 36 | public override string ToString() 37 | { 38 | return $"0x{U64:x16}"; 39 | } 40 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfLanguageKindEx.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public readonly partial struct DwarfLanguageKindEx : IEquatable 10 | { 11 | public DwarfLanguageKindEx(ushort value) 12 | { 13 | Value = (DwarfLanguageKind)value; 14 | } 15 | 16 | public DwarfLanguageKindEx(DwarfLanguageKind value) 17 | { 18 | Value = value; 19 | } 20 | 21 | public readonly DwarfLanguageKind Value; 22 | 23 | public override string ToString() 24 | { 25 | return ToStringInternal() ?? $"Unknown {nameof(DwarfLanguageKind)} (0x{Value:x4})"; 26 | } 27 | 28 | public bool Equals(DwarfLanguageKindEx other) 29 | { 30 | return Value == other.Value; 31 | } 32 | 33 | public override bool Equals(object? obj) 34 | { 35 | return obj is DwarfLanguageKindEx other && Equals(other); 36 | } 37 | 38 | public override int GetHashCode() 39 | { 40 | return Value.GetHashCode(); 41 | } 42 | 43 | public static bool operator ==(DwarfLanguageKindEx left, DwarfLanguageKindEx right) 44 | { 45 | return left.Equals(right); 46 | } 47 | 48 | public static bool operator !=(DwarfLanguageKindEx left, DwarfLanguageKindEx right) 49 | { 50 | return !left.Equals(right); 51 | } 52 | 53 | public static explicit operator uint(DwarfLanguageKindEx kind) => (uint)kind.Value; 54 | 55 | public static implicit operator DwarfLanguageKindEx(DwarfLanguageKind kind) => new DwarfLanguageKindEx(kind); 56 | 57 | public static implicit operator DwarfLanguageKind(DwarfLanguageKindEx kind) => kind.Value; 58 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfLayoutConfig.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public class DwarfLayoutConfig 10 | { 11 | private DwarfAttributeForm _defaultAttributeFormForReference; 12 | 13 | public DwarfLayoutConfig() 14 | { 15 | DefaultAttributeFormForReference = DwarfAttributeForm.Ref4; 16 | } 17 | 18 | public DwarfAttributeFormEx DefaultAttributeFormForReference 19 | { 20 | get => _defaultAttributeFormForReference; 21 | set 22 | { 23 | switch (value.Value) 24 | { 25 | case DwarfAttributeForm.Ref1: 26 | case DwarfAttributeForm.Ref2: 27 | case DwarfAttributeForm.Ref4: 28 | break; 29 | default: 30 | throw new ArgumentOutOfRangeException(nameof(value)); 31 | } 32 | 33 | _defaultAttributeFormForReference = value; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfLayoutContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | 10 | 11 | public abstract class DwarfVisitorContext : VisitorContextBase 12 | { 13 | internal DwarfVisitorContext(DwarfFile file, DiagnosticBag diagnostics) : base(file, diagnostics) 14 | { 15 | } 16 | } 17 | 18 | 19 | public sealed class DwarfLayoutContext : DwarfVisitorContext 20 | { 21 | internal DwarfLayoutContext(DwarfFile file, DwarfLayoutConfig config, DiagnosticBag diagnostics) : base(file, diagnostics) 22 | { 23 | Config = config; 24 | } 25 | 26 | public DwarfLayoutConfig Config { get; } 27 | 28 | public DwarfUnit? CurrentUnit { get; internal set; } 29 | } 30 | 31 | public sealed class DwarfVerifyContext : DwarfVisitorContext 32 | { 33 | internal DwarfVerifyContext(DwarfFile file, DiagnosticBag diagnostics) : base(file, diagnostics) 34 | { 35 | } 36 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfLineSequence.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using LibObjectFile.Collections; 9 | 10 | namespace LibObjectFile.Dwarf; 11 | 12 | /// 13 | /// A sequence of 14 | /// 15 | [DebuggerDisplay("Count = {Lines.Count,nq}")] 16 | public class DwarfLineSequence : DwarfObject, IEnumerable 17 | { 18 | private readonly ObjectList _lines; 19 | 20 | public DwarfLineSequence() 21 | { 22 | _lines = new ObjectList(this); 23 | } 24 | 25 | public ObjectList Lines => _lines; 26 | 27 | public void Add(DwarfLine line) 28 | { 29 | _lines.Add(line); 30 | } 31 | 32 | protected override void UpdateLayoutCore(DwarfLayoutContext context) 33 | { 34 | // This is implemented in DwarfLineSection 35 | } 36 | 37 | public override void Read(DwarfReader reader) 38 | { 39 | // This is implemented in DwarfLineSection 40 | } 41 | 42 | public override void Write(DwarfWriter writer) 43 | { 44 | // This is implemented in DwarfLineSection 45 | } 46 | 47 | public List.Enumerator GetEnumerator() 48 | { 49 | return _lines.GetEnumerator(); 50 | } 51 | 52 | IEnumerator IEnumerable.GetEnumerator() 53 | { 54 | return GetEnumerator(); 55 | } 56 | 57 | IEnumerator IEnumerable.GetEnumerator() 58 | { 59 | return ((IEnumerable) _lines).GetEnumerator(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfLocation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public struct DwarfLocation 8 | { 9 | public DwarfLocation(int value) 10 | { 11 | AsValue = new DwarfInteger() { I64 = value }; 12 | AsObject = null; 13 | } 14 | 15 | public DwarfLocation(DwarfExpression expression) 16 | { 17 | AsValue = default; 18 | AsObject = expression; 19 | } 20 | 21 | public DwarfLocation(DwarfLocationList locationList) 22 | { 23 | AsValue = default; 24 | AsObject = locationList; 25 | } 26 | 27 | public DwarfInteger AsValue; 28 | 29 | public object? AsObject; 30 | 31 | public DwarfExpression? AsExpression => AsObject as DwarfExpression; 32 | 33 | public DwarfLocationList? AsLocationList => AsObject as DwarfLocationList; 34 | 35 | public DwarfDIE? AsReference => AsObject as DwarfDIE; 36 | 37 | public override string ToString() 38 | { 39 | if (AsExpression != null) return $"Location Expression: {AsExpression}"; 40 | if (AsLocationList != null) return $"Location List: {AsLocationList}"; 41 | if (AsReference != null) return $"Location Reference: {AsReference}"; 42 | return $"Location Constant: {AsValue}"; 43 | } 44 | 45 | public static implicit operator DwarfLocation(DwarfExpression value) 46 | { 47 | return new DwarfLocation(value); 48 | } 49 | 50 | public static implicit operator DwarfLocation(DwarfLocationList value) 51 | { 52 | return new DwarfLocation(value); 53 | } 54 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfOperationKindEx.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public readonly partial struct DwarfOperationKindEx : IEquatable 10 | { 11 | public DwarfOperationKindEx(byte value) 12 | { 13 | Value = (DwarfOperationKind)value; 14 | } 15 | 16 | public DwarfOperationKindEx(DwarfOperationKind value) 17 | { 18 | Value = value; 19 | } 20 | 21 | public readonly DwarfOperationKind Value; 22 | 23 | public override string ToString() 24 | { 25 | return ToStringInternal() ?? $"Unknown {nameof(DwarfOperationKindEx)} ({(uint)Value:x2})"; 26 | } 27 | 28 | public bool Equals(DwarfOperationKindEx other) 29 | { 30 | return Value == other.Value; 31 | } 32 | 33 | public override bool Equals(object? obj) 34 | { 35 | return obj is DwarfOperationKindEx other && Equals(other); 36 | } 37 | 38 | public override int GetHashCode() 39 | { 40 | return Value.GetHashCode(); 41 | } 42 | 43 | public static bool operator ==(DwarfOperationKindEx left, DwarfOperationKindEx right) 44 | { 45 | return left.Equals(right); 46 | } 47 | 48 | public static bool operator !=(DwarfOperationKindEx left, DwarfOperationKindEx right) 49 | { 50 | return !left.Equals(right); 51 | } 52 | 53 | public static explicit operator uint(DwarfOperationKindEx kind) => (uint)kind.Value; 54 | 55 | public static implicit operator DwarfOperationKindEx(DwarfOperationKind kind) => new DwarfOperationKindEx(kind); 56 | 57 | public static implicit operator DwarfOperationKind(DwarfOperationKindEx kind) => kind.Value; 58 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfReaderContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public class DwarfReaderContext : DwarfReaderWriterContext 10 | { 11 | public DwarfReaderContext() 12 | { 13 | } 14 | 15 | public DwarfReaderContext(DwarfElfContext elfContext) 16 | { 17 | if (elfContext == null) throw new ArgumentNullException(nameof(elfContext)); 18 | IsLittleEndian = elfContext.IsLittleEndian; 19 | AddressSize = elfContext.AddressSize; 20 | DebugLineStream = elfContext.LineTable?.Stream; 21 | DebugStringStream = elfContext.StringTable?.Stream; 22 | DebugAbbrevStream = elfContext.AbbreviationTable?.Stream; 23 | DebugInfoStream = elfContext.InfoSection?.Stream; 24 | DebugAddressRangeStream = elfContext.AddressRangeTable?.Stream; 25 | DebugLocationStream = elfContext.LocationSection?.Stream; 26 | } 27 | 28 | public bool IsInputReadOnly { get; set; } 29 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfReaderWriterContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public abstract class DwarfReaderWriterContext 10 | { 11 | public bool IsLittleEndian { get; set; } 12 | 13 | public DwarfAddressSize AddressSize { get; set; } 14 | 15 | public Stream? DebugAbbrevStream { get; set; } 16 | 17 | public Stream? DebugStringStream { get; set; } 18 | 19 | public Stream? DebugAddressRangeStream { get; set; } 20 | 21 | public Stream? DebugLineStream { get; set; } 22 | 23 | public TextWriter? DebugLinePrinter { get; set; } 24 | 25 | public Stream? DebugInfoStream { get; set; } 26 | 27 | public Stream? DebugLocationStream { get; set; } 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfRelocation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | [DebuggerDisplay("{" + nameof(ToString) + "(),nq}")] 10 | public struct DwarfRelocation 11 | { 12 | public DwarfRelocation(ulong offset, DwarfRelocationTarget target, DwarfAddressSize size, ulong addend) 13 | { 14 | Offset = offset; 15 | Target = target; 16 | Size = size; 17 | Addend = addend; 18 | } 19 | 20 | public ulong Offset { get; set; } 21 | 22 | public DwarfRelocationTarget Target { get; set; } 23 | 24 | public DwarfAddressSize Size { get; set; } 25 | 26 | public ulong Addend { get; set; } 27 | 28 | public override string ToString() 29 | { 30 | return $"{nameof(Offset)}: {Offset}, {nameof(Target)}: {Target}, {nameof(Size)}: {Size}, {nameof(Addend)}: {Addend}"; 31 | } 32 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfRelocationTarget.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfRelocationTarget 8 | { 9 | Code, 10 | 11 | DebugString, 12 | 13 | DebugAbbrev, 14 | 15 | DebugInfo, 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfSection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | 8 | namespace LibObjectFile.Dwarf; 9 | 10 | public abstract class DwarfSection : DwarfContainer 11 | { 12 | protected override void ValidateParent(ObjectElement parent) 13 | { 14 | if (!(parent is DwarfFile)) 15 | { 16 | throw new ArgumentException($"Parent must inherit from type {nameof(DwarfFile)}"); 17 | } 18 | } 19 | 20 | /// 21 | /// Gets the containing . Might be null if this section or segment 22 | /// does not belong to an existing . 23 | /// 24 | [DebuggerBrowsable(DebuggerBrowsableState.Never)] 25 | public new DwarfFile? Parent 26 | { 27 | get => (DwarfFile?)base.Parent; 28 | internal set => base.Parent = value; 29 | } 30 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfSectionLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public struct DwarfSectionLink : IEquatable 10 | { 11 | public DwarfSectionLink(ulong offset) 12 | { 13 | Offset = offset; 14 | } 15 | 16 | public readonly ulong Offset; 17 | 18 | public override string ToString() 19 | { 20 | return $"SectionLink {nameof(Offset)}: 0x{Offset:x}"; 21 | } 22 | 23 | public bool Equals(DwarfSectionLink other) 24 | { 25 | return Offset == other.Offset; 26 | } 27 | 28 | public override bool Equals(object? obj) 29 | { 30 | return obj is DwarfSectionLink other && Equals(other); 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | return Offset.GetHashCode(); 36 | } 37 | 38 | public static bool operator ==(DwarfSectionLink left, DwarfSectionLink right) 39 | { 40 | return left.Equals(right); 41 | } 42 | 43 | public static bool operator !=(DwarfSectionLink left, DwarfSectionLink right) 44 | { 45 | return !left.Equals(right); 46 | } 47 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfTagEx.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | /// 10 | /// Defines the tag of an . 11 | /// 12 | public readonly partial struct DwarfTagEx : IEquatable 13 | { 14 | public DwarfTagEx(uint value) 15 | { 16 | Value = (DwarfTag)value; 17 | } 18 | 19 | public DwarfTagEx(DwarfTag value) 20 | { 21 | Value = value; 22 | } 23 | 24 | public readonly DwarfTag Value; 25 | 26 | public bool Equals(DwarfTagEx other) 27 | { 28 | return Value == other.Value; 29 | } 30 | 31 | public override bool Equals(object? obj) 32 | { 33 | return obj is DwarfTagEx other && Equals(other); 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return (int) Value; 39 | } 40 | 41 | public static bool operator ==(DwarfTagEx left, DwarfTagEx right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(DwarfTagEx left, DwarfTagEx right) 47 | { 48 | return !left.Equals(right); 49 | } 50 | 51 | public override string ToString() 52 | { 53 | return ToStringInternal() ?? $"Unknown {nameof(DwarfTagEx)} (0x{Value:X4})"; 54 | } 55 | 56 | public static explicit operator uint(DwarfTagEx tag) => (uint)tag.Value; 57 | 58 | public static implicit operator DwarfTagEx(DwarfTag tag) => new DwarfTagEx(tag); 59 | 60 | public static implicit operator DwarfTag(DwarfTagEx tag) => tag.Value; 61 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfUnitKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public readonly partial struct DwarfUnitKindEx : IEquatable 10 | { 11 | public DwarfUnitKindEx(byte value) 12 | { 13 | Value = (DwarfUnitKind)value; 14 | } 15 | 16 | public DwarfUnitKindEx(DwarfUnitKind value) 17 | { 18 | Value = value; 19 | } 20 | 21 | public readonly DwarfUnitKind Value; 22 | 23 | public override string ToString() 24 | { 25 | if ((byte)Value >= DwarfNative.DW_UT_lo_user) 26 | { 27 | return $"User {nameof(DwarfUnitKindEx)} (0x{Value:x2})"; 28 | } 29 | return ToStringInternal() ?? $"Unknown {nameof(DwarfUnitKindEx)} (0x{Value:x2})"; 30 | } 31 | 32 | public bool Equals(DwarfUnitKindEx other) 33 | { 34 | return Value == other.Value; 35 | } 36 | 37 | public override bool Equals(object? obj) 38 | { 39 | return obj is DwarfUnitKindEx other && Equals(other); 40 | } 41 | 42 | public override int GetHashCode() 43 | { 44 | return Value.GetHashCode(); 45 | } 46 | 47 | public static bool operator ==(DwarfUnitKindEx left, DwarfUnitKindEx right) 48 | { 49 | return left.Equals(right); 50 | } 51 | 52 | public static bool operator !=(DwarfUnitKindEx left, DwarfUnitKindEx right) 53 | { 54 | return !left.Equals(right); 55 | } 56 | 57 | public static explicit operator uint(DwarfUnitKindEx kind) => (uint)kind.Value; 58 | 59 | public static implicit operator DwarfUnitKindEx(DwarfUnitKind kind) => new DwarfUnitKindEx(kind); 60 | 61 | public static implicit operator DwarfUnitKind(DwarfUnitKindEx kind) => kind.Value; 62 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfVirtuality.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfVirtuality : byte 8 | { 9 | None = DwarfNative.DW_VIRTUALITY_none, 10 | 11 | Virtual = DwarfNative.DW_VIRTUALITY_virtual, 12 | 13 | PureVirtual = DwarfNative.DW_VIRTUALITY_pure_virtual, 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfVisibility.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Dwarf; 6 | 7 | public enum DwarfVisibility : byte 8 | { 9 | Local = DwarfNative.DW_VIS_local, 10 | 11 | Exported = DwarfNative.DW_VIS_exported, 12 | 13 | Qualified = DwarfNative.DW_VIS_qualified, 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfWriter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using LibObjectFile.Diagnostics; 7 | 8 | namespace LibObjectFile.Dwarf; 9 | 10 | public sealed class DwarfWriter : DwarfReaderWriter 11 | { 12 | internal DwarfWriter(DwarfFile file, bool isLittleEndian, DiagnosticBag diagnostics) : base(file, diagnostics) 13 | { 14 | IsLittleEndian = isLittleEndian; 15 | } 16 | 17 | public override bool KeepOriginalStreamForSubStreams => false; 18 | 19 | public bool EnableRelocation { get; internal set; } 20 | 21 | public void RecordRelocation(DwarfRelocationTarget target, DwarfAddressSize addressSize, ulong address) 22 | { 23 | if (CurrentSection is DwarfRelocatableSection relocSection) 24 | { 25 | 26 | relocSection.Relocations.Add(new DwarfRelocation(Position, target, addressSize, address)); 27 | 28 | } 29 | else 30 | { 31 | throw new InvalidOperationException($"Invalid {nameof(CurrentSection)} in {nameof(DwarfWriter)}. It must be a {nameof(DwarfRelocatableSection)}."); 32 | } 33 | } 34 | 35 | public void WriteAddress(DwarfRelocationTarget target, ulong address) 36 | { 37 | if (EnableRelocation) 38 | { 39 | RecordRelocation(target, AddressSize, address); 40 | // If the relocation is recorded, we write 0 as an address 41 | address = 0; 42 | } 43 | WriteUInt(address); 44 | } 45 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Dwarf/DwarfWriterContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Dwarf; 8 | 9 | public class DwarfWriterContext : DwarfReaderWriterContext 10 | { 11 | public DwarfWriterContext() : this(new DwarfLayoutConfig()) 12 | { 13 | } 14 | 15 | public DwarfWriterContext(DwarfLayoutConfig layoutConfig) 16 | { 17 | LayoutConfig = layoutConfig ?? throw new ArgumentNullException(nameof(layoutConfig)); 18 | EnableRelocation = true; 19 | } 20 | 21 | public DwarfLayoutConfig LayoutConfig { get; } 22 | 23 | public bool EnableRelocation { get; set; } 24 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfArch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines a machine architecture. 11 | /// This is the value seen in or 12 | /// as well as the various machine defines (e.g ). 13 | /// 14 | public readonly partial struct ElfArchEx : IEquatable 15 | { 16 | public ElfArchEx(ushort value) 17 | { 18 | Value = (ElfArch)value; 19 | } 20 | 21 | public ElfArchEx(ElfArch value) 22 | { 23 | Value = value; 24 | } 25 | 26 | /// 27 | /// Raw value. 28 | /// 29 | public readonly ElfArch Value; 30 | 31 | public override string ToString() 32 | { 33 | return ToStringInternal() ?? $"Unknown {nameof(ElfArchEx)} (0x{Value:X4})"; 34 | } 35 | 36 | public bool Equals(ElfArchEx other) 37 | { 38 | return Value == other.Value; 39 | } 40 | 41 | public override bool Equals(object? obj) 42 | { 43 | return obj is ElfArchEx other && Equals(other); 44 | } 45 | 46 | public override int GetHashCode() 47 | { 48 | return Value.GetHashCode(); 49 | } 50 | 51 | public static bool operator ==(ElfArchEx left, ElfArchEx right) 52 | { 53 | return left.Equals(right); 54 | } 55 | 56 | public static bool operator !=(ElfArchEx left, ElfArchEx right) 57 | { 58 | return !left.Equals(right); 59 | } 60 | 61 | public static explicit operator uint(ElfArchEx arch) => (uint)arch.Value; 62 | 63 | public static implicit operator ElfArchEx(ElfArch arch) => new ElfArchEx(arch); 64 | 65 | public static implicit operator ElfArch(ElfArchEx arch) => arch.Value; 66 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfContentData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// A shadow section is a section that will not be saved to the section header table but can contain data 9 | /// that will be saved with the . 10 | /// A shadow section is usually associated with an that is referencing a portion of 11 | /// data that is not owned by a visible section. 12 | /// 13 | public abstract class ElfContentData : ElfContent 14 | { 15 | protected ElfContentData() 16 | { 17 | } 18 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfEncoding.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Encoding of an . 9 | /// This is the value seen in the ident part of an Elf header at index 10 | /// It is associated with , and 11 | /// 12 | public enum ElfEncoding : byte 13 | { 14 | /// 15 | /// Invalid data encoding. Equivalent of 16 | /// 17 | None = ElfNative.ELFDATANONE, 18 | 19 | /// 20 | /// 2's complement, little endian. Equivalent of 21 | /// 22 | Lsb = ElfNative.ELFDATA2LSB, 23 | 24 | /// 25 | /// 2's complement, big endian. Equivalent of 26 | /// 27 | Msb = ElfNative.ELFDATA2MSB, 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfFile.Write.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Runtime.InteropServices; 9 | using LibObjectFile.Diagnostics; 10 | 11 | namespace LibObjectFile.Elf; 12 | 13 | partial class ElfFile 14 | { 15 | public override void Write(ElfWriter writer) 16 | { 17 | writer.Position = 0; 18 | var contentList = Content.UnsafeList; 19 | 20 | // We write the content all sections including shadows 21 | for (var i = 0; i < contentList.Count; i++) 22 | { 23 | var content = contentList[i]; 24 | if (content is ElfSection section && section.Type == ElfSectionType.NoBits) 25 | { 26 | continue; 27 | } 28 | 29 | if (content.Position > writer.Position) 30 | { 31 | writer.WriteZero((int)(content.Position - writer.Position)); 32 | } 33 | content.Write(writer); 34 | } 35 | 36 | // Write trailing zeros 37 | if (writer.Position < Layout.TotalSize) 38 | { 39 | writer.WriteZero((int)(Layout.TotalSize - writer.Position)); 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfFileClass.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines the File class byte index (32bit or 64bits) of an . 9 | /// This is the value seen in the ident part of an Elf header at index 10 | /// It is associated with , and 11 | /// 12 | public enum ElfFileClass : byte 13 | { 14 | /// 15 | /// Invalid class. Equivalent of . 16 | /// 17 | None = ElfNative.ELFCLASSNONE, 18 | 19 | /// 20 | /// 32-bit objects. Equivalent of . 21 | /// 22 | Is32 = ElfNative.ELFCLASS32, 23 | 24 | /// 25 | /// 64-bit objects. Equivalent of . 26 | /// 27 | Is64 = ElfNative.ELFCLASS64, 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfFileLayout.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Contains the layout of an object available after reading an 9 | /// or after calling 10 | /// 11 | public sealed class ElfFileLayout 12 | { 13 | internal ElfFileLayout() 14 | { 15 | } 16 | 17 | /// 18 | /// Size of ELF Header. 19 | /// 20 | public ushort SizeOfElfHeader { get; internal set; } 21 | 22 | /// 23 | /// Offset of the program header table. 24 | /// 25 | public ulong OffsetOfProgramHeaderTable { get; internal set; } 26 | 27 | /// 28 | /// Size of a program header entry. 29 | /// 30 | public ushort SizeOfProgramHeaderEntry { get; internal set; } 31 | 32 | /// 33 | /// The number of header entries. 34 | /// 35 | public uint ProgramHeaderCount { get; internal set; } 36 | 37 | /// 38 | /// Offset of the section header table. 39 | /// 40 | public ulong OffsetOfSectionHeaderTable { get; internal set; } 41 | 42 | /// 43 | /// Size of a section header entry. 44 | /// 45 | public ushort SizeOfSectionHeaderEntry { get; internal set; } 46 | 47 | /// 48 | /// The number of section header entries. 49 | /// 50 | public uint SectionHeaderCount { get; internal set; } 51 | 52 | /// 53 | /// Size of the entire file 54 | /// 55 | public ulong TotalSize { get; internal set; } 56 | 57 | /// 58 | /// The index of the section string table. 59 | /// 60 | public uint SectionStringTableIndex { get; internal set; } 61 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfFileType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines the file type of an . 9 | /// This is the value seen in or 10 | /// as well as the various machine defines (e.g ). 11 | /// 12 | public enum ElfFileType : ushort 13 | { 14 | /// 15 | /// No file type 16 | /// 17 | None = ElfNative.ET_NONE, 18 | 19 | /// 20 | /// Relocatable file 21 | /// 22 | Relocatable = ElfNative.ET_REL, 23 | 24 | /// 25 | /// Executable file 26 | /// 27 | Executable = ElfNative.ET_EXEC, 28 | 29 | /// 30 | /// Shared object file 31 | /// 32 | Dynamic = ElfNative.ET_DYN, 33 | 34 | /// 35 | /// Core file 36 | /// 37 | Core = ElfNative.ET_CORE, 38 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfHeaderFlags.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines the flags of an . 11 | /// This is the value seen in or . 12 | /// This is currently not used. 13 | /// 14 | public readonly struct ElfHeaderFlags : IEquatable 15 | { 16 | public ElfHeaderFlags(uint value) 17 | { 18 | Value = value; 19 | } 20 | 21 | public readonly uint Value; 22 | 23 | 24 | public bool Equals(ElfHeaderFlags other) 25 | { 26 | return Value == other.Value; 27 | } 28 | 29 | public override bool Equals(object? obj) 30 | { 31 | return obj is ElfHeaderFlags other && Equals(other); 32 | } 33 | 34 | public override int GetHashCode() 35 | { 36 | return (int) Value; 37 | } 38 | 39 | public static bool operator ==(ElfHeaderFlags left, ElfHeaderFlags right) 40 | { 41 | return left.Equals(right); 42 | } 43 | 44 | public static bool operator !=(ElfHeaderFlags left, ElfHeaderFlags right) 45 | { 46 | return !left.Equals(right); 47 | } 48 | 49 | public override string ToString() 50 | { 51 | return $"0x{Value:x}"; 52 | } 53 | 54 | public static explicit operator uint(ElfHeaderFlags flags) => flags.Value; 55 | 56 | public static implicit operator ElfHeaderFlags(uint flags) => new ElfHeaderFlags(flags); 57 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfOSABIEx.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines an OS ABI. 11 | /// This is the value seen in the ident part of an Elf header at index 12 | /// as well as the various machine defines (e.g ). 13 | /// 14 | public readonly partial struct ElfOSABIEx : IEquatable 15 | { 16 | public ElfOSABIEx(byte value) 17 | { 18 | Value = (ElfOSABI)value; 19 | } 20 | 21 | public ElfOSABIEx(ElfOSABI value) 22 | { 23 | Value = value; 24 | } 25 | 26 | public readonly ElfOSABI Value; 27 | 28 | public override string ToString() 29 | { 30 | return ToStringInternal() ?? $"Unknown {nameof(ElfOSABIEx)} (0x{Value:X4})"; 31 | } 32 | 33 | public bool Equals(ElfOSABIEx other) 34 | { 35 | return Value == other.Value; 36 | } 37 | 38 | public override bool Equals(object? obj) 39 | { 40 | return obj is ElfOSABIEx other && Equals(other); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return Value.GetHashCode(); 46 | } 47 | 48 | public static bool operator ==(ElfOSABIEx left, ElfOSABIEx right) 49 | { 50 | return left.Equals(right); 51 | } 52 | 53 | public static bool operator !=(ElfOSABIEx left, ElfOSABIEx right) 54 | { 55 | return !left.Equals(right); 56 | } 57 | 58 | public static explicit operator byte(ElfOSABIEx osABI) => (byte)osABI.Value; 59 | 60 | public static implicit operator ElfOSABIEx(ElfOSABI osABI) => new ElfOSABIEx(osABI); 61 | 62 | public static implicit operator ElfOSABI(ElfOSABIEx osABI) => osABI.Value; 63 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfOffsetCalculationMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines the way a value is calculated. 9 | /// 10 | public enum ElfOffsetCalculationMode 11 | { 12 | /// 13 | /// The associated value is automatically calculated by the system. 14 | /// 15 | Auto, 16 | 17 | /// 18 | /// The associated value is set manually. 19 | /// 20 | Manual, 21 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfReaderDirect.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Internal implementation of with a . 11 | /// 12 | internal sealed class ElfReaderDirect : ElfReader 13 | { 14 | public ElfReaderDirect(ElfFile elfFile, Stream stream, ElfReaderOptions options) : base(elfFile, stream, options) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfReaderSwap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Internal implementation of with a . 11 | /// 12 | internal sealed class ElfReaderSwap : ElfReader 13 | { 14 | public ElfReaderSwap(ElfFile elfFile, Stream stream, ElfReaderOptions options) : base(elfFile, stream, options) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfSectionFlags.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines the flag of a section. 11 | /// 12 | [Flags] 13 | public enum ElfSectionFlags : uint 14 | { 15 | None = 0, 16 | 17 | /// 18 | /// Writable 19 | /// 20 | Write = ElfNative.SHF_WRITE, 21 | 22 | /// 23 | /// Occupies memory during execution 24 | /// 25 | Alloc = ElfNative.SHF_ALLOC, 26 | 27 | /// 28 | /// Executable 29 | /// 30 | Executable = ElfNative.SHF_EXECINSTR, 31 | 32 | /// 33 | /// Might be merged 34 | /// 35 | Merge = ElfNative.SHF_MERGE, 36 | 37 | /// 38 | /// Contains nul-terminated strings 39 | /// 40 | Strings = ElfNative.SHF_STRINGS, 41 | 42 | /// 43 | /// `sh_info' contains SHT index 44 | /// 45 | InfoLink = ElfNative.SHF_INFO_LINK, 46 | 47 | /// 48 | /// Preserve order after combining 49 | /// 50 | LinkOrder = ElfNative.SHF_LINK_ORDER, 51 | 52 | /// 53 | /// Non-standard OS specific handling required 54 | /// 55 | OsNonConforming = ElfNative.SHF_OS_NONCONFORMING, 56 | 57 | /// 58 | /// Section is member of a group. 59 | /// 60 | Group = ElfNative.SHF_GROUP, 61 | 62 | /// 63 | /// Section hold thread-local data. 64 | /// 65 | Tls = ElfNative.SHF_TLS, 66 | 67 | /// 68 | /// Section with compressed data. 69 | /// 70 | Compressed = ElfNative.SHF_COMPRESSED, 71 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfSegmentFlags.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines a segment flags 11 | /// 12 | public readonly struct ElfSegmentFlags : IEquatable 13 | { 14 | public ElfSegmentFlags(uint value) 15 | { 16 | Value = value; 17 | } 18 | 19 | public ElfSegmentFlags(ElfSegmentFlagsCore value) 20 | { 21 | Value = (uint)value; 22 | } 23 | 24 | public readonly uint Value; 25 | 26 | public bool Equals(ElfSegmentFlags other) 27 | { 28 | return Value == other.Value; 29 | } 30 | 31 | public override bool Equals(object? obj) 32 | { 33 | return obj is ElfSegmentFlags other && Equals(other); 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return (int) Value; 39 | } 40 | 41 | public static bool operator ==(ElfSegmentFlags left, ElfSegmentFlags right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(ElfSegmentFlags left, ElfSegmentFlags right) 47 | { 48 | return !left.Equals(right); 49 | } 50 | 51 | public override string ToString() 52 | { 53 | return $"SegmentFlags {((ElfSegmentFlagsCore)(Value&3))} 0x{Value:X8}"; 54 | } 55 | 56 | public static implicit operator ElfSegmentFlags(ElfSegmentFlagsCore segmentFlagsCore) 57 | { 58 | return new ElfSegmentFlags(segmentFlagsCore); 59 | } 60 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfSegmentFlagsCore.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines the core part of 11 | /// 12 | [Flags] 13 | public enum ElfSegmentFlagsCore : uint 14 | { 15 | /// 16 | /// Segment flags is undefined 17 | /// 18 | None = 0, 19 | 20 | /// 21 | /// Segment is executable 22 | /// 23 | Executable = ElfNative.PF_X, 24 | 25 | /// 26 | /// Segment is writable 27 | /// 28 | Writable = ElfNative.PF_W, 29 | 30 | /// 31 | /// Segment is readable 32 | /// 33 | Readable = ElfNative.PF_R, 34 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfSegmentType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Defines a segment type 11 | /// 12 | public readonly struct ElfSegmentType : IEquatable 13 | { 14 | public ElfSegmentType(uint value) 15 | { 16 | Value = value; 17 | } 18 | 19 | public ElfSegmentType(ElfSegmentTypeCore value) 20 | { 21 | Value = (uint)value; 22 | } 23 | 24 | public readonly uint Value; 25 | 26 | public bool Equals(ElfSegmentType other) 27 | { 28 | return Value == other.Value; 29 | } 30 | 31 | public override bool Equals(object? obj) 32 | { 33 | return obj is ElfSegmentType other && Equals(other); 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return (int) Value; 39 | } 40 | 41 | public static bool operator ==(ElfSegmentType left, ElfSegmentType right) 42 | { 43 | return left.Equals(right); 44 | } 45 | 46 | public static bool operator !=(ElfSegmentType left, ElfSegmentType right) 47 | { 48 | return !left.Equals(right); 49 | } 50 | 51 | public override string ToString() 52 | { 53 | return Value < ElfNative.PT_NUM ? $"SegmentType {((ElfSegmentTypeCore) Value)}" : $"SegmentType 0x{Value:X8}"; 54 | } 55 | 56 | public static implicit operator ElfSegmentType(ElfSegmentTypeCore segmentTypeCore) 57 | { 58 | return new ElfSegmentType(segmentTypeCore); 59 | } 60 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfSegmentTypeCore.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines a core 9 | /// 10 | public enum ElfSegmentTypeCore : uint 11 | { 12 | /// 13 | /// Program header table entry unused 14 | /// 15 | Null = ElfNative.PT_NULL, 16 | 17 | /// 18 | /// Loadable program segment 19 | /// 20 | Load = ElfNative.PT_LOAD, 21 | 22 | /// 23 | /// Dynamic linking information 24 | /// 25 | Dynamic = ElfNative.PT_DYNAMIC, 26 | 27 | /// 28 | /// Program interpreter 29 | /// 30 | Interpreter = ElfNative.PT_INTERP, 31 | 32 | /// 33 | /// Auxiliary information 34 | /// 35 | Note = ElfNative.PT_NOTE, 36 | 37 | /// 38 | /// Reserved 39 | /// 40 | SectionHeaderLib = ElfNative.PT_SHLIB, 41 | 42 | /// 43 | /// Entry for header table itself 44 | /// 45 | ProgramHeader = ElfNative.PT_PHDR, 46 | 47 | /// 48 | /// Thread-local storage segment 49 | /// 50 | Tls = ElfNative.PT_TLS, 51 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfStreamContentData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | 8 | namespace LibObjectFile.Elf; 9 | 10 | /// 11 | /// Equivalent of but used for shadow. 12 | /// 13 | public sealed class ElfStreamContentData : ElfContentData 14 | { 15 | private Stream _stream; 16 | 17 | public ElfStreamContentData() : this(new MemoryStream()) 18 | { 19 | } 20 | 21 | public ElfStreamContentData(Stream stream) 22 | { 23 | _stream = stream; 24 | Size = (ulong)stream.Length; 25 | } 26 | 27 | internal ElfStreamContentData(bool unused) 28 | { 29 | _stream = Stream.Null; 30 | } 31 | 32 | public Stream Stream 33 | { 34 | get => _stream; 35 | set 36 | { 37 | ArgumentNullException.ThrowIfNull(value); 38 | _stream = value; 39 | Size = (ulong)value.Length; 40 | } 41 | } 42 | 43 | public override void Read(ElfReader reader) 44 | { 45 | reader.Position = Position; 46 | Stream = reader.ReadAsStream(Size); 47 | } 48 | 49 | public override void Write(ElfWriter writer) 50 | { 51 | writer.Write(Stream); 52 | } 53 | 54 | protected override void UpdateLayoutCore(ElfVisitorContext context) 55 | { 56 | Size = (ulong)Stream.Length; 57 | } 58 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfString.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | 8 | namespace LibObjectFile.Elf; 9 | 10 | /// 11 | /// Defines a string with the associated index in the string table. 12 | /// 13 | [DebuggerDisplay("{ToString(),nq}")] 14 | public readonly record struct ElfString 15 | { 16 | [Obsolete("This constructor cannot be used. Create an ElfString from a ElfStringTable", error: true)] 17 | public ElfString() 18 | { 19 | Value = string.Empty; 20 | } 21 | public ElfString(string text) 22 | { 23 | Value = text; 24 | Index = 0; 25 | } 26 | 27 | internal ElfString(string text, uint index) 28 | { 29 | Value = text; 30 | Index = index; 31 | } 32 | 33 | internal ElfString(uint index) 34 | { 35 | Value = string.Empty; 36 | Index = index; 37 | } 38 | 39 | public bool IsEmpty => string.IsNullOrEmpty(Value) && Index == 0; 40 | 41 | /// 42 | /// Gets the text of the string. 43 | /// 44 | public string Value { get; } 45 | 46 | /// 47 | /// Gets the index of the string in the string table. 48 | /// 49 | public uint Index { get; } 50 | 51 | public override string ToString() => string.IsNullOrEmpty(Value) ? $"0x{Index:x8}" : Value; 52 | 53 | public static implicit operator ElfString(string text) => new(text); 54 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfVisitorContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | using System.Xml.Linq; 7 | 8 | namespace LibObjectFile.Elf; 9 | 10 | public class ElfVisitorContext : VisitorContextBase 11 | { 12 | internal ElfVisitorContext(ElfFile elfFile, DiagnosticBag diagnostics) : base(elfFile, diagnostics) 13 | { 14 | } 15 | 16 | public ElfString ResolveName(ElfString name) 17 | { 18 | var stringTable = File.SectionHeaderStringTable; 19 | if (stringTable is null) 20 | { 21 | Diagnostics.Error(DiagnosticId.ELF_ERR_SectionHeaderStringTableNotFound, $"The section header string table is not found. Cannot resolve {name}."); 22 | return name; 23 | } 24 | 25 | return stringTable.Resolve(name); 26 | } 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfWriterDirect.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Internal implementation of with a . 11 | /// 12 | internal sealed class ElfWriterDirect : ElfWriter 13 | { 14 | public ElfWriterDirect(ElfFile elfFile, Stream stream) : base(elfFile, stream) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/ElfWriterSwap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Internal implementation of with a . 11 | /// 12 | internal sealed class ElfWriterSwap : ElfWriter 13 | { 14 | public ElfWriterSwap(ElfFile elfFile, Stream stream) : base(elfFile, stream) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/IElfDecoder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// A decoder interface for the various Elf types that provides decoding of data based on LSB/MSB. 9 | /// 10 | /// 11 | public interface IElfDecoder 12 | { 13 | ushort Decode(ElfNative.Elf32_Half src); 14 | 15 | ushort Decode(ElfNative.Elf64_Half src); 16 | 17 | uint Decode(ElfNative.Elf32_Word src); 18 | 19 | uint Decode(ElfNative.Elf64_Word src); 20 | 21 | int Decode(ElfNative.Elf32_Sword src); 22 | 23 | int Decode(ElfNative.Elf64_Sword src); 24 | 25 | ulong Decode(ElfNative.Elf32_Xword src); 26 | 27 | long Decode(ElfNative.Elf32_Sxword src); 28 | 29 | ulong Decode(ElfNative.Elf64_Xword src); 30 | 31 | long Decode(ElfNative.Elf64_Sxword src); 32 | 33 | uint Decode(ElfNative.Elf32_Addr src); 34 | 35 | ulong Decode(ElfNative.Elf64_Addr src); 36 | 37 | uint Decode(ElfNative.Elf32_Off src); 38 | 39 | ulong Decode(ElfNative.Elf64_Off src); 40 | 41 | ushort Decode(ElfNative.Elf32_Section src); 42 | 43 | ushort Decode(ElfNative.Elf64_Section src); 44 | 45 | ushort Decode(ElfNative.Elf32_Versym src); 46 | 47 | ushort Decode(ElfNative.Elf64_Versym src); 48 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/IElfEncoder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// An encoder interface for the various Elf types that provides encoding of data based on LSB/MSB. 9 | /// 10 | /// 11 | public interface IElfEncoder 12 | { 13 | void Encode(out ElfNative.Elf32_Half dest, ushort value); 14 | 15 | void Encode(out ElfNative.Elf64_Half dest, ushort value); 16 | 17 | void Encode(out ElfNative.Elf32_Word dest, uint value); 18 | 19 | void Encode(out ElfNative.Elf64_Word dest, uint value); 20 | 21 | void Encode(out ElfNative.Elf32_Sword dest, int value); 22 | 23 | void Encode(out ElfNative.Elf64_Sword dest, int value); 24 | 25 | void Encode(out ElfNative.Elf32_Xword dest, ulong value); 26 | 27 | void Encode(out ElfNative.Elf32_Sxword dest, long value); 28 | 29 | void Encode(out ElfNative.Elf64_Xword dest, ulong value); 30 | 31 | void Encode(out ElfNative.Elf64_Sxword dest, long value); 32 | 33 | void Encode(out ElfNative.Elf32_Addr dest, uint value); 34 | 35 | void Encode(out ElfNative.Elf64_Addr dest, ulong value); 36 | 37 | void Encode(out ElfNative.Elf32_Off dest, uint offset); 38 | 39 | void Encode(out ElfNative.Elf64_Off dest, ulong offset); 40 | 41 | void Encode(out ElfNative.Elf32_Section dest, ushort index); 42 | 43 | void Encode(out ElfNative.Elf64_Section dest, ushort index); 44 | 45 | void Encode(out ElfNative.Elf32_Versym dest, ushort value); 46 | 47 | void Encode(out ElfNative.Elf64_Versym dest, ushort value); 48 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfGnuNote.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | public abstract class ElfGnuNote : ElfNote 8 | { 9 | public override string GetName() 10 | { 11 | return "GNU"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfGnuNoteBuildId.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Buffers; 6 | using System.IO; 7 | using System.Text; 8 | 9 | namespace LibObjectFile.Elf; 10 | 11 | public class ElfGnuNoteBuildId : ElfGnuNote 12 | { 13 | public override ElfNoteTypeEx GetNoteType() => new ElfNoteTypeEx(ElfNoteType.GNU_BUILD_ID); 14 | 15 | public Stream? BuildId { get; set; } 16 | 17 | public override uint GetDescriptorSize() => BuildId != null ? (uint)BuildId.Length : 0; 18 | 19 | public override string GetDescriptorAsText() 20 | { 21 | var builder = new StringBuilder(); 22 | builder.Append("Build ID: "); 23 | 24 | if (BuildId != null) 25 | { 26 | BuildId.Position = 0; 27 | var length = (int)BuildId.Length; 28 | var buffer = ArrayPool.Shared.Rent(length); 29 | length = BuildId.Read(buffer, 0, length); 30 | BuildId.Position = 0; 31 | 32 | for (int i = 0; i < length; i++) 33 | { 34 | builder.Append($"{buffer[i]:x2}"); 35 | } 36 | } 37 | 38 | return builder.ToString(); 39 | } 40 | 41 | 42 | protected override void ReadDescriptor(ElfReader reader, uint descriptorLength) 43 | { 44 | if (descriptorLength > 0) 45 | { 46 | BuildId = reader.ReadAsStream(descriptorLength); 47 | } 48 | } 49 | 50 | protected override void WriteDescriptor(ElfWriter writer) 51 | { 52 | if (BuildId != null) 53 | { 54 | writer.Write(BuildId); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfGnuNoteOSKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Type of Operating System for a 9 | /// 10 | public enum ElfGnuNoteOSKind : uint 11 | { 12 | /// 13 | /// Linux operating system. 14 | /// 15 | Linux = ElfNative.ELF_NOTE_OS_LINUX, 16 | 17 | /// 18 | /// A Gnu operating system. 19 | /// 20 | Gnu = ElfNative.ELF_NOTE_OS_GNU, 21 | 22 | /// 23 | /// Solaris operating system. 24 | /// 25 | Solaris = ElfNative.ELF_NOTE_OS_SOLARIS2, 26 | 27 | /// 28 | /// FreeBSD operating system. 29 | /// 30 | FreeBSD = ElfNative.ELF_NOTE_OS_FREEBSD, 31 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfNoBitsSection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | public sealed class ElfNoBitsSection : ElfSection 8 | { 9 | public ElfNoBitsSection() : base(ElfSectionType.NoBits) 10 | { 11 | } 12 | 13 | public ulong PositionOffsetFromPreviousContent { get; set; } 14 | 15 | public override void Read(ElfReader reader) 16 | { 17 | } 18 | 19 | public override void Write(ElfWriter writer) 20 | { 21 | } 22 | 23 | protected override void UpdateLayoutCore(ElfVisitorContext context) 24 | { 25 | } 26 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfNote.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// A Note entry in 9 | /// 10 | public abstract class ElfNote 11 | { 12 | protected ElfNote() 13 | { 14 | } 15 | 16 | /// 17 | /// Gets or sets the name of this note. 18 | /// 19 | public abstract string GetName(); 20 | 21 | /// 22 | /// Gets or sets the type of this note. 23 | /// 24 | public abstract ElfNoteTypeEx GetNoteType(); 25 | 26 | public abstract uint GetDescriptorSize(); 27 | 28 | public abstract string GetDescriptorAsText(); 29 | 30 | public override string ToString() 31 | { 32 | return $"{nameof(ElfNote)} {GetName()}, Type: {GetNoteType()}"; 33 | } 34 | 35 | internal void ReadDescriptorInternal(ElfReader reader, uint descriptorLength) 36 | { 37 | ReadDescriptor(reader, descriptorLength); 38 | } 39 | 40 | internal void WriteDescriptorInternal(ElfWriter writer) 41 | { 42 | WriteDescriptor(writer); 43 | } 44 | protected abstract void ReadDescriptor(ElfReader reader, uint descriptorLength); 45 | 46 | protected abstract void WriteDescriptor(ElfWriter writer); 47 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfNoteType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// Gets the type of a . 11 | /// 12 | public readonly partial struct ElfNoteTypeEx : IEquatable 13 | { 14 | public ElfNoteTypeEx(uint value) 15 | { 16 | Value = (ElfNoteType)value; 17 | } 18 | 19 | public ElfNoteTypeEx(ElfNoteType value) 20 | { 21 | Value = value; 22 | } 23 | 24 | /// 25 | /// The value of this note type. 26 | /// 27 | public readonly ElfNoteType Value; 28 | 29 | public override string ToString() 30 | { 31 | return ToStringInternal() ?? $"Unknown {nameof(ElfNoteTypeEx)} (0x{(uint)Value:X4})"; 32 | } 33 | 34 | public bool Equals(ElfNoteTypeEx other) 35 | { 36 | return Value == other.Value; 37 | } 38 | 39 | public override bool Equals(object? obj) 40 | { 41 | return obj is ElfNoteTypeEx other && Equals(other); 42 | } 43 | 44 | public override int GetHashCode() 45 | { 46 | return (int)Value; 47 | } 48 | 49 | public static bool operator ==(ElfNoteTypeEx left, ElfNoteTypeEx right) 50 | { 51 | return left.Equals(right); 52 | } 53 | 54 | public static bool operator !=(ElfNoteTypeEx left, ElfNoteTypeEx right) 55 | { 56 | return !left.Equals(right); 57 | } 58 | 59 | public static explicit operator byte(ElfNoteTypeEx noteType) => (byte)noteType.Value; 60 | 61 | public static implicit operator ElfNoteTypeEx(ElfNoteType noteType) => new ElfNoteTypeEx(noteType); 62 | 63 | public static implicit operator ElfNoteType(ElfNoteTypeEx noteType) => noteType.Value; 64 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfNullSection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | 7 | namespace LibObjectFile.Elf; 8 | 9 | /// 10 | /// A null section with the type . 11 | /// 12 | public sealed class ElfNullSection() : ElfSection(ElfSectionType.Null) 13 | { 14 | public override void Verify(ElfVisitorContext context) 15 | { 16 | if (Type != ElfSectionType.Null || 17 | Flags != ElfSectionFlags.None || 18 | !Name.IsEmpty || 19 | VirtualAddress != 0 || 20 | VirtualAddressAlignment != 0 || 21 | !Link.IsEmpty || 22 | !Info.IsEmpty || 23 | Position != 0 || 24 | Size != 0) 25 | { 26 | context.Diagnostics.Error(DiagnosticId.ELF_ERR_InvalidNullSection, "Invalid Null section. This section should not be modified and all properties must be null"); 27 | } 28 | } 29 | 30 | protected override void UpdateLayoutCore(ElfVisitorContext context) 31 | { 32 | } 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfRelocation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// A relocation entry in the 9 | /// This is the value seen in or 10 | /// 11 | public record struct ElfRelocation 12 | { 13 | public ElfRelocation() 14 | { 15 | } 16 | 17 | public ElfRelocation(ulong offset, ElfRelocationType type, uint symbolIndex, long addend) 18 | { 19 | Offset = offset; 20 | Type = type; 21 | SymbolIndex = symbolIndex; 22 | Addend = addend; 23 | } 24 | 25 | /// 26 | /// Gets or sets the offset. 27 | /// 28 | public ulong Offset { get; set; } 29 | 30 | /// 31 | /// Gets or sets the type of relocation. 32 | /// 33 | public ElfRelocationType Type { get; set; } 34 | 35 | /// 36 | /// Gets or sets the symbol index associated with the symbol table. 37 | /// 38 | public uint SymbolIndex { get; set; } 39 | 40 | /// 41 | /// Gets or sets the addend value. 42 | /// 43 | public long Addend { get; set; } 44 | 45 | /// 46 | /// Gets the computed Info value as expected by 47 | /// 48 | public uint Info32 => 49 | ((uint) SymbolIndex << 8) | ((Type.Value & 0xFF)); 50 | 51 | /// 52 | /// Gets the computed Info value as expected by 53 | /// 54 | public ulong Info64 => 55 | ((ulong)SymbolIndex << 32) | (Type.Value); 56 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfRelocationContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Context used when applying relocation via . 9 | /// 10 | public struct ElfRelocationContext 11 | { 12 | public ulong BaseAddress { get; set; } 13 | 14 | public ulong GlobalObjectTableAddress { get; set; } 15 | 16 | public ulong GlobalObjectTableOffset { get; set; } 17 | 18 | public ulong ProcedureLinkageTableAddress { get; set; } 19 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfSectionHeaderStringTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// The Section Header String Table used by . 9 | /// 10 | public sealed class ElfSectionHeaderStringTable : ElfStringTable 11 | { 12 | public new const string DefaultName = ".shstrtab"; 13 | 14 | public ElfSectionHeaderStringTable() : base(DefaultName) 15 | { 16 | } 17 | 18 | internal ElfSectionHeaderStringTable(bool unused) : base(unused) 19 | { 20 | } 21 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfSymbolBind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines a symbol binding 9 | /// This is the value seen compressed in or 10 | /// as well as the various defines (e.g ). 11 | /// 12 | public enum ElfSymbolBind : byte 13 | { 14 | /// 15 | /// Local symbol 16 | /// 17 | Local = ElfNative.STB_LOCAL, 18 | 19 | /// 20 | /// Global symbol 21 | /// 22 | Global = ElfNative.STB_GLOBAL, 23 | 24 | /// 25 | /// Weak symbol 26 | /// 27 | Weak = ElfNative.STB_WEAK, 28 | 29 | /// 30 | /// Unique symbol 31 | /// 32 | GnuUnique = ElfNative.STB_GNU_UNIQUE, 33 | 34 | /// 35 | /// OS-specific 0 36 | /// 37 | SpecificOS0 = ElfNative.STB_GNU_UNIQUE, 38 | 39 | /// 40 | /// OS-specific 1 41 | /// 42 | SpecificOS1 = ElfNative.STB_GNU_UNIQUE + 1, 43 | 44 | /// 45 | /// OS-specific 2 46 | /// 47 | SpecificOS2 = ElfNative.STB_GNU_UNIQUE + 2, 48 | 49 | /// 50 | /// Processor-specific 0 51 | /// 52 | SpecificProcessor0 = ElfNative.STB_LOPROC, 53 | 54 | /// 55 | /// Processor-specific 1 56 | /// 57 | SpecificProcessor1 = ElfNative.STB_LOPROC + 1, 58 | 59 | /// 60 | /// Processor-specific 2 61 | /// 62 | SpecificProcessor2 = ElfNative.STB_LOPROC + 2, 63 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Elf/Sections/ElfSymbolVisibility.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.Elf; 6 | 7 | /// 8 | /// Defines the visibility of a symbol 9 | /// This is the value seen compressed in or 10 | /// as well as the various defines (e.g ). 11 | /// 12 | public enum ElfSymbolVisibility : byte 13 | { 14 | /// 15 | /// Default symbol visibility rules 16 | /// 17 | Default = ElfNative.STV_DEFAULT, 18 | 19 | /// 20 | /// Processor specific hidden class 21 | /// 22 | Internal = ElfNative.STV_INTERNAL, 23 | 24 | /// 25 | /// Sym unavailable in other modules 26 | /// 27 | Hidden = ElfNative.STV_HIDDEN, 28 | 29 | /// 30 | /// Not preemptible, not exported 31 | /// 32 | Protected = ElfNative.STV_PROTECTED, 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/LibObjectFile.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True -------------------------------------------------------------------------------- /src/LibObjectFile/ObjectFileElementHolder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile; 8 | 9 | /// 10 | /// Helper struct to hold an element of type and ensure that it is properly set with its parent. 11 | /// 12 | /// The type of the object to hold 13 | public struct ObjectFileElementHolder 14 | where TObject : ObjectFileElement 15 | { 16 | private TObject _element; 17 | 18 | public ObjectFileElementHolder(ObjectFileElement parent, TObject element) 19 | { 20 | ArgumentNullException.ThrowIfNull(parent); 21 | ArgumentNullException.ThrowIfNull(element); 22 | _element = null!; // Avoid warning 23 | Set(parent, element); 24 | } 25 | 26 | public TObject Element => _element; 27 | 28 | public static implicit operator TObject(ObjectFileElementHolder holder) => holder._element; 29 | 30 | public void Set(ObjectFileElement parent, TObject? element) 31 | { 32 | ArgumentNullException.ThrowIfNull(parent); 33 | if (element?.Parent != null) throw new InvalidOperationException($"Cannot set the {element.GetType()} as it already belongs to another {element.Parent.GetType()} instance"); 34 | 35 | if (_element is not null) 36 | { 37 | _element.Parent = null; 38 | } 39 | 40 | _element = element!; 41 | 42 | if (element != null) 43 | { 44 | element.Parent = parent; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/LibObjectFile/ObjectFileException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using LibObjectFile.Diagnostics; 7 | 8 | namespace LibObjectFile; 9 | 10 | /// 11 | /// An exception used when diagnostics error are happening during read/write. 12 | /// 13 | public sealed class ObjectFileException : Exception 14 | { 15 | public ObjectFileException(string message, DiagnosticBag diagnostics) : base(message) 16 | { 17 | 18 | Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); 19 | } 20 | 21 | public override string Message => base.Message + Environment.NewLine + Diagnostics; 22 | 23 | /// 24 | /// The associated diagnostics messages. 25 | /// 26 | public DiagnosticBag Diagnostics { get; } 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEArchitectureDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// Represents the Architecture directory. 11 | /// 12 | public sealed class PEArchitectureDirectory : PEDataDirectory 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public PEArchitectureDirectory() : base(PEDataDirectoryKind.Architecture) 18 | { 19 | } 20 | 21 | protected override uint ComputeHeaderSize(PELayoutContext context) 22 | { 23 | return 0; 24 | } 25 | 26 | public override void Read(PEImageReader reader) 27 | { 28 | // TBD 29 | } 30 | 31 | public override void Write(PEImageWriter writer) 32 | { 33 | } 34 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBaseRelocation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace LibObjectFile.PE; 10 | 11 | /// 12 | /// A base relocation in a Portable Executable (PE) image. 13 | /// 14 | [DebuggerDisplay("{ToString(),nq}")] 15 | public readonly struct PEBaseRelocation 16 | { 17 | public const ushort MaxVirtualOffset = (1 << 12) - 1; 18 | private const ushort TypeMask = unchecked((ushort)~MaxVirtualOffset); 19 | private const ushort VirtualOffsetMask = MaxVirtualOffset; 20 | 21 | private readonly ushort _value; 22 | 23 | public PEBaseRelocation(ushort value) 24 | { 25 | _value = value; 26 | } 27 | 28 | public PEBaseRelocation(PEBaseRelocationType type, ushort offsetInBlock) 29 | { 30 | _value = (ushort)((ushort)type | (offsetInBlock & VirtualOffsetMask)); 31 | } 32 | 33 | /// 34 | /// Gets a value indicating whether the base relocation is zero (used for padding). 35 | /// 36 | public bool IsZero => _value == 0; 37 | 38 | /// 39 | /// Gets the type of the base relocation. 40 | /// 41 | public PEBaseRelocationType Type => (PEBaseRelocationType)(_value & TypeMask); 42 | 43 | /// 44 | /// Gets the virtual offset of the base relocation relative to the offset of the associated . 45 | /// 46 | public ushort OffsetInPage => (ushort)(_value & VirtualOffsetMask); 47 | 48 | public override string ToString() => Type == PEBaseRelocationType.Absolute ? $"{Type} Zero Padding" : $"{Type} OffsetInBlock = 0x{OffsetInPage:X}"; 49 | } 50 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBlobDataLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | [DebuggerDisplay("{ToString(),nq}")] 10 | public readonly record struct PEBlobDataLink(PEObjectBase? Container, RVO RVO, uint Size) : IPELink 11 | { 12 | public override string ToString() => $"{this.ToDisplayText()}, Size = 0x{Size:X}"; 13 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBoundImportAddressTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public abstract class PEBoundImportAddressTable : PEThunkAddressTable 8 | { 9 | private protected PEBoundImportAddressTable(bool is32Bits) : base(is32Bits) 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBoundImportAddressTable32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Runtime.InteropServices; 8 | using LibObjectFile.Utils; 9 | 10 | namespace LibObjectFile.PE; 11 | 12 | public sealed class PEBoundImportAddressTable32() : PEBoundImportAddressTable(true) 13 | { 14 | public List Entries { get; } = new(); 15 | 16 | public override void Read(PEImageReader reader) => Read32(reader, Entries); 17 | 18 | public override void Write(PEImageWriter writer) => Write32(writer, Entries); 19 | 20 | public override int Count => Entries.Count; 21 | 22 | internal override void SetCount(int count) => CollectionsMarshal.SetCount(Entries, count); 23 | 24 | public override int ReadAt(uint offset, Span destination) 25 | { 26 | var buffer = MemoryMarshal.AsBytes(CollectionsMarshal.AsSpan(Entries)); 27 | return DataUtils.ReadAt(buffer, offset, destination); 28 | } 29 | 30 | public override void WriteAt(uint offset, ReadOnlySpan source) 31 | { 32 | var buffer = MemoryMarshal.AsBytes(CollectionsMarshal.AsSpan(Entries)); 33 | DataUtils.WriteAt(buffer, offset, source); 34 | } 35 | 36 | public override unsafe bool CanReadWriteAt(uint offset, uint size) => offset + size <= (uint)Entries.Count * sizeof(VA32); 37 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBoundImportAddressTable64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Utils; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Runtime.InteropServices; 9 | 10 | namespace LibObjectFile.PE; 11 | 12 | public sealed class PEBoundImportAddressTable64() : PEBoundImportAddressTable(false) 13 | { 14 | public List Entries { get; } = new(); 15 | 16 | public override void Read(PEImageReader reader) => Read64(reader, Entries); 17 | 18 | public override void Write(PEImageWriter writer) => Write64(writer, Entries); 19 | 20 | public override int Count => Entries.Count; 21 | 22 | internal override void SetCount(int count) => CollectionsMarshal.SetCount(Entries, count); 23 | 24 | public override int ReadAt(uint offset, Span destination) 25 | { 26 | var buffer = MemoryMarshal.AsBytes(CollectionsMarshal.AsSpan(Entries)); 27 | return DataUtils.ReadAt(buffer, offset, destination); 28 | } 29 | 30 | public override void WriteAt(uint offset, ReadOnlySpan source) 31 | { 32 | var buffer = MemoryMarshal.AsBytes(CollectionsMarshal.AsSpan(Entries)); 33 | DataUtils.WriteAt(buffer, offset, source); 34 | } 35 | 36 | public override unsafe bool CanReadWriteAt(uint offset, uint size) => offset + size <= (uint)Entries.Count * sizeof(VA64); 37 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBoundImportDirectoryEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using LibObjectFile.PE.Internal; 7 | 8 | namespace LibObjectFile.PE; 9 | 10 | /// 11 | /// Represents an entry in the Bound Import Directory of a Portable Executable (PE) file. 12 | /// 13 | public sealed class PEBoundImportDirectoryEntry 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | public PEBoundImportDirectoryEntry() 19 | { 20 | ForwarderRefs = new List(); 21 | } 22 | 23 | /// 24 | /// Gets or sets the module name for this entry. 25 | /// 26 | public PEAsciiStringLink ModuleName { get; set; } 27 | 28 | /// 29 | /// Gets the list of forwarder references for this entry. 30 | /// 31 | public List ForwarderRefs { get; } 32 | 33 | /// 34 | /// Gets the size of this entry in the Bound Import Directory. 35 | /// 36 | internal unsafe uint Size => (uint)(sizeof(RawPEBoundImportDirectory) + ForwarderRefs.Count * sizeof(RawPEBoundImportForwarderRef)); 37 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEBoundImportForwarderRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a forwarder reference in the Bound Import Directory of a Portable Executable (PE) file. 9 | /// 10 | public readonly record struct PEBoundImportForwarderRef 11 | { 12 | /// 13 | /// Initializes a new instance of the struct. 14 | /// 15 | /// The module name of the forwarder reference. 16 | public PEBoundImportForwarderRef(PEAsciiStringLink moduleName) 17 | { 18 | ModuleName = moduleName; 19 | } 20 | 21 | /// 22 | /// Gets the module name of the forwarder reference. 23 | /// 24 | public PEAsciiStringLink ModuleName { get; } 25 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEClrMetadata.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// Represents the CLR metadata directory in a PE file. 11 | /// 12 | public sealed class PEClrMetadata : PEDataDirectory 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public PEClrMetadata() : base(PEDataDirectoryKind.ClrMetadata) 18 | { 19 | } 20 | 21 | /// 22 | protected override uint ComputeHeaderSize(PELayoutContext context) => 0; 23 | 24 | /// 25 | public override void Read(PEImageReader reader) 26 | { 27 | } 28 | 29 | /// 30 | public override void Write(PEImageWriter writer) 31 | { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEDataDirectoryKind.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines directory entry indices. 9 | /// 10 | public enum PEDataDirectoryKind : ushort 11 | { 12 | /// 13 | /// Export Directory 14 | /// 15 | Export = 0, 16 | /// 17 | /// Import Directory 18 | /// 19 | Import = 1, 20 | /// 21 | /// Resource Directory 22 | /// 23 | Resource = 2, 24 | /// 25 | /// Exception Directory 26 | /// 27 | Exception = 3, 28 | /// 29 | /// Security/Certificate Directory 30 | /// 31 | SecurityCertificate = 4, 32 | /// 33 | /// Base Relocation Table 34 | /// 35 | BaseRelocation = 5, 36 | /// 37 | /// Debug Directory 38 | /// 39 | Debug = 6, 40 | /// 41 | /// Architecture Specific Data 42 | /// 43 | Architecture = 7, 44 | /// 45 | /// RVA of GP 46 | /// 47 | GlobalPointer = 8, 48 | /// 49 | /// TLS Directory 50 | /// 51 | Tls = 9, 52 | /// 53 | /// Load Configuration Directory 54 | /// 55 | LoadConfig = 10, 56 | /// 57 | /// Bound Import Directory in headers 58 | /// 59 | BoundImport = 11, 60 | /// 61 | /// Import Address Table 62 | /// 63 | ImportAddressTable = 12, 64 | /// 65 | /// Delay Load Import Descriptors 66 | /// 67 | DelayImport = 13, 68 | /// 69 | /// .NET CLR Metadata 70 | /// 71 | ClrMetadata = 14, 72 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEDebugSectionData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public abstract class PEDebugSectionData : PESectionData 8 | { 9 | protected PEDebugSectionData() 10 | { 11 | } 12 | 13 | public override bool HasChildren => false; 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEDebugStreamExtraData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a debug directory entry in a Portable Executable (PE) file. 9 | /// 10 | public class PEDebugStreamExtraData : PEStreamExtraData 11 | { 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEDebugStreamSectionData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A debug stream section data in a Portable Executable (PE) image. 11 | /// 12 | public class PEDebugStreamSectionData : PEStreamSectionData 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public PEDebugStreamSectionData() 18 | { 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The stream containing the data of this section data. 25 | public PEDebugStreamSectionData(Stream stream) : base(stream) 26 | { 27 | } 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEExceptionFunctionEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents an exception function entry in a Portable Executable (PE) file. 9 | /// 10 | public abstract class PEExceptionFunctionEntry 11 | { 12 | /// 13 | /// Initializes a new instance of the class with the specified begin address. 14 | /// 15 | /// The begin address of the exception function entry. 16 | internal PEExceptionFunctionEntry(PESectionDataLink beginAddress) 17 | { 18 | BeginAddress = beginAddress; 19 | } 20 | 21 | /// 22 | /// Gets or sets the begin address of the exception function entry. 23 | /// 24 | public PESectionDataLink BeginAddress { get; set; } 25 | 26 | internal virtual void Verify(PEVerifyContext context, PEExceptionDirectory exceptionDirectory, int index) 27 | { 28 | context.VerifyObject(BeginAddress.Container, exceptionDirectory, $"the {nameof(BeginAddress)} of the {nameof(PEExceptionFunctionEntry)} at #{index}", false); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEExceptionFunctionEntryArm.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents an ARM exception function entry in a Portable Executable (PE) file. 9 | /// 10 | public sealed class PEExceptionFunctionEntryARM : PEExceptionFunctionEntry 11 | { 12 | /// 13 | /// Initializes a new instance of the class with the specified begin address and unwind data. 14 | /// 15 | /// The begin address of the exception function entry. 16 | /// The unwind data. 17 | public PEExceptionFunctionEntryARM(PESectionDataLink beginAddress, uint unwindData) : base(beginAddress) 18 | { 19 | UnwindData = unwindData; 20 | } 21 | 22 | /// 23 | /// Gets or sets the unwind data. 24 | /// 25 | public uint UnwindData { get; set; } 26 | 27 | /// 28 | public override string ToString() 29 | { 30 | return $"{nameof(BeginAddress)} = {BeginAddress.RVA()}, {nameof(UnwindData)} = 0x{UnwindData:X}"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEExportFunctionEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | #pragma warning disable CS0649 8 | public readonly struct PEExportFunctionEntry 9 | { 10 | private readonly PEObject? _container; 11 | private readonly uint _offset; 12 | private readonly bool _isForwarderRVA; 13 | 14 | public PEExportFunctionEntry(PEFunctionAddressLink exportRVA) 15 | { 16 | _container = exportRVA.Container; 17 | _offset = exportRVA.RVO; 18 | _isForwarderRVA = false; 19 | } 20 | 21 | public PEExportFunctionEntry(PEAsciiStringLink forwarderRVA) 22 | { 23 | _container = forwarderRVA.Container; 24 | _offset = forwarderRVA.RVO; 25 | _isForwarderRVA = true; 26 | } 27 | 28 | public bool IsForwarderRVA => _isForwarderRVA; 29 | 30 | public bool IsEmpty => _container is null && _offset == 0; 31 | 32 | public PEFunctionAddressLink ExportRVA => IsForwarderRVA ? default : new(_container, _offset); 33 | 34 | public PEAsciiStringLink ForwarderRVA => IsForwarderRVA ? new(_container as PEStreamSectionData, _offset) : default; 35 | 36 | public override string ToString() => IsEmpty ? "null" : ForwarderRVA.IsNull() ? $"{ExportRVA}" : $"{ExportRVA}, ForwarderRVA = {ForwarderRVA}"; 37 | 38 | 39 | internal void Verify(PEVerifyContext context, PEExportAddressTable parent, int index) 40 | { 41 | context.VerifyObject(_container, parent, $"the object pointed by the {nameof(PEExportFunctionEntry)} at #{index}", false); 42 | } 43 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEExportOrdinalTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Runtime.InteropServices; 7 | using LibObjectFile.Diagnostics; 8 | 9 | namespace LibObjectFile.PE; 10 | 11 | public sealed class PEExportOrdinalTable : PESectionData 12 | { 13 | public PEExportOrdinalTable() 14 | { 15 | } 16 | 17 | internal PEExportOrdinalTable(int count) 18 | { 19 | CollectionsMarshal.SetCount(Values, count); 20 | } 21 | 22 | public override bool HasChildren => false; 23 | 24 | public List Values { get; } = new(); 25 | 26 | 27 | protected override void UpdateLayoutCore(PELayoutContext context) 28 | { 29 | Size = (ulong)Values.Count * sizeof(ushort); 30 | } 31 | 32 | // Special method that can read from a known size 33 | public override void Read(PEImageReader reader) 34 | { 35 | reader.Position = Position; 36 | var span = CollectionsMarshal.AsSpan(Values); 37 | 38 | int read = reader.Read(MemoryMarshal.AsBytes(span)); 39 | if (read != Values.Count * sizeof(ushort)) 40 | { 41 | reader.Diagnostics.Error(DiagnosticId.CMN_ERR_UnexpectedEndOfFile, $"Unable to read Export Ordinal Table"); 42 | return; 43 | } 44 | } 45 | 46 | public override void Write(PEImageWriter writer) 47 | { 48 | var span = CollectionsMarshal.AsSpan(Values); 49 | writer.Write(MemoryMarshal.AsBytes(span)); 50 | } 51 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEGlobalPointerDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// Represents the GlobalPointer directory. 11 | /// 12 | public sealed class PEGlobalPointerDirectory : PEDataDirectory 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public PEGlobalPointerDirectory() : base(PEDataDirectoryKind.GlobalPointer) 18 | { 19 | } 20 | 21 | protected override uint ComputeHeaderSize(PELayoutContext context) 22 | { 23 | return 0; 24 | } 25 | 26 | public override void Read(PEImageReader reader) 27 | { 28 | } 29 | 30 | public override void Write(PEImageWriter writer) 31 | { 32 | } 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportAddressTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public abstract class PEImportAddressTable : PEImportFunctionTable 8 | { 9 | private protected PEImportAddressTable(bool is32Bit) : base(is32Bit) 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportAddressTable32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public sealed class PEImportAddressTable32() : PEImportAddressTable(true); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportAddressTable64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public sealed class PEImportAddressTable64() : PEImportAddressTable(false); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportAddressTableDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Runtime.InteropServices; 8 | using LibObjectFile.Collections; 9 | 10 | namespace LibObjectFile.PE; 11 | 12 | public sealed class PEImportAddressTableDirectory : PEDataDirectory 13 | { 14 | public PEImportAddressTableDirectory() : base(PEDataDirectoryKind.ImportAddressTable) 15 | { 16 | } 17 | 18 | public override void Read(PEImageReader reader) 19 | { 20 | } 21 | 22 | public override void Write(PEImageWriter writer) 23 | { 24 | } 25 | 26 | protected override uint ComputeHeaderSize(PELayoutContext context) => 0; 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportLookupTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public abstract class PEImportLookupTable : PEImportFunctionTable 8 | { 9 | private protected PEImportLookupTable(bool is32Bit) : base(is32Bit) 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportLookupTable32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public sealed class PEImportLookupTable32() : PEImportLookupTable(true); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEImportLookupTable64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public sealed class PEImportLookupTable64() : PEImportLookupTable(false); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PELoadConfigCodeIntegrity.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// A structure representing the Code Integrity information in the Load Configuration Directory. 9 | /// 10 | public struct PELoadConfigCodeIntegrity 11 | { 12 | public ushort Flags; // Flags to indicate if CI information is available, etc. 13 | public ushort Catalog; // 0xFFFF means not available 14 | public uint CatalogOffset; 15 | public uint Reserved; // Additional bitmask to be defined later 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PELoadConfigDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | using System; 7 | using System.Runtime.InteropServices; 8 | using LibObjectFile.Utils; 9 | 10 | namespace LibObjectFile.PE; 11 | 12 | /// 13 | /// Represents the Load Configuration Directory for a PE file. 14 | /// 15 | public abstract class PELoadConfigDirectory : PERawDataDirectory 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | private protected PELoadConfigDirectory(int minSize) : base(PEDataDirectoryKind.LoadConfig, minSize) 21 | { 22 | } 23 | 24 | /// 25 | /// Change the recorded size of the Load Configuration Directory. 26 | /// 27 | /// 28 | public void SetConfigSize(uint size) 29 | { 30 | SetRawDataSize(size); 31 | 32 | // Write back the configuration size 33 | MemoryMarshal.Write(RawData, size); 34 | } 35 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEResourceData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A section data that contains a resource data. 11 | /// 12 | public sealed class PEResourceData : PEStreamSectionData 13 | { 14 | public PEResourceData() 15 | { 16 | RequiredPositionAlignment = 4; 17 | RequiredSizeAlignment = 4; 18 | } 19 | 20 | /// 21 | protected override void ValidateParent(ObjectElement parent) 22 | { 23 | if (parent is not PEResourceDirectory) 24 | { 25 | throw new ArgumentException($"Invalid parent type {parent.GetType().FullName}. Expecting a parent of type {typeof(PEResourceDirectory).FullName}"); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEResourceDirectoryEntryById.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a resource directory entry with an ID in a PE file. 9 | /// 10 | /// The identifier of the resource directory entry. 11 | /// The resource entry associated with the identifier. 12 | public readonly record struct PEResourceDirectoryEntryById(PEResourceId Id, PEResourceEntry Entry); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEResourceDirectoryEntryByName.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a resource directory entry with a name in a PE file. 9 | /// 10 | /// The name of the resource directory entry. 11 | /// The resource entry associated with the name. 12 | public readonly record struct PEResourceDirectoryEntryByName(PEResourceString Name, PEResourceEntry Entry); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PESectionVirtualSizeMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines the way the virtual size of a section is computed. 9 | /// 10 | public enum PESectionVirtualSizeMode 11 | { 12 | /// 13 | /// The virtual size of the section is automatically computed by the raw size of its content without file alignment. 14 | /// 15 | Auto = 0, 16 | 17 | /// 18 | /// The virtual size of the section is fixed. 19 | /// 20 | /// 21 | /// This is usually the case when the virtual size is requested to be bigger than the raw size (e.g. uninitialized data). 22 | /// 23 | Fixed = 1, 24 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PESecurityCertificateRevision.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines the revision of the security certificate. 9 | /// 10 | public enum PESecurityCertificateRevision : ushort 11 | { 12 | /// 13 | /// Version 1, legacy version of the Win_Certificate structure. It is supported only for purposes of verifying legacy Authenticode signatures 14 | /// 15 | Revision1 = 0x0100, 16 | 17 | /// 18 | /// Version 2 is the current version of the Win_Certificate structure. 19 | /// 20 | Revision2 = 0x0200, 21 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PESecurityCertificateType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines the type of the security certificate. 9 | /// 10 | public enum PESecurityCertificateType : ushort 11 | { 12 | /// 13 | /// X.509 Certificate. Not Supported 14 | /// 15 | X509 = 0x0001, 16 | 17 | /// 18 | /// PKCS#7 SignedData structure. 19 | /// 20 | PKCS7 = 0x0002, 21 | 22 | /// 23 | /// Reserved. Not supported. 24 | /// 25 | Reserved = 0x0003, 26 | 27 | /// 28 | /// Terminal Server Protocol Stack Certificate signing. Not Supported 29 | /// 30 | TerminalServerProtocolStack = 0x0004, 31 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PETlsCharacteristics.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | [Flags] 10 | public enum PETlsCharacteristics : uint 11 | { 12 | Align1Bytes = 1048576, // 0x00100000 13 | Align2Bytes = 2097152, // 0x00200000 14 | Align4Bytes = Align2Bytes | Align1Bytes, // 0x00300000 15 | Align8Bytes = 4194304, // 0x00400000 16 | Align16Bytes = Align8Bytes | Align1Bytes, // 0x00500000 17 | Align32Bytes = Align8Bytes | Align2Bytes, // 0x00600000 18 | Align64Bytes = Align32Bytes | Align1Bytes, // 0x00700000 19 | Align128Bytes = 8388608, // 0x00800000 20 | Align256Bytes = Align128Bytes | Align1Bytes, // 0x00900000 21 | Align512Bytes = Align128Bytes | Align2Bytes, // 0x00A00000 22 | Align1024Bytes = Align512Bytes | Align1Bytes, // 0x00B00000 23 | Align2048Bytes = Align128Bytes | Align8Bytes, // 0x00C00000 24 | Align4096Bytes = Align2048Bytes | Align1Bytes, // 0x00D00000 25 | Align8192Bytes = Align2048Bytes | Align2Bytes, // 0x00E00000 26 | AlignMask = Align8192Bytes | Align1Bytes, // 0x00F00000 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PETlsDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | namespace LibObjectFile.PE; 5 | 6 | /// 7 | /// Represents the Thread Local Storage (TLS) directory in a PE file. 8 | /// 9 | public abstract class PETlsDirectory : PERawDataDirectory 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | private protected PETlsDirectory(int minSize) : base(PEDataDirectoryKind.Tls, minSize) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/DataDirectory/PEUnknownDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents an unknown directory (when going beyond the known directories). 9 | /// 10 | public sealed class PEUnknownDirectory : PEDataDirectory 11 | { 12 | internal PEUnknownDirectory(int index) : base((PEDataDirectoryKind)index) 13 | { 14 | } 15 | 16 | protected override uint ComputeHeaderSize(PELayoutContext context) => 0; 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/IPELink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | // ReSharper disable once InconsistentNaming 8 | 9 | 10 | public interface IPELink; 11 | 12 | public interface IPELink : IPELink where TObject: PEObjectBase 13 | { 14 | public TObject? Container { get; } 15 | 16 | public RVO RVO { get; } 17 | } 18 | 19 | 20 | public interface IPELink : IPELink where TObject : PEObjectBase 21 | { 22 | public TData Resolve(); 23 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawDelayLoadDescriptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | /// 9 | /// Represents a delay load descriptor in a Portable Executable (PE) image. 10 | /// 11 | internal struct RawDelayLoadDescriptor 12 | { 13 | /// 14 | /// The attributes that must be zero. 15 | /// 16 | public uint Attributes; 17 | 18 | /// 19 | /// The RVA of the name of the DLL to delay load. 20 | /// 21 | public RVA NameRVA; 22 | 23 | /// 24 | /// The RVA to the HMODULE caching location (PHMODULE) 25 | /// 26 | public RVA ModuleHandleRVA; 27 | 28 | /// 29 | /// The RVA of the delay load import address table, which contains the RVAs of the delay load import name table and the delay load import module. 30 | /// 31 | public RVA DelayLoadImportAddressTableRVA; 32 | 33 | /// 34 | /// The RVA of the delay load import name table, which contains the names of the delay load imports. 35 | /// 36 | public RVA DelayLoadImportNameTableRVA; 37 | 38 | /// 39 | /// The RVA of the bound delay load import address table. This table contains the actual addresses to use for the delay load imports. 40 | /// 41 | public RVA BoundDelayLoadImportAddressTableRVA; 42 | 43 | /// 44 | /// The RVA of the unload delay load import address table. 45 | /// 46 | public RVA UnloadDelayLoadImportAddressTableRVA; 47 | 48 | /// 49 | /// The time/date stamp of the delay load import table. 50 | /// 51 | public uint TimeDateStamp; 52 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawExceptionFunctionEntryARM.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawExceptionFunctionEntryARM 10 | { 11 | public RVA BeginAddress; 12 | public uint UnwindData; 13 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawExceptionFunctionEntryX86.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawExceptionFunctionEntryX86 10 | { 11 | public RVA BeginAddress; 12 | public RVA EndAddress; 13 | public RVA UnwindInfoAddress; 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageDataDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | /// 11 | /// Data directory entry in the optional header of a Portable Executable (PE) file. 12 | /// 13 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 14 | internal struct RawImageDataDirectory 15 | { 16 | /// 17 | /// The relative virtual address of the data directory. 18 | /// 19 | public RVA RVA; 20 | 21 | /// 22 | /// The size of the data directory, in bytes. 23 | /// 24 | public uint Size; 25 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageDataDirectoryArray.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Runtime.CompilerServices; 7 | 8 | namespace LibObjectFile.PE.Internal; 9 | 10 | #pragma warning disable CS0649 11 | 12 | /// 13 | /// An array of entries. 14 | /// 15 | [InlineArray(16)] 16 | internal struct RawImageDataDirectoryArray 17 | { 18 | private RawImageDataDirectory _e; 19 | 20 | /// 21 | /// Gets or sets the at the specified index. 22 | /// 23 | /// The index of the to get or set. 24 | /// The at the specified index. 25 | [UnscopedRef] 26 | public ref RawImageDataDirectory this[PEDataDirectoryKind kind] => ref this[(int)kind]; 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageDebugDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawImageDebugDirectory 10 | { 11 | public uint Characteristics; 12 | public uint TimeDateStamp; 13 | public ushort MajorVersion; 14 | public ushort MinorVersion; 15 | public PEDebugType Type; 16 | public uint SizeOfData; 17 | public RVA AddressOfRawData; 18 | public uint PointerToRawData; 19 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeader32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 12 | internal struct RawImageOptionalHeader32 13 | { 14 | public RawImageOptionalHeaderCommonPart1 Common; 15 | public RawImageOptionalHeaderBase32 Base32; 16 | public RawImageOptionalHeaderCommonPart2 Common2; 17 | public RawImageOptionalHeaderSize32 Size32; 18 | public RawImageOptionalHeaderCommonPart3 Common3; 19 | 20 | // In case of a PE Header with zero directories 21 | public static unsafe int MinimumSize => sizeof(RawImageOptionalHeader32) - sizeof(RawImageDataDirectoryArray); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeader64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 12 | internal struct RawImageOptionalHeader64 13 | { 14 | public RawImageOptionalHeaderCommonPart1 Common; 15 | public RawImageOptionalHeaderBase64 Base64; 16 | public RawImageOptionalHeaderCommonPart2 Common2; 17 | public RawImageOptionalHeaderSize64 Size64; 18 | public RawImageOptionalHeaderCommonPart3 Common3; 19 | 20 | // In case of a PE Header with zero directories 21 | public static unsafe int MinimumSize => sizeof(RawImageOptionalHeader64) - sizeof(RawImageDataDirectoryArray); 22 | } 23 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderBase32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawImageOptionalHeaderBase32 10 | { 11 | /// 12 | /// The address relative to the image base of the beginning of the data section. 13 | /// 14 | public RVA BaseOfData; 15 | 16 | // 17 | // NT additional fields. 18 | // 19 | 20 | /// 21 | /// The preferred address of the first byte of the image when loaded into memory. 22 | /// 23 | public uint ImageBase; 24 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderBase64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawImageOptionalHeaderBase64 10 | { 11 | // 12 | // NT additional fields. 13 | // 14 | 15 | /// 16 | /// The preferred address of the first byte of the image when loaded into memory. 17 | /// 18 | public ulong ImageBase; 19 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderCommonPart1.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | /// 12 | /// Represents the optional header in a PE (Portable Executable) file format (32-bit). 13 | /// 14 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 15 | internal struct RawImageOptionalHeaderCommonPart1 16 | { 17 | /// 18 | /// The magic number, which identifies the file format. Expected to be 0x10b for PE32. 19 | /// 20 | public PEOptionalHeaderMagic Magic; 21 | 22 | /// 23 | /// The major version number of the linker. 24 | /// 25 | public byte MajorLinkerVersion; 26 | 27 | /// 28 | /// The minor version number of the linker. 29 | /// 30 | public byte MinorLinkerVersion; 31 | 32 | /// 33 | /// The size of the code (text) section, in bytes. 34 | /// 35 | public uint SizeOfCode; 36 | 37 | /// 38 | /// The size of the initialized data section, in bytes. 39 | /// 40 | public uint SizeOfInitializedData; 41 | 42 | /// 43 | /// The size of the uninitialized data section, in bytes. 44 | /// 45 | public uint SizeOfUninitializedData; 46 | 47 | /// 48 | /// The address of the entry point relative to the image base when the executable starts. 49 | /// 50 | public RVA AddressOfEntryPoint; 51 | 52 | /// 53 | /// The address relative to the image base of the beginning of the code section. 54 | /// 55 | public RVA BaseOfCode; 56 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderCommonPart3.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 12 | internal struct RawImageOptionalHeaderCommonPart3 13 | { 14 | /// 15 | /// Reserved; must be zero. 16 | /// 17 | public uint LoaderFlags; 18 | 19 | /// 20 | /// The number of data-directory entries in the remainder of the optional header. 21 | /// 22 | public uint NumberOfRvaAndSizes; 23 | 24 | /// 25 | /// The data directories array, which contains the location and size of special tables in the file. 26 | /// 27 | public RawImageDataDirectoryArray DataDirectory; 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderSize32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 12 | internal struct RawImageOptionalHeaderSize32 13 | { 14 | /// 15 | /// The size of the stack to reserve, in bytes. 16 | /// 17 | public uint SizeOfStackReserve; 18 | 19 | /// 20 | /// The size of the stack to commit, in bytes. 21 | /// 22 | public uint SizeOfStackCommit; 23 | 24 | /// 25 | /// The size of the local heap space to reserve, in bytes. 26 | /// 27 | public uint SizeOfHeapReserve; 28 | 29 | /// 30 | /// The size of the local heap space to commit, in bytes. 31 | /// 32 | public uint SizeOfHeapCommit; 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageOptionalHeaderSize64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace LibObjectFile.PE.Internal; 8 | 9 | #pragma warning disable CS0649 10 | 11 | [StructLayout(LayoutKind.Sequential, Pack = 4)] 12 | internal struct RawImageOptionalHeaderSize64 13 | { 14 | /// 15 | /// The size of the stack to reserve, in bytes. 16 | /// 17 | public ulong SizeOfStackReserve; 18 | 19 | /// 20 | /// The size of the stack to commit, in bytes. 21 | /// 22 | public ulong SizeOfStackCommit; 23 | 24 | /// 25 | /// The size of the local heap space to reserve, in bytes. 26 | /// 27 | public ulong SizeOfHeapReserve; 28 | 29 | /// 30 | /// The size of the local heap space to commit, in bytes. 31 | /// 32 | public ulong SizeOfHeapCommit; 33 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImageResourceDirectoryEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | internal struct RawImageResourceDirectoryEntry 9 | { 10 | public uint NameOrId; 11 | public uint OffsetToDataOrDirectoryEntry; 12 | } 13 | 14 | internal struct RawImageResourceDataEntry 15 | { 16 | public RVA OffsetToData; 17 | public uint Size; 18 | public uint CodePage; 19 | public uint Reserved; 20 | } 21 | 22 | internal struct RawImageResourceDirectory 23 | { 24 | public uint Characteristics; 25 | public uint TimeDateStamp; 26 | public ushort MajorVersion; 27 | public ushort MinorVersion; 28 | public ushort NumberOfNamedEntries; 29 | public ushort NumberOfIdEntries; 30 | // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; 31 | } 32 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImportDirectoryEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | internal struct RawImportDirectoryEntry 8 | { 9 | #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value 10 | 11 | /// 12 | /// The RVA of the import lookup table. This table contains a name or ordinal for each import. (The name "Characteristics" is used in Winnt.h, but no longer describes this field.) 13 | /// 14 | public RVA ImportLookupTableRVA; 15 | 16 | /// 17 | /// The stamp that is set to zero until the image is bound. After the image is bound, this field is set to the time/data stamp of the DLL. 18 | /// 19 | /// 0 if not bound, 20 | /// -1 if bound, and real date\time stamp in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) 21 | /// O.W. date/time stamp of DLL bound to (Old BIND) 22 | /// 23 | public uint TimeDateStamp; 24 | 25 | /// 26 | /// The index of the first forwarder reference. -1 if no forwarders 27 | /// 28 | public uint ForwarderChain; 29 | 30 | /// 31 | /// The address of an ASCII string that contains the name of the DLL. This address is relative to the image base. 32 | /// 33 | public RVA NameRVA; 34 | 35 | /// 36 | /// The RVA of the import address table. The contents of this table are identical to the contents of the import lookup table until the image is bound. 37 | /// 38 | public RVA ImportAddressTableRVA; 39 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImportFunctionEntry32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | internal readonly struct RawImportFunctionEntry32 9 | { 10 | private readonly uint _hintNameTableRVA; 11 | 12 | public RawImportFunctionEntry32(uint hintNameTableRVA) 13 | { 14 | _hintNameTableRVA = hintNameTableRVA; 15 | } 16 | 17 | public uint HintNameTableRVA => IsImportByOrdinal ? 0U : _hintNameTableRVA; 18 | 19 | public bool IsNull => _hintNameTableRVA == 0; 20 | 21 | public bool IsImportByOrdinal => (_hintNameTableRVA & 0x8000_0000U) != 0; 22 | 23 | public ushort Ordinal => IsImportByOrdinal ? (ushort)_hintNameTableRVA : (ushort)0; 24 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawImportFunctionEntry64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | internal readonly struct RawImportFunctionEntry64 9 | { 10 | private readonly ulong _hintNameTableRVA; 11 | 12 | public RawImportFunctionEntry64(ulong hintNameTableRVA) 13 | { 14 | _hintNameTableRVA = hintNameTableRVA; 15 | } 16 | 17 | public ulong HintNameTableRVA => IsImportByOrdinal ? 0U : _hintNameTableRVA; 18 | 19 | public bool IsNull => _hintNameTableRVA == 0; 20 | 21 | public ushort Ordinal => IsImportByOrdinal ? (ushort)_hintNameTableRVA : (ushort)0; 22 | 23 | public bool IsImportByOrdinal => (_hintNameTableRVA & 0x8000_0000_0000_0000UL) != 0; 24 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawPEBoundImportDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawPEBoundImportDirectory 10 | { 11 | public uint TimeDateStamp; 12 | public ushort OffsetModuleName; 13 | public ushort NumberOfModuleForwarderRefs; 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/Internal/RawPEBoundImportForwarderRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE.Internal; 6 | 7 | #pragma warning disable CS0649 8 | 9 | internal struct RawPEBoundImportForwarderRef 10 | { 11 | public uint TimeDateStamp; 12 | public ushort OffsetModuleName; 13 | public ushort Reserved; 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEAsciiStringLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A link to a null terminated ASCII string in a . 11 | /// 12 | [DebuggerDisplay("{ToString(),nq}")] 13 | public readonly record struct PEAsciiStringLink(PEStreamSectionData? Container, RVO RVO) : IPELink 14 | { 15 | /// 16 | public override string ToString() => this.ToDisplayTextWithRVA(); 17 | 18 | /// 19 | /// Resolves this link to a string. 20 | /// 21 | /// The string resolved. 22 | public string? Resolve() => Container?.ReadAsciiString(RVO); 23 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEDosMagic.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | #pragma warning disable CS0649 8 | /// 9 | /// Magic number for the > 10 | /// 11 | public enum PEDosMagic : ushort 12 | { 13 | /// 14 | /// MZ - DOS executable file signature. 15 | /// 16 | DOS = 0x5A4D, 17 | /// 18 | /// NE - OS/2 executable file signature. 19 | /// 20 | OS2 = 0x454E, 21 | /// 22 | /// LE - OS/2 LE or VXD. 23 | /// 24 | OS2OrVXD = 0x454C, 25 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEExtraData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Base class for extra data in a PE file accessible via . 9 | /// 10 | public abstract class PEExtraData : PEObjectBase 11 | { 12 | protected PEExtraData() 13 | { 14 | } 15 | 16 | public override bool HasChildren => false; 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEFile.Verify.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using LibObjectFile.Diagnostics; 7 | 8 | namespace LibObjectFile.PE; 9 | 10 | /// 11 | /// A Portable Executable file that can be read, modified and written. 12 | /// 13 | partial class PEFile 14 | { 15 | /// 16 | /// Verifies the validity of this PE file. 17 | /// 18 | /// The diagnostics to output errors. 19 | public void Verify(DiagnosticBag diagnostics) 20 | { 21 | ArgumentNullException.ThrowIfNull(diagnostics); 22 | var context = new PEVerifyContext(this, diagnostics); 23 | Verify(context); 24 | } 25 | 26 | /// 27 | public override void Verify(PEVerifyContext context) 28 | { 29 | ArgumentNullException.ThrowIfNull(context); 30 | 31 | if (!TryVerifyAlignment(context.Diagnostics)) 32 | { 33 | return; 34 | } 35 | 36 | foreach (var data in ExtraDataBeforeSections) 37 | { 38 | data.Verify(context); 39 | } 40 | 41 | foreach (var section in Sections) 42 | { 43 | section.Verify(context); 44 | } 45 | 46 | foreach (var data in ExtraDataAfterSections) 47 | { 48 | data.Verify(context); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEFunctionAddressLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | #pragma warning disable CS0649 10 | [DebuggerDisplay("{ToString(),nq}")] 11 | public readonly record struct PEFunctionAddressLink(PEObject? Container, RVO RVO) : IPELink 12 | { 13 | public override string ToString() => Container is not null ? $"{Container}, Offset = {RVO}" : $""; 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImageReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | public sealed class PEImageReader : ObjectFileReaderWriter 10 | { 11 | internal PEImageReader(PEFile file, Stream stream, PEImageReaderOptions readerOptions) : base(file, stream) 12 | { 13 | Options = readerOptions; 14 | LayoutContext = new PELayoutContext(File, Diagnostics, true); 15 | } 16 | 17 | public new PEFile File => (PEFile)base.File; 18 | 19 | public PEImageReaderOptions Options { get; } 20 | 21 | public override bool KeepOriginalStreamForSubStreams => Options.UseSubStream; 22 | 23 | public PELayoutContext LayoutContext { get; } 24 | 25 | 26 | public static implicit operator PELayoutContext(PEImageReader reader) => reader.LayoutContext; 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImageReaderOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public class PEImageReaderOptions 8 | { 9 | public bool UseSubStream { get; init; } 10 | 11 | public bool EnableStackTrace { get; init; } 12 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImageWriter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.IO; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | public sealed class PEImageWriter : ObjectFileReaderWriter 10 | { 11 | internal PEImageWriter(PEFile file, Stream stream, PEImageWriterOptions options) : base(file, stream) 12 | { 13 | Options = options; 14 | } 15 | 16 | public PEFile PEFile => (PEFile)base.File; 17 | 18 | public PEImageWriterOptions Options { get; } 19 | 20 | public override bool KeepOriginalStreamForSubStreams => false; 21 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImageWriterOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public class PEImageWriterOptions 8 | { 9 | public static readonly PEImageWriterOptions Default = new(); 10 | 11 | public bool EnableStackTrace { get; init; } 12 | 13 | public bool EnableChecksum { get; init; } 14 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImportHintName.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// A PE Import Hint Name used in . 9 | /// 10 | /// An index into the export name pointer table. A match is attempted first with this value. If it fails, a binary search is performed on the DLL's export name pointer table. 11 | /// This is the string that must be matched to the public name in the DLL 12 | public readonly record struct PEImportHintName(ushort Hint, string? Name); -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEImportHintNameLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A link to a PE Import Hint Name in a . 11 | /// 12 | [DebuggerDisplay("{ToString(),nq}")] 13 | public readonly record struct PEImportHintNameLink(PEStreamSectionData? Container, RVO RVO) : IPELink 14 | { 15 | /// 16 | public override string ToString() => this.ToDisplayTextWithRVA(); 17 | 18 | /// 19 | /// Resolves this link to a PE Import Hint Name. 20 | /// 21 | /// The PE Import Hint Name resolved. 22 | public PEImportHintName Resolve() => Container?.ReadHintName(RVO) ?? default; 23 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEModuleHandleLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A link to a module handle. 11 | /// 12 | [DebuggerDisplay("{ToString(),nq}")] 13 | public readonly record struct PEModuleHandleLink(PESection? Container, RVO RVO) : IPELink 14 | { 15 | /// 16 | public override string ToString() => this.ToDisplayTextWithRVA(); 17 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEObjectBaseExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace LibObjectFile.PE; 10 | 11 | public static class PEObjectBaseExtensions 12 | { 13 | public static unsafe T ReadAt(this PEObjectBase obj, uint offset) where T : unmanaged 14 | { 15 | T value = default; 16 | 17 | int read = obj.ReadAt(offset, MemoryMarshal.CreateSpan(ref Unsafe.As(ref value), sizeof(T))); 18 | if (read != sizeof(T)) 19 | { 20 | throw new InvalidOperationException($"Failed to read {typeof(T).Name} at offset {offset} in {obj}"); 21 | } 22 | 23 | return value; 24 | } 25 | 26 | public static unsafe void WriteAt(this PEObjectBase obj, uint offset, T value) where T : unmanaged 27 | { 28 | obj.WriteAt(offset, MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref value), sizeof(T))); 29 | } 30 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEOptionalHeaderMagic.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | public enum PEOptionalHeaderMagic : ushort 8 | { 9 | /// 10 | /// PE32 11 | /// 12 | PE32 = 0x10b, 13 | 14 | /// 15 | /// PE32+ 16 | /// 17 | PE32Plus = 0x20b, 18 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PESectionData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Utils; 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | 10 | namespace LibObjectFile.PE; 11 | 12 | /// 13 | /// Base class for data contained in a . 14 | /// 15 | public abstract class PESectionData : PEObject 16 | { 17 | protected PESectionData() 18 | { 19 | } 20 | 21 | protected override void ValidateParent(ObjectElement parent) 22 | { 23 | if (parent is not PESection && parent is not PESectionData) 24 | { 25 | throw new ArgumentException($"Invalid parent type {parent.GetType().FullName}. Expecting a parent of type {typeof(PESection).FullName} or {typeof(PESectionData).FullName}"); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PESectionDataLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A link to a section data. 11 | /// 12 | [DebuggerDisplay("{ToString(),nq}")] 13 | public readonly record struct PESectionDataLink(PESectionData? Container, RVO RVO) : IPELink 14 | { 15 | public override string ToString() => this.ToDisplayTextWithRVA(); 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PESectionLink.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace LibObjectFile.PE; 8 | 9 | /// 10 | /// A link to a section 11 | /// 12 | [DebuggerDisplay("{ToString(),nq}")] 13 | public readonly record struct PESectionLink(PESection? Container, RVO RVO) : IPELink 14 | { 15 | public override string ToString() => this.ToDisplayTextWithRVA(); 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PESignature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines the NT signature for a PE image. 9 | /// 10 | public enum PESignature : uint 11 | { 12 | /// 13 | /// PE00 14 | /// 15 | PE = 0x00004550, 16 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/PEStreamExtraData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | 8 | namespace LibObjectFile.PE; 9 | 10 | /// 11 | /// Defines a stream extra data in the PE file . 12 | /// 13 | public class PEStreamExtraData : PEExtraData 14 | { 15 | private Stream _stream; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public PEStreamExtraData() 21 | { 22 | _stream = Stream.Null; 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | /// The data stream. 29 | public PEStreamExtraData(Stream stream) 30 | { 31 | ArgumentNullException.ThrowIfNull(stream); 32 | _stream = stream; 33 | Size = (uint)stream.Length; 34 | } 35 | 36 | /// 37 | /// Gets or sets the data stream. 38 | /// 39 | public Stream Stream 40 | { 41 | get => _stream; 42 | set 43 | { 44 | ArgumentNullException.ThrowIfNull(value); 45 | _stream = value; 46 | Size = (uint)value.Length; 47 | } 48 | } 49 | 50 | protected override void UpdateLayoutCore(PELayoutContext context) 51 | { 52 | Size = (uint)Stream.Length; 53 | } 54 | 55 | public override void Read(PEImageReader reader) 56 | { 57 | reader.Position = Position; 58 | Stream = reader.ReadAsStream(Size); 59 | } 60 | 61 | public override void Write(PEImageWriter writer) 62 | { 63 | Stream.Position = 0; 64 | Stream.CopyTo(writer.Stream); 65 | } 66 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/RVA.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines a Relative Virtual Address (RVA) in a Portable Executable (PE) image. 9 | /// 10 | /// The value of the address 11 | public record struct RVA(uint Value) 12 | { 13 | /// 14 | /// Converts a to a . 15 | /// 16 | /// The value to convert. 17 | public static implicit operator uint(RVA value) => value.Value; 18 | 19 | /// 20 | /// Converts a to a . 21 | /// 22 | /// The value to convert. 23 | public static implicit operator RVA(uint value) => new(value); 24 | 25 | /// 26 | public override string ToString() => $"0x{Value:X}"; 27 | } 28 | -------------------------------------------------------------------------------- /src/LibObjectFile/PE/RVO.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Defines a Relative Virtual Offset (RVO) that is relative to a in a Portable Executable (PE) image. 9 | /// 10 | /// The value of the relative offset. 11 | public record struct RVO(uint Value) 12 | { 13 | /// 14 | /// Converts a to a . 15 | /// 16 | /// The value to convert. 17 | public static implicit operator uint(RVO value) => value.Value; 18 | 19 | /// 20 | /// Converts a to a . 21 | /// 22 | /// The value to convert. 23 | public static implicit operator RVO(uint value) => new(value); 24 | 25 | /// 26 | public override string ToString() => $"0x{Value:X}"; 27 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/VA32.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a 32-bit virtual address. 9 | /// 10 | public record struct VA32(uint Value) 11 | { 12 | /// 13 | /// Implicitly converts a to a . 14 | /// 15 | /// The value to convert. 16 | /// The converted value. 17 | public static implicit operator uint(VA32 value) => value.Value; 18 | 19 | /// 20 | /// Implicitly converts a to a . 21 | /// 22 | /// The value to convert. 23 | /// The converted value. 24 | public static implicit operator VA32(uint value) => new(value); 25 | 26 | /// 27 | /// Gets a value indicating whether the is null (value is 0). 28 | /// 29 | public bool IsNull => Value == 0; 30 | 31 | /// 32 | /// Returns a string representation of the value. 33 | /// 34 | /// A string representation of the value. 35 | public override string ToString() => $"0x{Value:X}"; 36 | } -------------------------------------------------------------------------------- /src/LibObjectFile/PE/VA64.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | namespace LibObjectFile.PE; 6 | 7 | /// 8 | /// Represents a 64-bit virtual address. 9 | /// 10 | public record struct VA64(ulong Value) 11 | { 12 | /// 13 | /// Implicitly converts a to a . 14 | /// 15 | /// The value to convert. 16 | /// The converted value. 17 | public static implicit operator ulong(VA64 value) => value.Value; 18 | 19 | /// 20 | /// Implicitly converts a to a . 21 | /// 22 | /// The value to convert. 23 | /// The converted value. 24 | public static implicit operator VA64(ulong value) => new(value); 25 | 26 | /// 27 | /// Gets a value indicating whether the is null (value is 0). 28 | /// 29 | public bool IsNull => Value == 0; 30 | 31 | /// 32 | /// Returns a string representation of the value. 33 | /// 34 | /// A string representation of the value. 35 | public override string ToString() => $"0x{Value:X}"; 36 | } -------------------------------------------------------------------------------- /src/LibObjectFile/Utils/DataUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace LibObjectFile.Utils; 8 | 9 | internal static class DataUtils 10 | { 11 | public static int ReadAt(ReadOnlySpan source, uint offset, Span destination) 12 | { 13 | ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(offset, (uint)source.Length); 14 | 15 | var lengthToCopy = Math.Min(source.Length - (int)offset, destination.Length); 16 | source.Slice((int)offset, lengthToCopy).CopyTo(destination); 17 | 18 | return lengthToCopy; 19 | } 20 | 21 | public static unsafe void WriteAt(Span destination, uint offset, ReadOnlySpan source) 22 | { 23 | ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(offset, (uint)destination.Length); 24 | 25 | if (source.Length > (destination.Length - (int)offset)) 26 | { 27 | throw new ArgumentOutOfRangeException(nameof(source), $"The source buffer is too large to fit at the offset {offset} in the destination buffer"); 28 | } 29 | 30 | source.CopyTo(destination.Slice((int)offset, source.Length)); 31 | } 32 | } -------------------------------------------------------------------------------- /src/LibObjectFile/VisitorContextBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Alexandre Mutel. All rights reserved. 2 | // This file is licensed under the BSD-Clause 2 license. 3 | // See the license.txt file in the project root for more information. 4 | 5 | using LibObjectFile.Diagnostics; 6 | using System.IO; 7 | 8 | namespace LibObjectFile; 9 | 10 | /// 11 | /// Base class used for layout-ing an object file. 12 | /// 13 | /// The root object file. 14 | /// The diagnostics. 15 | public abstract class VisitorContextBase(ObjectFileElement file, DiagnosticBag diagnostics) 16 | { 17 | public ObjectFileElement File { get; } = file; 18 | 19 | 20 | public DiagnosticBag Diagnostics { get; } = diagnostics; 21 | 22 | 23 | public bool HasErrors => Diagnostics.HasErrors; 24 | 25 | public TextWriter? DebugLog { get; set; } 26 | } 27 | 28 | /// 29 | /// Base class used for layout-ing an object file. 30 | /// 31 | /// The type of the object file. 32 | /// The root object file. 33 | /// The diagnostics. 34 | public abstract class VisitorContextBase(TFile file, DiagnosticBag diagnostics) : VisitorContextBase(file, diagnostics) 35 | where TFile : ObjectFileElement 36 | { 37 | public new TFile File => (TFile)base.File; 38 | } -------------------------------------------------------------------------------- /src/dotnet-releaser.toml: -------------------------------------------------------------------------------- 1 | # configuration file for dotnet-releaser 2 | [msbuild] 3 | project = "LibObjectFile.sln" 4 | build_debug = true 5 | [test] 6 | run_tests_for_debug = true 7 | [github] 8 | user = "xoofx" 9 | repo = "LibObjectFile" 10 | -------------------------------------------------------------------------------- /src/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.100", 4 | "rollForward": "latestMinor", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeConsole2Win64/NativeConsole2Win64.cpp: -------------------------------------------------------------------------------- 1 | // NativeConsole2Win64.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include 5 | 6 | extern "C" 7 | { 8 | __declspec(dllimport) int __cdecl HelloWorld(int a, int b); 9 | __declspec(dllexport) int __cdecl AnotherFunction(); 10 | } 11 | 12 | int main() 13 | { 14 | std::cout << "HelloWorld " << HelloWorld(1 + AnotherFunction(), 2) << std::endl; 15 | } 16 | 17 | // Run program: Ctrl + F5 or Debug > Start Without Debugging menu 18 | // Debug program: F5 or Debug > Start Debugging menu 19 | 20 | // Tips for Getting Started: 21 | // 1. Use the Solution Explorer window to add/manage files 22 | // 2. Use the Team Explorer window to connect to source control 23 | // 3. Use the Output window to see build output and other messages 24 | // 4. Use the Error List window to view errors 25 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 26 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 27 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeConsole2Win64/NativeConsole2Win64.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeConsoleWin64/NativeConsoleWin64.cpp: -------------------------------------------------------------------------------- 1 | // NativeConsoleWin64.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include 5 | 6 | int main() 7 | { 8 | std::cout << "Hello World!\n"; 9 | } 10 | 11 | // Run program: Ctrl + F5 or Debug > Start Without Debugging menu 12 | // Debug program: F5 or Debug > Start Debugging menu 13 | 14 | // Tips for Getting Started: 15 | // 1. Use the Solution Explorer window to add/manage files 16 | // 2. Use the Team Explorer window to connect to source control 17 | // 3. Use the Output window to see build output and other messages 18 | // 4. Use the Error List window to view errors 19 | // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project 20 | // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file 21 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeConsoleWin64/NativeConsoleWin64.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeLibraryWin64/NativeLibraryWin64.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeLibraryWin64/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "pch.h" 3 | 4 | BOOL APIENTRY DllMain( HMODULE hModule, 5 | DWORD ul_reason_for_call, 6 | LPVOID lpReserved 7 | ) 8 | { 9 | switch (ul_reason_for_call) 10 | { 11 | case DLL_PROCESS_ATTACH: 12 | case DLL_THREAD_ATTACH: 13 | case DLL_THREAD_DETACH: 14 | case DLL_PROCESS_DETACH: 15 | break; 16 | } 17 | return TRUE; 18 | } 19 | 20 | 21 | extern "C" 22 | { 23 | __declspec(dllexport) int __cdecl HelloWorld(int a, int b) 24 | { 25 | return a + b; 26 | } 27 | 28 | __declspec(dllexport) int __cdecl AnotherFunction() 29 | { 30 | return 123; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeLibraryWin64/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files 5 | #include 6 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeLibraryWin64/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/NativeLibraryWin64/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/RawNativeConsoleWin64/RawNativeConsoleWin64.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void mainCRTStartup(void) 4 | { 5 | ExitProcess(156); 6 | } -------------------------------------------------------------------------------- /src/native/Win64/NativeProjects/RawNativeConsoleWin64/RawNativeConsoleWin64.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/objdasm/objdasm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | LibObjectFile.Disasm 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test-with-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export TEST_TAG_NAME=libobjectfile-tests 4 | 5 | # To rebuild the image, simply delete the tag: 6 | # docker rmi $TEST_TAG_NAME 7 | 8 | if [[ "$(docker images -q ${TEST_TAG_NAME}:latest 2> /dev/null)" == "" ]]; then 9 | docker build -t ${TEST_TAG_NAME} . 10 | fi 11 | 12 | # Run unit tests in Docker - See Dockerfile 13 | docker run -v `pwd`:/src --rm -it ${TEST_TAG_NAME} 14 | 15 | --------------------------------------------------------------------------------