Beispiel #1
0
        /// <summary>
        /// Copy PE headers into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="peHeaders">Headers to copy</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = peHeaders.CoffHeader.Characteristics;

            if (is64BitTarget)
            {
                imageCharacteristics &= ~Characteristics.Bit32Machine;
                imageCharacteristics |= Characteristics.LargeAddressAware;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                       // we need the same alignment for both.
                       sectionAlignment: (target.IsWindows ? peHeaders.PEHeader.SectionAlignment : peHeaders.PEHeader.FileAlignment),
                       fileAlignment: peHeaders.PEHeader.FileAlignment,
                       imageBase: peHeaders.PEHeader.ImageBase,
                       majorLinkerVersion: peHeaders.PEHeader.MajorLinkerVersion,
                       minorLinkerVersion: peHeaders.PEHeader.MinorLinkerVersion,
                       majorOperatingSystemVersion: peHeaders.PEHeader.MajorOperatingSystemVersion,
                       minorOperatingSystemVersion: peHeaders.PEHeader.MinorOperatingSystemVersion,
                       majorImageVersion: peHeaders.PEHeader.MajorImageVersion,
                       minorImageVersion: peHeaders.PEHeader.MinorImageVersion,
                       majorSubsystemVersion: peHeaders.PEHeader.MajorSubsystemVersion,
                       minorSubsystemVersion: peHeaders.PEHeader.MinorSubsystemVersion,
                       subsystem: peHeaders.PEHeader.Subsystem,
                       dllCharacteristics: peHeaders.PEHeader.DllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: peHeaders.PEHeader.SizeOfStackReserve,
                       sizeOfStackCommit: peHeaders.PEHeader.SizeOfStackCommit,
                       sizeOfHeapReserve: peHeaders.PEHeader.SizeOfHeapReserve,
                       sizeOfHeapCommit: peHeaders.PEHeader.SizeOfHeapCommit));
        }
Beispiel #2
0
        /// <summary>
        /// Fill in PE header information into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="relocsStripped">Relocs are not present in the PE executable</param>
        /// <param name="dllCharacteristics">Extra DLL characteristics to apply</param>
        /// <param name="subsystem">Targeting subsystem</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Create(Characteristics imageCharacteristics, DllCharacteristics dllCharacteristics, Subsystem subsystem, TargetDetails target)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            imageCharacteristics &= ~(Characteristics.Bit32Machine | Characteristics.LargeAddressAware);
            imageCharacteristics |= (is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine);

            ulong imageBase = PE32HeaderConstants.ImageBase;

            if (target.IsWindows && is64BitTarget && (imageBase <= uint.MaxValue))
            {
                // Base addresses below 4 GiB are reserved for WoW on x64 and disallowed on ARM64.
                // If the input assembly was compiled for anycpu, its base address is 32-bit and we need to fix it.
                imageBase = (imageCharacteristics & Characteristics.Dll) != 0 ? PE64HeaderConstants.DllImageBase : PE64HeaderConstants.ExeImageBase;
            }

            int fileAlignment = 0x200;

            if (!target.IsWindows && !is64BitTarget)
            {
                // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K).
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!target.IsWindows && is64BitTarget)
            {
                // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                sectionAlignment = fileAlignment;
            }

            dllCharacteristics &= DllCharacteristics.AppContainer;

            // In Crossgen1, this is under a debug-specific condition 'if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen))'
            dllCharacteristics |= DllCharacteristics.DynamicBase;

            // Without NxCompatible the PE executable cannot execute on Windows ARM64
            dllCharacteristics |= DllCharacteristics.NxCompatible | DllCharacteristics.TerminalServerAware;

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }
            else
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: imageBase,
                       majorLinkerVersion: PEHeaderConstants.MajorLinkerVersion,
                       minorLinkerVersion: PEHeaderConstants.MinorLinkerVersion,
                       majorOperatingSystemVersion: PEHeaderConstants.MajorOperatingSystemVersion,
                       minorOperatingSystemVersion: PEHeaderConstants.MinorOperatingSystemVersion,
                       majorImageVersion: PEHeaderConstants.MajorImageVersion,
                       minorImageVersion: PEHeaderConstants.MinorImageVersion,
                       majorSubsystemVersion: PEHeaderConstants.MajorSubsystemVersion,
                       minorSubsystemVersion: PEHeaderConstants.MinorSubsystemVersion,
                       subsystem: subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfStackReserve : PE32HeaderConstants.SizeOfStackReserve),
                       sizeOfStackCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfStackCommit : PE32HeaderConstants.SizeOfStackCommit),
                       sizeOfHeapReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapReserve : PE32HeaderConstants.SizeOfHeapReserve),
                       sizeOfHeapCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapCommit : PE32HeaderConstants.SizeOfHeapCommit)));
        }
