Example #1
0
        /// <summary>
        /// Process a single relocation by copying the required number of bytes into a
        /// buffer, applying the relocation and writing it to the output file.
        /// </summary>
        /// <param name="relocationType">Relocation type to process</param>
        /// <param name="sourceRVA">RVA representing the address to relocate</param>
        /// <param name="targetRVA">RVA representing the relocation target</param>
        public void ProcessRelocation(RelocType relocationType, int sourceRVA, int targetRVA, int filePosWhenPlaced)
        {
            int  relocationLength = 0;
            long delta            = 0;

            switch (relocationType)
            {
            case RelocType.IMAGE_REL_BASED_ABSOLUTE:
                // No relocation
                return;

            case RelocType.IMAGE_REL_BASED_HIGHLOW:
            {
                relocationLength = 4;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_ADDR32NB:
            case RelocType.IMAGE_REL_SYMBOL_SIZE:
            {
                relocationLength = 4;
                delta            = targetRVA;
                break;
            }

            case RelocType.IMAGE_REL_BASED_REL32:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            case RelocType.IMAGE_REL_BASED_DIR64:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (long)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_MOV32_PCREL:
            {
                relocationLength = 8;
                const uint offsetCorrection = 12;
                delta = unchecked (targetRVA - (sourceRVA + offsetCorrection));
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
            {
                relocationLength = 4;
                int sourcePageRVA = sourceRVA & ~0xfff;
                // Page delta always fits in 21 bits as long as we use 4-byte RVAs
                delta = ((targetRVA - sourcePageRVA) >> 12) & 0x1f_ffff;
                break;
            }

            case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
            {
                relocationLength = 4;
                delta            = targetRVA & 0xfff;
                break;
            }

            case RelocType.IMAGE_REL_FILE_ABSOLUTE:
            {
                relocationLength = 4;
                delta            = filePosWhenPlaced;
                break;
            }

            case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC:
            case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR:
            {
                relocationLength = 8;
                delta            = targetRVA - sourceRVA;
                break;
            }

            default:
                throw new NotSupportedException();
            }

            if (relocationLength > 0)
            {
                CopyBytesToBuffer(_relocationBuffer, relocationLength);
                unsafe
                {
                    fixed(byte *bufferContent = _relocationBuffer)
                    {
                        long value = Relocation.ReadValue(relocationType, bufferContent);

                        // Supporting non-zero values for ARM64 would require refactoring this function
                        if (((relocationType == RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21) ||
                             (relocationType == RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A) ||
                             (relocationType == RelocType.IMAGE_REL_BASED_LOONGARCH64_PC) ||
                             (relocationType == RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR)
                             ) && (value != 0))
                        {
                            throw new NotSupportedException();
                        }

                        Relocation.WriteValue(relocationType, bufferContent, unchecked (value + delta));
                    }
                }

                // Write the relocated bytes to the output file
                _outputStream.Write(_relocationBuffer, 0, relocationLength);
                _outputFilePos += relocationLength;
            }
        }
Example #2
0
        /// <summary>
        /// Process a single relocation by copying the required number of bytes into a
        /// buffer, applying the relocation and writing it to the output file.
        /// </summary>
        /// <param name="relocationType">Relocation type to process</param>
        /// <param name="sourceRVA">RVA representing the address to relocate</param>
        /// <param name="targetRVA">RVA representing the relocation target</param>
        public void ProcessRelocation(RelocType relocationType, int sourceRVA, int targetRVA)
        {
            int  relocationLength = 0;
            long delta            = 0;

            switch (relocationType)
            {
            case RelocType.IMAGE_REL_BASED_ABSOLUTE:
                // No relocation
                return;

            case RelocType.IMAGE_REL_BASED_HIGHLOW:
            {
                relocationLength = 4;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_ADDR32NB:
            case RelocType.IMAGE_REL_SYMBOL_SIZE:
            {
                relocationLength = 4;
                delta            = targetRVA;
                break;
            }

            case RelocType.IMAGE_REL_BASED_REL32:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            case RelocType.IMAGE_REL_BASED_DIR64:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (long)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
            {
                relocationLength = 4;
                delta            = (targetRVA - sourceRVA) >> 12;
                break;
            }

            case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
            {
                relocationLength = 4;
                delta            = targetRVA & 0xfff;
                break;
            }

            default:
                throw new NotSupportedException();
            }

            if (relocationLength > 0)
            {
                CopyBytesToBuffer(_relocationBuffer, relocationLength);
                unsafe
                {
                    fixed(byte *bufferContent = _relocationBuffer)
                    {
                        long value = Relocation.ReadValue(relocationType, bufferContent);

                        // Supporting non-zero values for ARM64 would require refactoring this function
                        if (((relocationType == RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21) || (relocationType == RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A)) && (value != 0))
                        {
                            throw new NotSupportedException();
                        }

                        Relocation.WriteValue(relocationType, bufferContent, unchecked (value + delta));
                    }
                }

                // Write the relocated bytes to the output file
                _outputStream.Write(_relocationBuffer, 0, relocationLength);
                _outputFilePos += relocationLength;
            }
        }
Example #3
0
        /// <summary>
        /// Process a single relocation by copying the required number of bytes into a
        /// buffer, applying the relocation and writing it to the output file.
        /// </summary>
        /// <param name="relocationType">Relocation type to process</param>
        /// <param name="sourceRVA">RVA representing the address to relocate</param>
        /// <param name="targetRVA">RVA representing the relocation target</param>
        public void ProcessRelocation(RelocType relocationType, int sourceRVA, int targetRVA)
        {
            int  relocationLength = 0;
            long delta            = 0;

            switch (relocationType)
            {
            case RelocType.IMAGE_REL_BASED_ABSOLUTE:
                // No relocation
                return;

            case RelocType.IMAGE_REL_BASED_HIGHLOW:
            {
                relocationLength = 4;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_ADDR32NB:
            {
                relocationLength = 4;
                delta            = targetRVA;
                break;
            }

            case RelocType.IMAGE_REL_BASED_REL32:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            case RelocType.IMAGE_REL_BASED_DIR64:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (long)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
            {
                relocationLength = 8;
                delta            = unchecked (targetRVA + (int)_defaultImageBase);
                break;
            }

            case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
            {
                relocationLength = 4;
                delta            = targetRVA - sourceRVA - 4;
                break;
            }

            default:
                throw new NotSupportedException();
            }

            if (relocationLength > 0)
            {
                CopyBytesToBuffer(_relocationBuffer, relocationLength);
                unsafe
                {
                    fixed(byte *bufferContent = _relocationBuffer)
                    {
                        long value = Relocation.ReadValue(relocationType, bufferContent);

                        Relocation.WriteValue(relocationType, bufferContent, unchecked (value + delta));
                    }
                }

                // Write the relocated bytes to the output file
                _outputStream.Write(_relocationBuffer, 0, relocationLength);
                _outputFilePos += relocationLength;
            }
        }