From 7d7ec69dc18d266a537637ca8809dc1a952d7d8d Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 5 Nov 2022 15:34:14 -0700 Subject: [PATCH] Add PE auxiliary symbol record formats --- .../COFFSymbolTableEntry.cs | 216 +++++++++++++++++- .../PortableExecutable/Executable.cs | 2 +- 2 files changed, 216 insertions(+), 2 deletions(-) diff --git a/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs b/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs index 2d8877f9..4bf76777 100644 --- a/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs +++ b/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs @@ -1,4 +1,7 @@ -using System.Runtime.InteropServices; +using System.Diagnostics; +using System; +using System.Drawing; +using System.Runtime.InteropServices; namespace BurnOutSharp.Models.PortableExecutable { @@ -21,6 +24,8 @@ namespace BurnOutSharp.Models.PortableExecutable [StructLayout(LayoutKind.Explicit)] public class COFFSymbolTableEntry { + #region Standard COFF Symbol Table Entry + /// /// An array of 8 bytes. This array is padded with nulls on the right if /// the name is less than 8 bytes long. @@ -66,5 +71,214 @@ namespace BurnOutSharp.Models.PortableExecutable /// The number of auxiliary symbol table entries that follow this record. /// [FieldOffset(17)] public byte NumberOfAuxSymbols; + + #endregion + + #region Auxiliary Symbol Records + + // Auxiliary symbol table records always follow, and apply to, some standard + // symbol table record. An auxiliary record can have any format that the tools + // can recognize, but 18 bytes must be allocated for them so that symbol table + // is maintained as an array of regular size. Currently, Microsoft tools + // recognize auxiliary formats for the following kinds of records: function + // definitions, function begin and end symbols (.bf and .ef), weak externals, + // file names, and section definitions. + // + // The traditional COFF design also includes auxiliary-record formats for arrays + // and structures.Microsoft tools do not use these, but instead place that + // symbolic information in Visual C++ debug format in the debug sections. + + #region Auxiliary Format 1: Function Definitions + + // A symbol table record marks the beginning of a function definition if it + // has all of the following: a storage class of EXTERNAL (2), a Type value + // that indicates it is a function (0x20), and a section number that is + // greater than zero. Note that a symbol table record that has a section + // number of UNDEFINED (0) does not define the function and does not have + // an auxiliary record. Function-definition symbol records are followed by + // an auxiliary record in the format described below: + + /// + /// The symbol-table index of the corresponding .bf (begin function) + /// symbol record. + /// + [FieldOffset(0)] public uint AuxFormat1TagIndex; + + /// + /// The size of the executable code for the function itself. If the function + /// is in its own section, the SizeOfRawData in the section header is greater + /// or equal to this field, depending on alignment considerations. + /// + [FieldOffset(4)] public uint AuxFormat1TotalSize; + + /// + /// The file offset of the first COFF line-number entry for the function, or + /// zero if none exists. + /// + [FieldOffset(8)] public uint AuxFormat1PointerToLinenumber; + + /// + /// The symbol-table index of the record for the next function. If the function + /// is the last in the symbol table, this field is set to zero. + /// + [FieldOffset(12)] public uint AuxFormat1PointerToNextFunction; + + /// + /// Unused + /// + [FieldOffset(16)] public ushort AuxFormat1Unused; + + #endregion + + #region Auxiliary Format 2: .bf and .ef Symbols + + // For each function definition in the symbol table, three items describe + // the beginning, ending, and number of lines. Each of these symbols has + // storage class FUNCTION (101): + // + // A symbol record named.bf(begin function). The Value field is unused. + // + // A symbol record named.lf(lines in function). The Value field gives the + // number of lines in the function. + // + // A symbol record named.ef (end of function). The Value field has the same + // number as the Total Size field in the function-definition symbol record. + // + // The.bf and.ef symbol records (but not .lf records) are followed by an + // auxiliary record with the following format: + + /// + /// Unused + /// + [FieldOffset(0)] public uint AuxFormat2Unused1; + + /// + /// The actual ordinal line number (1, 2, 3, and so on) within the source file, + /// corresponding to the .bf or .ef record. + /// + [FieldOffset(4)] public ushort AuxFormat2Linenumber; + + /// + /// Unused + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + [FieldOffset(6)] public byte[] AuxFormat2Unused2; + + /// + /// The symbol-table index of the next .bf symbol record. If the function is the + /// last in the symbol table, this field is set to zero. It is not used for + /// .ef records. + /// + [FieldOffset(12)] public uint AuxFormat2PointerToNextFunction; + + /// + /// Unused + /// + [FieldOffset(12)] public ushort AuxFormat2Unused3; + + #endregion + + #region Auxiliary Format 3: Weak Externals + + // "Weak externals" are a mechanism for object files that allows flexibility at + // link time. A module can contain an unresolved external symbol (sym1), but it + // can also include an auxiliary record that indicates that if sym1 is not + // present at link time, another external symbol (sym2) is used to resolve + // references instead. + // + // If a definition of sym1 is linked, then an external reference to the symbol + // is resolved normally. If a definition of sym1 is not linked, then all references + // to the weak external for sym1 refer to sym2 instead. The external symbol, sym2, + // must always be linked; typically, it is defined in the module that contains + // the weak reference to sym1. + // + // Weak externals are represented by a symbol table record with EXTERNAL storage + // class, UNDEF section number, and a value of zero. The weak-external symbol + // record is followed by an auxiliary record with the following format: + + /// + /// The symbol-table index of sym2, the symbol to be linked if sym1 is not found. + /// + [FieldOffset(0)] public uint AuxFormat3TagIndex; + + /// + /// A value of IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY indicates that no library search + /// for sym1 should be performed. + /// A value of IMAGE_WEAK_EXTERN_SEARCH_LIBRARY indicates that a library search for + /// sym1 should be performed. + /// A value of IMAGE_WEAK_EXTERN_SEARCH_ALIAS indicates that sym1 is an alias for sym2. + /// + [FieldOffset(4)] public uint AuxFormat3Characteristics; + + /// + /// Unused + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + [FieldOffset(8)] public byte[] AuxFormat3Unused; + + #endregion + + #region Auxiliary Format 4: Files + + // This format follows a symbol-table record with storage class FILE (103). + // The symbol name itself should be .file, and the auxiliary record that + // follows it gives the name of a source-code file. + + /// + /// An ANSI string that gives the name of the source file. This is padded + /// with nulls if it is less than the maximum length. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] + [FieldOffset(0)] public byte[] AuxFormat4FileName; + + #endregion + + #region Auxiliary Format 5: Section Definitions + + // This format follows a symbol-table record that defines a section. Such a + // record has a symbol name that is the name of a section (such as .text or + // .drectve) and has storage class STATIC (3). The auxiliary record provides + // information about the section to which it refers. Thus, it duplicates some + // of the information in the section header. + + /// + /// The size of section data; the same as SizeOfRawData in the section header. + /// + [FieldOffset(0)] public uint AuxFormat5Length; + + /// + /// The number of relocation entries for the section. + /// + [FieldOffset(4)] public ushort AuxFormat5NumberOfRelocations; + + /// + /// The number of line-number entries for the section. + /// + [FieldOffset(6)] public ushort AuxFormat5NumberOfLinenumbers; + + /// + /// The checksum for communal data. It is applicable if the IMAGE_SCN_LNK_COMDAT + /// flag is set in the section header. + /// + [FieldOffset(8)] public uint AuxFormat5CheckSum; + + /// + /// One-based index into the section table for the associated section. This is + /// used when the COMDAT selection setting is 5. + /// + [FieldOffset(12)] public ushort AuxFormat5Number; + + /// + /// The COMDAT selection number. This is applicable if the section is a + /// COMDAT section. + /// + [FieldOffset(14)] public byte AuxFormat5Selection; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + [FieldOffset(15)] public byte[] AuxFormat5Unused; + + #endregion + + #endregion } } diff --git a/BurnOutSharp.Models/PortableExecutable/Executable.cs b/BurnOutSharp.Models/PortableExecutable/Executable.cs index 8f74221e..323e5715 100644 --- a/BurnOutSharp.Models/PortableExecutable/Executable.cs +++ b/BurnOutSharp.Models/PortableExecutable/Executable.cs @@ -41,6 +41,6 @@ namespace BurnOutSharp.Models.PortableExecutable /// public COFFSymbolTableEntry[] COFFSymbolTable { get; set; } - // TODO: Left off at "Auxiliary Symbol Records" + // TODO: Left off at "COMDAT Sections (Object Only)" } }