Beispiel #3
0
        /// <summary>
        /// Copy PE headers into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="peHeaders">Headers to copy</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = peHeaders.CoffHeader.Characteristics;

            if (is64BitTarget)
            {
                imageCharacteristics &= ~Characteristics.Bit32Machine;
                imageCharacteristics |= Characteristics.LargeAddressAware;
            }

            int fileAlignment = 0x200;

            if (!target.IsWindows && !is64BitTarget)
            {
                // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K).
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!target.IsWindows && is64BitTarget)
            {
                // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                sectionAlignment = fileAlignment;
            }

            DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible;

            if (!is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            // Copy over selected DLL characteristics bits from IL image
            dllCharacteristics |= peHeaders.PEHeader.DllCharacteristics &
                                  (DllCharacteristics.TerminalServerAware | DllCharacteristics.AppContainer);

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: peHeaders.PEHeader.ImageBase,
                       majorLinkerVersion: 11,
                       minorLinkerVersion: 0,
                       majorOperatingSystemVersion: 5,
                       // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images
                       minorOperatingSystemVersion: is64BitTarget ? (ushort)2 : (ushort)0,
                       majorImageVersion: peHeaders.PEHeader.MajorImageVersion,
                       minorImageVersion: peHeaders.PEHeader.MinorImageVersion,
                       majorSubsystemVersion: peHeaders.PEHeader.MajorSubsystemVersion,
                       minorSubsystemVersion: peHeaders.PEHeader.MinorSubsystemVersion,
                       subsystem: peHeaders.PEHeader.Subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: peHeaders.PEHeader.SizeOfStackReserve,
                       sizeOfStackCommit: peHeaders.PEHeader.SizeOfStackCommit,
                       sizeOfHeapReserve: 0,
                       sizeOfHeapCommit: 0));
        }
Beispiel #4
0
        /// <summary>
        /// Fill in PE header information into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="subsystem">Targeting subsystem</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Create(Subsystem subsystem, TargetDetails target, ulong imageBase)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = Characteristics.ExecutableImage | Characteristics.Dll;

            imageCharacteristics |= is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine;

            int  fileAlignment    = 0x200;
            bool isWindowsOr32bit = target.IsWindows || !is64BitTarget;

            if (isWindowsOr32bit)
            {
                // To minimize wasted VA space on 32-bit systems (regardless of OS),
                // align file to page boundaries (presumed to be 4K)
                //
                // On Windows we use 4K file alignment (regardless of ptr size),
                // per requirements of memory mapping API (MapViewOfFile3, et al).
                // The alternative could be using the same approach as on Unix, but that would result in PEs
                // incompatible with OS loader. While that is not a problem on Unix, we do not want that on Windows.
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!isWindowsOr32bit)
            {
                // On 64bit Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                //
                // In addition to that we specify section RVAs to be at least 64K apart, which is > page on most systems.
                // It ensures that the sections will not overlap when mapped from a singlefile bundle, which introduces a sub-page skew.
                //
                // Such format would not be accepted by OS loader on Windows, but it is not a problem on Unix.
                sectionAlignment = fileAlignment;
            }

            // Without NxCompatible the PE executable cannot execute on Windows ARM64
            DllCharacteristics dllCharacteristics =
                DllCharacteristics.DynamicBase |
                DllCharacteristics.NxCompatible |
                DllCharacteristics.TerminalServerAware;

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }
            else
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: imageBase,
                       majorLinkerVersion: PEHeaderConstants.MajorLinkerVersion,
                       minorLinkerVersion: PEHeaderConstants.MinorLinkerVersion,
                       majorOperatingSystemVersion: PEHeaderConstants.MajorOperatingSystemVersion,
                       minorOperatingSystemVersion: PEHeaderConstants.MinorOperatingSystemVersion,
                       majorImageVersion: PEHeaderConstants.MajorImageVersion,
                       minorImageVersion: PEHeaderConstants.MinorImageVersion,
                       majorSubsystemVersion: PEHeaderConstants.MajorSubsystemVersion,
                       minorSubsystemVersion: PEHeaderConstants.MinorSubsystemVersion,
                       subsystem: subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfStackReserve : PE32HeaderConstants.SizeOfStackReserve),
                       sizeOfStackCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfStackCommit : PE32HeaderConstants.SizeOfStackCommit),
                       sizeOfHeapReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapReserve : PE32HeaderConstants.SizeOfHeapReserve),
                       sizeOfHeapCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapCommit : PE32HeaderConstants.SizeOfHeapCommit)));
        }
