From 0fa6673d213c56964d427fe009dfd158b181fe1f Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 14 Mar 2022 15:27:42 -0700 Subject: [PATCH] Add debug section (nw) --- .../ExecutableType/Microsoft/Enums.cs | 77 +++++++++++++++++ .../Microsoft/PE/PortableExecutable.cs | 23 +++++ .../Microsoft/PE/Sections/DebugSection.cs | 45 ++++++++++ .../Microsoft/PE/Tables/DebugDirectory.cs | 85 +++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 BurnOutSharp/ExecutableType/Microsoft/PE/Sections/DebugSection.cs create mode 100644 BurnOutSharp/ExecutableType/Microsoft/PE/Tables/DebugDirectory.cs diff --git a/BurnOutSharp/ExecutableType/Microsoft/Enums.cs b/BurnOutSharp/ExecutableType/Microsoft/Enums.cs index 318a38f8..afa570f6 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/Enums.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/Enums.cs @@ -2,6 +2,83 @@ using System; namespace BurnOutSharp.ExecutableType.Microsoft { + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-type + public enum DebugType : uint + { + /// + /// An unknown value that is ignored by all tools. + /// + IMAGE_DEBUG_TYPE_UNKNOWN = 0, + + /// + /// The COFF debug information (line numbers, symbol table, and string table). + /// This type of debug information is also pointed to by fields in the file headers. + /// + IMAGE_DEBUG_TYPE_COFF = 1, + + /// + /// The Visual C++ debug information. + /// + IMAGE_DEBUG_TYPE_CODEVIEW = 2, + + /// + /// The frame pointer omission (FPO) information. + /// This information tells the debugger how to interpret nonstandard stack frames, + /// which use the EBP register for a purpose other than as a frame pointer. + /// + IMAGE_DEBUG_TYPE_FPO = 3, + + /// + /// The location of DBG file. + /// + IMAGE_DEBUG_TYPE_MISC = 4, + + /// + /// A copy of .pdata section. + /// + IMAGE_DEBUG_TYPE_EXCEPTION = 5, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_FIXUP = 6, + + /// + /// The mapping from an RVA in image to an RVA in source image. + /// + IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7, + + /// + /// The mapping from an RVA in source image to an RVA in image. + /// + IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8, + + /// + /// Reserved for Borland. + /// + IMAGE_DEBUG_TYPE_BORLAND = 9, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_RESERVED10 = 10, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_CLSID = 11, + + /// + /// PE determinism or reproducibility. + /// + IMAGE_DEBUG_TYPE_REPRO = 16, + + /// + /// Extended DLL characteristics bits. + /// + IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS = 20, + } + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#dll-characteristics [Flags] public enum DllCharacteristics : ushort diff --git a/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs b/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs index 7a7d97fa..9e541e04 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs @@ -71,6 +71,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE #region Tables + /// + /// The .debug section is used in object files to contain compiler-generated debug information and in image files to contain + /// all of the debug information that is generated. + /// This section describes the packaging of debug information in object and image files. + /// + public DebugSection DebugDirectory; + /// /// The export data section, named .edata, contains information about symbols that other images can access through dynamic linking. /// Exported symbols are generally found in DLLs, but DLLs can also import symbols. @@ -235,6 +242,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE #region Structured Tables + // // Debug Section + // var table = this.GetLastSection(".debug", true); + // if (table != null && table.VirtualSize > 0) + // { + // stream.Seek((int)table.PointerToRawData, SeekOrigin.Begin); + // this.DebugSection = DebugSection.Deserialize(stream, this.SectionTable); + // } + // // Export Table // var table = this.GetLastSection(".edata", true); // if (table != null && table.VirtualSize > 0) @@ -326,6 +341,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE #region Structured Tables + // // Debug Section + // var table = this.GetLastSection(".debug", true); + // if (table != null && table.VirtualSize > 0) + // { + // int tableAddress = (int)table.PointerToRawData; + // this.DebugSection = DebugSection.Deserialize(content, ref tableAddress, this.SectionTable); + // } + // // Export Table // var table = this.GetLastSection(".edata", true); // if (table != null && table.VirtualSize > 0) diff --git a/BurnOutSharp/ExecutableType/Microsoft/PE/Sections/DebugSection.cs b/BurnOutSharp/ExecutableType/Microsoft/PE/Sections/DebugSection.cs new file mode 100644 index 00000000..dcc637e7 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/PE/Sections/DebugSection.cs @@ -0,0 +1,45 @@ +using System.IO; +using BurnOutSharp.ExecutableType.Microsoft.PE.Headers; +using BurnOutSharp.ExecutableType.Microsoft.PE.Tables; + +namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections +{ + /// + /// The .debug section is used in object files to contain compiler-generated debug information and in image files to contain + /// all of the debug information that is generated. + /// This section describes the packaging of debug information in object and image files. + /// + /// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-debug-section + public class DebugSection + { + /// + /// Image files contain an optional debug directory that indicates what form of debug information is present and where it is. + /// This directory consists of an array of debug directory entries whose location and size are indicated in the image optional header. + /// + public DebugDirectory DebugDirectory; + + public static DebugSection Deserialize(Stream stream, SectionHeader[] sections) + { + long originalPosition = stream.Position; + var ds = new DebugSection(); + + ds.DebugDirectory = DebugDirectory.Deserialize(stream); + + // TODO: Read in raw debug data + + return ds; + } + + public static DebugSection Deserialize(byte[] content, ref int offset, SectionHeader[] sections) + { + int originalPosition = offset; + var ds = new DebugSection(); + + ds.DebugDirectory = DebugDirectory.Deserialize(content, ref offset); + + // TODO: Read in raw debug data + + return ds; + } + } +} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/PE/Tables/DebugDirectory.cs b/BurnOutSharp/ExecutableType/Microsoft/PE/Tables/DebugDirectory.cs new file mode 100644 index 00000000..8809202d --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/PE/Tables/DebugDirectory.cs @@ -0,0 +1,85 @@ +using System.IO; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables +{ + /// + /// Image files contain an optional debug directory that indicates what form of debug information is present and where it is. + /// This directory consists of an array of debug directory entries whose location and size are indicated in the image optional header. + /// + /// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-directory-image-only + public class DebugDirectory + { + /// + /// Reserved, must be 0. + /// + public uint Characteristics; + + /// + /// The time and date that the debug data was created. + /// + public uint TimeDateStamp; + + /// + /// The major version number of the debug data format. + /// + public ushort MajorVersion; + + /// + /// The minor version number of the debug data format. + /// + public ushort MinorVersion; + + /// + /// The format of debugging information. This field enables support of multiple debuggers. + /// + public DebugType DebugType; + + /// + /// The size of the debug data (not including the debug directory itself). + /// + public uint SizeOfData; + + /// + /// The address of the debug data when loaded, relative to the image base. + /// + public uint AddressOfRawData; + + /// + /// The file pointer to the debug data. + /// + public uint PointerToRawData; + + public static DebugDirectory Deserialize(Stream stream) + { + var dd = new DebugDirectory(); + + dd.Characteristics = stream.ReadUInt32(); + dd.TimeDateStamp = stream.ReadUInt32(); + dd.MajorVersion = stream.ReadUInt16(); + dd.MinorVersion = stream.ReadUInt16(); + dd.DebugType = (DebugType)stream.ReadUInt32(); + dd.SizeOfData = stream.ReadUInt32(); + dd.AddressOfRawData = stream.ReadUInt32(); + dd.PointerToRawData = stream.ReadUInt32(); + + return dd; + } + + public static DebugDirectory Deserialize(byte[] content, ref int offset) + { + var dd = new DebugDirectory(); + + dd.Characteristics = content.ReadUInt32(ref offset); + dd.TimeDateStamp = content.ReadUInt32(ref offset); + dd.MajorVersion = content.ReadUInt16(ref offset); + dd.MinorVersion = content.ReadUInt16(ref offset); + dd.DebugType = (DebugType)content.ReadUInt32(ref offset); + dd.SizeOfData = content.ReadUInt32(ref offset); + dd.AddressOfRawData = content.ReadUInt32(ref offset); + dd.PointerToRawData = content.ReadUInt32(ref offset); + + return dd; + } + } +} \ No newline at end of file