Beispiel #5
0
        /// <summary>
        /// Fill in PE header information into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="subsystem">Targeting subsystem</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Create(Subsystem subsystem, TargetDetails target)
        {
            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = Characteristics.ExecutableImage | Characteristics.Dll;

            imageCharacteristics |= is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine;

            ulong imageBase = is64BitTarget ? PE64HeaderConstants.DllImageBase : PE32HeaderConstants.ImageBase;

            int fileAlignment = 0x200;

            if (!target.IsWindows && !is64BitTarget)
            {
                // To minimize wasted VA space on 32-bit systems, align file to page boundaries (presumed to be 4K)
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!target.IsWindows && is64BitTarget)
            {
                // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                sectionAlignment = fileAlignment;
            }

            // Without NxCompatible the PE executable cannot execute on Windows ARM64
            DllCharacteristics dllCharacteristics =
                DllCharacteristics.DynamicBase |
                DllCharacteristics.NxCompatible |
                DllCharacteristics.TerminalServerAware;

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }
            else
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: imageBase,
                       majorLinkerVersion: PEHeaderConstants.MajorLinkerVersion,
                       minorLinkerVersion: PEHeaderConstants.MinorLinkerVersion,
                       majorOperatingSystemVersion: PEHeaderConstants.MajorOperatingSystemVersion,
                       minorOperatingSystemVersion: PEHeaderConstants.MinorOperatingSystemVersion,
                       majorImageVersion: PEHeaderConstants.MajorImageVersion,
                       minorImageVersion: PEHeaderConstants.MinorImageVersion,
                       majorSubsystemVersion: PEHeaderConstants.MajorSubsystemVersion,
                       minorSubsystemVersion: PEHeaderConstants.MinorSubsystemVersion,
                       subsystem: subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfStackReserve : PE32HeaderConstants.SizeOfStackReserve),
                       sizeOfStackCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfStackCommit : PE32HeaderConstants.SizeOfStackCommit),
                       sizeOfHeapReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapReserve : PE32HeaderConstants.SizeOfHeapReserve),
                       sizeOfHeapCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapCommit : PE32HeaderConstants.SizeOfHeapCommit)));
        }
Beispiel #6
0
        /// <summary>
        /// Copy PE headers into a PEHeaderBuilder used by PEBuilder.
        /// </summary>
        /// <param name="peHeaders">Headers to copy</param>
        /// <param name="target">Target architecture to set in the header</param>
        public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
        {
            // Default base addresses used by Roslyn
            const ulong DefaultExeBaseAddress64Bit = 0x1_4000_0000;
            const ulong DefaultDllBaseAddress64Bit = 0x1_8000_0000;

            bool is64BitTarget = target.PointerSize == sizeof(long);

            Characteristics imageCharacteristics = peHeaders.CoffHeader.Characteristics;

            if (is64BitTarget)
            {
                imageCharacteristics &= ~Characteristics.Bit32Machine;
                imageCharacteristics |= Characteristics.LargeAddressAware;
            }

            ulong imageBase = peHeaders.PEHeader.ImageBase;

            if (target.IsWindows && is64BitTarget && (imageBase <= uint.MaxValue))
            {
                // Base addresses below 4 GiB are reserved for WoW on x64 and disallowed on ARM64.
                // If the input assembly was compiled for anycpu, its base address is 32-bit and we need to fix it.
                imageBase = (imageCharacteristics & Characteristics.Dll) != 0 ? DefaultDllBaseAddress64Bit : DefaultExeBaseAddress64Bit;
            }

            int fileAlignment = 0x200;

            if (!target.IsWindows && !is64BitTarget)
            {
                // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K).
                fileAlignment = 0x1000;
            }

            int sectionAlignment = 0x1000;

            if (!target.IsWindows && is64BitTarget)
            {
                // On Linux, we must match the bottom 12 bits of section RVA's to their file offsets. For this reason
                // we need the same alignment for both.
                sectionAlignment = fileAlignment;
            }

            DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible;

            // Copy over selected DLL characteristics bits from IL image
            dllCharacteristics |= peHeaders.PEHeader.DllCharacteristics &
                                  (DllCharacteristics.TerminalServerAware | DllCharacteristics.AppContainer);

            if (is64BitTarget)
            {
                dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
            }
            else
            {
                dllCharacteristics |= DllCharacteristics.NoSeh;
            }

            return(new PEHeaderBuilder(
                       machine: target.MachineFromTarget(),
                       sectionAlignment: sectionAlignment,
                       fileAlignment: fileAlignment,
                       imageBase: imageBase,
                       majorLinkerVersion: 11,
                       minorLinkerVersion: 0,
                       majorOperatingSystemVersion: 5,
                       // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images
                       minorOperatingSystemVersion: is64BitTarget ? (ushort)2 : (ushort)0,
                       majorImageVersion: peHeaders.PEHeader.MajorImageVersion,
                       minorImageVersion: peHeaders.PEHeader.MinorImageVersion,
                       majorSubsystemVersion: peHeaders.PEHeader.MajorSubsystemVersion,
                       minorSubsystemVersion: peHeaders.PEHeader.MinorSubsystemVersion,
                       subsystem: peHeaders.PEHeader.Subsystem,
                       dllCharacteristics: dllCharacteristics,
                       imageCharacteristics: imageCharacteristics,
                       sizeOfStackReserve: peHeaders.PEHeader.SizeOfStackReserve,
                       sizeOfStackCommit: peHeaders.PEHeader.SizeOfStackCommit,
                       sizeOfHeapReserve: 0,
                       sizeOfHeapCommit: 0));
        }