private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);
                RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

            #if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
            #endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                            entryParser.GetUnsigned();

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned()));
                        IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset);

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
            #if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
            #endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
        public MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, uint nativeLayoutOffset)
        {
            NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset);

            string methodName = parser.GetString();

            // Signatures are indirected to through a relative offset so that we don't have to parse them
            // when not comparing signatures (parsing them requires resolving types and is tremendously
            // expensive).
            NativeParser sigParser = parser.GetParserFromRelativeOffset();
            IntPtr methodSigPtr = sigParser.Reader.OffsetToAddress(sigParser.Offset);

            return new MethodNameAndSignature(methodName, methodSigPtr);
        }
Exemplo n.º 3
0
        public bool TryGetAt(byte[] image, uint index, ref int pOffset)
        {
            if (index >= _nElements)
            {
                return(false);
            }

            uint offset = 0;

            if (_entryIndexSize == 0)
            {
                int i = (int)(_baseOffset + (index / _blockSize));
                offset = NativeReader.ReadByte(image, ref i);
            }
            else if (_entryIndexSize == 1)
            {
                int i = (int)(_baseOffset + 2 * (index / _blockSize));
                offset = NativeReader.ReadUInt16(image, ref i);
            }
            else
            {
                int i = (int)(_baseOffset + 4 * (index / _blockSize));
                offset = NativeReader.ReadUInt32(image, ref i);
            }
            offset += _baseOffset;

            for (uint bit = _blockSize >> 1; bit > 0; bit >>= 1)
            {
                uint val     = 0;
                uint offset2 = NativeReader.DecodeUnsigned(image, offset, ref val);
                if ((index & bit) != 0)
                {
                    if ((val & 2) != 0)
                    {
                        offset = offset + (val >> 2);
                        continue;
                    }
                }
                else
                {
                    if ((val & 1) != 0)
                    {
                        offset = offset2;
                        continue;
                    }
                }

                // Not found
                if ((val & 3) == 0)
                {
                    // Matching special leaf node?
                    if ((val >> 2) == (index & (_blockSize - 1)))
                    {
                        offset = offset2;
                        break;
                    }
                }
                return(false);
            }
            pOffset = (int)offset;
            return(true);
        }
Exemplo n.º 4
0
        private List <List <BaseGcSlot> > GetLiveSlotsAtSafepoints(byte[] image, ref int bitOffset)
        {
            // For each safe point, enumerates a list of GC slots that are alive at that point
            var result = new List <List <BaseGcSlot> >();

            uint numSlots = SlotTable.NumTracked;

            if (numSlots == 0)
            {
                return(null);
            }

            uint numBitsPerOffset = 0;

            // Duplicate the encoder's heuristic to determine if we have indirect live
            // slot table (similar to the chunk pointers)
            if (NativeReader.ReadBits(image, 1, ref bitOffset) != 0)
            {
                numBitsPerOffset = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.POINTER_SIZE_ENCBASE, ref bitOffset) + 1;
                Debug.Assert(numBitsPerOffset != 0);
            }

            uint offsetTablePos = (uint)bitOffset;

            for (uint safePointIndex = 0; safePointIndex < NumSafePoints; safePointIndex++)
            {
                bitOffset = (int)offsetTablePos;

                var liveSlots = new List <BaseGcSlot>();

                if (numBitsPerOffset != 0)
                {
                    bitOffset += (int)(numBitsPerOffset * safePointIndex);

                    uint liveStatesOffset = (uint)NativeReader.ReadBits(image, (int)numBitsPerOffset, ref bitOffset);
                    uint liveStatesStart  = (uint)((offsetTablePos + NumSafePoints * numBitsPerOffset + 7) & (~7));
                    bitOffset = (int)(liveStatesStart + liveStatesOffset);
                    if (NativeReader.ReadBits(image, 1, ref bitOffset) != 0)
                    {
                        // RLE encoded
                        bool skip      = NativeReader.ReadBits(image, 1, ref bitOffset) == 0;
                        bool report    = true;
                        uint readSlots = NativeReader.DecodeVarLengthUnsigned(image,
                                                                              skip ? _gcInfoTypes.LIVESTATE_RLE_SKIP_ENCBASE : _gcInfoTypes.LIVESTATE_RLE_RUN_ENCBASE, ref bitOffset);
                        skip = !skip;
                        while (readSlots < numSlots)
                        {
                            uint cnt = NativeReader.DecodeVarLengthUnsigned(image,
                                                                            skip ? _gcInfoTypes.LIVESTATE_RLE_SKIP_ENCBASE : _gcInfoTypes.LIVESTATE_RLE_RUN_ENCBASE, ref bitOffset) + 1;
                            if (report)
                            {
                                for (uint slotIndex = readSlots; slotIndex < readSlots + cnt; slotIndex++)
                                {
                                    int trackedSlotIndex = 0;
                                    foreach (var slot in SlotTable.GcSlots)
                                    {
                                        if (slot.Flags != GcSlotFlags.GC_SLOT_UNTRACKED)
                                        {
                                            if (slotIndex == trackedSlotIndex)
                                            {
                                                liveSlots.Add(slot);
                                                break;
                                            }
                                            trackedSlotIndex++;
                                        }
                                    }
                                }
                            }
                            readSlots += cnt;
                            skip       = !skip;
                            report     = !report;
                        }
                        Debug.Assert(readSlots == numSlots);
                        result.Add(liveSlots);
                        continue;
                    }
                    // Just a normal live state (1 bit per slot), so use the normal decoding loop
                }
                else
                {
                    bitOffset += (int)(safePointIndex * numSlots);
                }

                for (uint slotIndex = 0; slotIndex < numSlots; slotIndex++)
                {
                    bool isLive = NativeReader.ReadBits(image, 1, ref bitOffset) != 0;
                    if (isLive)
                    {
                        int trackedSlotIndex = 0;
                        foreach (var slot in SlotTable.GcSlots)
                        {
                            if (slot.Flags != GcSlotFlags.GC_SLOT_UNTRACKED)
                            {
                                if (slotIndex == trackedSlotIndex)
                                {
                                    liveSlots.Add(slot);
                                    break;
                                }
                                trackedSlotIndex++;
                            }
                        }
                    }
                }

                result.Add(liveSlots);
            }

            return(result);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Initialize the GcInfo header
        /// based on <a href="https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp">src\inc\gcdecoder.cpp</a> DecodeHeader and <a href="https://github.com/dotnet/runtime/blob/main/src/coreclr/gcdump/i386/gcdumpx86.cpp">GCDump::DumpInfoHdr</a>
        /// </summary>
        public static InfoHdrSmall DecodeHeader(byte[] image, ref int offset, int codeLength)
        {
            byte         nextByte = image[offset++];
            byte         encoding = (byte)(nextByte & 0x7f);
            InfoHdrSmall header   = GetInfoHdr(encoding);

            while ((nextByte & (uint)InfoHdrAdjustConstants.MORE_BYTES_TO_FOLLOW) != 0)
            {
                nextByte = image[offset++];
                encoding = (byte)(nextByte & (uint)InfoHdrAdjustConstants.ADJ_ENCODING_MAX);

                if (encoding < (uint)InfoHdrAdjust.NEXT_FOUR_START)
                {
                    if (encoding < (uint)InfoHdrAdjust.SET_ARGCOUNT)
                    {
                        header.FrameSize = (byte)(encoding - (uint)InfoHdrAdjust.SET_FRAMESIZE);
                    }
                    else if (encoding < (uint)InfoHdrAdjust.SET_PROLOGSIZE)
                    {
                        header.ArgCount = (byte)(encoding - (uint)InfoHdrAdjust.SET_ARGCOUNT);
                    }
                    else if (encoding < (uint)InfoHdrAdjust.SET_EPILOGSIZE)
                    {
                        header.PrologSize = (byte)(encoding - (uint)InfoHdrAdjust.SET_PROLOGSIZE);
                    }
                    else if (encoding < (uint)InfoHdrAdjust.SET_EPILOGCNT)
                    {
                        header.EpilogSize = (byte)(encoding - (uint)InfoHdrAdjust.SET_EPILOGSIZE);
                    }
                    else if (encoding < (uint)InfoHdrAdjust.SET_UNTRACKED)
                    {
                        header.EpilogCount = (byte)((encoding - (uint)InfoHdrAdjust.SET_EPILOGCNT) / 2);
                        header.EpilogAtEnd = ((encoding - (uint)InfoHdrAdjust.SET_EPILOGCNT) & 1) == 1 ? true : false;
                    }
                    else if (encoding < (uint)InfoHdrAdjust.FIRST_FLIP)
                    {
                        header.UntrackedCnt = (byte)(encoding - (uint)InfoHdrAdjust.SET_UNTRACKED);
                    }
                    else
                    {
                        switch (encoding)
                        {
                        case (byte)InfoHdrAdjust.FLIP_EDI_SAVED:
                            header.EdiSaved = !header.EdiSaved;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_ESI_SAVED:
                            header.EsiSaved = !header.EsiSaved;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_EBX_SAVED:
                            header.EbxSaved = !header.EbxSaved;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_EBP_SAVED:
                            header.EbpSaved = !header.EbpSaved;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_EBP_FRAME:
                            header.EbpFrame = !header.EbpFrame;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_INTERRUPTIBLE:
                            header.Interruptible = !header.Interruptible;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_DOUBLE_ALIGN:
                            header.DoubleAlign = !header.DoubleAlign;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_SECURITY:
                            header.Security = !header.Security;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_HANDLERS:
                            header.Handlers = !header.Handlers;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_LOCALLOC:
                            header.Localloc = !header.Localloc;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_EDITnCONTINUE:
                            header.EditNcontinue = !header.EditNcontinue;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_VAR_PTR_TABLE_SZ:
                            header.VarPtrTableSize ^= HAS_VARPTR;
                            break;

                        case (byte)InfoHdrAdjust.FFFF_UNTRACKED_CNT:
                            header.UntrackedCnt = HAS_UNTRACKED;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_VARARGS:
                            header.Varargs = !header.Varargs;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_PROF_CALLBACKS:
                            header.ProfCallbacks = !header.ProfCallbacks;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_HAS_GENERICS_CONTEXT:
                            header.GenericsContext ^= 1;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_GENERICS_CONTEXT_IS_METHODDESC:
                            header.GenericsContextIsMethodDesc ^= 1;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_HAS_GS_COOKIE:
                            header.GsCookieOffset ^= HAS_GS_COOKIE_OFFSET;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_SYNC:
                            header.SyncStartOffset ^= HAS_SYNC_OFFSET;
                            break;

                        case (byte)InfoHdrAdjust.FLIP_REV_PINVOKE_FRAME:
                            header.RevPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET;
                            break;

                        case (byte)InfoHdrAdjust.NEXT_OPCODE:
                            nextByte = image[offset++];
                            encoding = (byte)(nextByte & (int)InfoHdrAdjustConstants.ADJ_ENCODING_MAX);
                            // encoding here always corresponds to codes in InfoHdrAdjust2 set

                            if (encoding < (int)InfoHdrAdjustConstants.SET_RET_KIND_MAX)
                            {
                                header.ReturnKind = (ReturnKinds)encoding;
                            }
                            else
                            {
                                throw new BadImageFormatException("Unexpected gcinfo header encoding");
                            }
                            break;

                        default:
                            throw new BadImageFormatException("Unexpected gcinfo header encoding");
                        }
                    }
                }
                else
                {
                    byte lowBits;
                    switch (encoding >> 4)
                    {
                    case 5:
                        lowBits            = (byte)(encoding & 0xf);
                        header.FrameSize <<= 4;
                        header.FrameSize  += lowBits;
                        break;

                    case 6:
                        lowBits           = (byte)(encoding & 0xf);
                        header.ArgCount <<= 4;
                        header.ArgCount  += lowBits;
                        break;

                    case 7:
                        if ((encoding & 0x8) == 0)
                        {
                            lowBits             = (byte)(encoding & 0x7);
                            header.PrologSize <<= 3;
                            header.PrologSize  += lowBits;
                        }
                        else
                        {
                            lowBits             = (byte)(encoding & 0x7);
                            header.EpilogSize <<= 3;
                            header.EpilogSize  += lowBits;
                        }
                        break;

                    default:
                        throw new BadImageFormatException("Unexpected gcinfo header encoding");
                    }
                }
            }

            if (header.UntrackedCnt == HAS_UNTRACKED)
            {
                header.HasArgTabOffset = true;
                header.UntrackedCnt    = NativeReader.DecodeUnsignedGc(image, ref offset);
            }
            if (header.VarPtrTableSize == HAS_VARPTR)
            {
                header.HasArgTabOffset = true;
                header.VarPtrTableSize = NativeReader.DecodeUnsignedGc(image, ref offset);
            }
            if (header.GsCookieOffset == HAS_GS_COOKIE_OFFSET)
            {
                header.GsCookieOffset = NativeReader.DecodeUnsignedGc(image, ref offset);
            }
            if (header.SyncStartOffset == HAS_SYNC_OFFSET)
            {
                header.SyncStartOffset = NativeReader.DecodeUnsignedGc(image, ref offset);
                header.SyncEndOffset   = NativeReader.DecodeUnsignedGc(image, ref offset);
            }
            if (header.RevPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET)
            {
                header.RevPInvokeOffset = NativeReader.DecodeUnsignedGc(image, ref offset);
            }

            header.Epilogs = new List <int>();
            if (header.EpilogCount > 1 || (header.EpilogCount != 0 && !header.EpilogAtEnd))
            {
                uint offs = 0;

                for (int i = 0; i < header.EpilogCount; i++)
                {
                    offs = NativeReader.DecodeUDelta(image, ref offset, offs);
                    header.Epilogs.Add((int)offs);
                }
            }
            else
            {
                if (header.EpilogCount != 0)
                {
                    header.Epilogs.Add(codeLength - (int)header.EpilogSize);
                }
            }

            if (header.HasArgTabOffset)
            {
                header.ArgTabOffset = NativeReader.DecodeUnsignedGc(image, ref offset);
            }

            return(header);
        }
Exemplo n.º 6
0
        private void GetTransitionsNoEbp(byte[] image, ref int offset)
        {
            uint curOffs  = 0;
            uint lastSkip = 0;
            uint imask    = 0;

            for (; ;)
            {
                uint val = image[offset++];

                if ((val & 0x80) == 0)
                {
                    if ((val & 0x40) == 0)
                    {
                        if ((val & 0x20) == 0)
                        {
                            // push    000DDDDD          push one item, 5-bit delta
                            curOffs += val & 0x1F;
                            AddNewTransition(new GcTransitionRegister((int)curOffs, Registers.ESP, Action.PUSH));
                        }
                        else
                        {
                            // push    00100000 [pushCount]     ESP push multiple items
                            uint pushCount = NativeReader.DecodeUnsignedGc(image, ref offset);
                            AddNewTransition(new GcTransitionRegister((int)curOffs, Registers.ESP, Action.PUSH, false, false, (int)pushCount));
                        }
                    }
                    else
                    {
                        uint popSize;
                        uint skip;

                        if ((val & 0x3f) == 0)
                        {
                            //
                            // skip    01000000 [Delta]  Skip arbitrary sized delta
                            //
                            skip     = NativeReader.DecodeUnsignedGc(image, ref offset);
                            curOffs += skip;
                            lastSkip = skip;
                        }
                        else
                        {
                            //  pop     01CCDDDD         pop CC items, 4-bit delta
                            popSize  = (val & 0x30) >> 4;
                            skip     = val & 0x0f;
                            curOffs += skip;

                            if (popSize > 0)
                            {
                                AddNewTransition(new GcTransitionRegister((int)curOffs, Registers.ESP, Action.POP, false, false, (int)popSize));
                            }
                            else
                            {
                                lastSkip = skip;
                            }
                        }
                    }
                }
                else
                {
                    uint callArgCnt;
                    uint callRegMask;
                    bool callPndTab = false;
                    uint callPndMask = 0;
                    uint callPndTabCnt = 0, callPndTabSize = 0;

                    switch ((val & 0x70) >> 4)
                    {
                    default:
                        //
                        // call    1PPPPPPP          Call Pattern, P=[0..79]
                        //
                        CallPattern.DecodeCallPattern((val & 0x7f), out callArgCnt, out callRegMask, out callPndMask, out lastSkip);
                        curOffs += lastSkip;
                        SaveCallTransition(image, ref offset, val, curOffs, callRegMask, callPndTab, callPndTabCnt, callPndMask, lastSkip, ref imask);
                        break;

                    case 5:
                        //
                        // call    1101RRRR DDCCCMMM  Call RegMask=RRRR,ArgCnt=CCC,
                        //                        ArgMask=MMM Delta=commonDelta[DD]
                        //
                        callRegMask = val & 0xf;        // EBP,EBX,ESI,EDI
                        val         = image[offset++];
                        callPndMask = (val & 0x7);
                        callArgCnt  = (val >> 3) & 0x7;
                        lastSkip    = CallPattern.callCommonDelta[val >> 6];
                        curOffs    += lastSkip;
                        SaveCallTransition(image, ref offset, val, curOffs, callRegMask, callPndTab, callPndTabCnt, callPndMask, lastSkip, ref imask);
                        break;

                    case 6:
                        //
                        // call    1110RRRR [ArgCnt] [ArgMask]
                        //                          Call ArgCnt,RegMask=RRR,ArgMask
                        //
                        callRegMask = val & 0xf;        // EBP,EBX,ESI,EDI
                        callArgCnt  = NativeReader.DecodeUnsignedGc(image, ref offset);
                        callPndMask = NativeReader.DecodeUnsignedGc(image, ref offset);
                        SaveCallTransition(image, ref offset, val, curOffs, callRegMask, callPndTab, callPndTabCnt, callPndMask, lastSkip, ref imask);
                        break;

                    case 7:
                        switch (val & 0x0C)
                        {
                        case 0x00:
                            //  iptr 11110000 [IPtrMask] Arbitrary Interior Pointer Mask
                            imask = NativeReader.DecodeUnsignedGc(image, ref offset);
                            AddNewTransition(new IPtrMask((int)curOffs, imask));
                            break;

                        case 0x04:
                            AddNewTransition(new CalleeSavedRegister((int)curOffs, (CalleeSavedRegisters)(val & 0x3)));
                            break;

                        case 0x08:
                            val            = image[offset++];
                            callRegMask    = val & 0xF;
                            imask          = val >> 4;
                            lastSkip       = NativeReader.ReadUInt32(image, ref offset);
                            curOffs       += lastSkip;
                            callArgCnt     = NativeReader.ReadUInt32(image, ref offset);
                            callPndTabCnt  = NativeReader.ReadUInt32(image, ref offset);
                            callPndTabSize = NativeReader.ReadUInt32(image, ref offset);
                            callPndTab     = true;
                            SaveCallTransition(image, ref offset, val, curOffs, callRegMask, callPndTab, callPndTabCnt, callPndMask, lastSkip, ref imask);
                            break;

                        case 0x0C:
                            return;

                        default:
                            throw new BadImageFormatException("Invalid GC encoding");
                        }
                        break;
                    }
                }
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/gcdump/i386/gcdumpx86.cpp">GCDump::DumpGCTable</a>
        /// </summary>
        private void GetTransitionsFullyInterruptible(byte[] image, ref int offset)
        {
            uint argCnt  = 0;
            bool isThis  = false;
            bool iptr    = false;
            uint curOffs = 0;

            while (true)
            {
                uint isPop;
                uint argOffs;
                uint val = image[offset++];

                if ((val & 0x80) == 0)
                {
                    /* A small 'regPtr' encoding */

                    curOffs += val & 0x7;

                    Action isLive = Action.LIVE;
                    if ((val & 0x40) == 0)
                    {
                        isLive = Action.DEAD;
                    }
                    AddNewTransition(new GcTransitionRegister((int)curOffs, (Registers)((val >> 3) & 7), isLive, isThis, iptr));

                    isThis = false;
                    iptr   = false;
                    continue;
                }

                /* This is probably an argument push/pop */

                argOffs = (val & 0x38) >> 3;

                /* 6 [110] and 7 [111] are reserved for other encodings */

                if (argOffs < 6)
                {
                    /* A small argument encoding */

                    curOffs += (val & 0x07);
                    isPop    = (val & 0x40);

                    ArgEncoding(image, ref isPop, ref argOffs, ref argCnt, ref curOffs, ref isThis, ref iptr);

                    continue;
                }
                else if (argOffs == 6)
                {
                    if ((val & 0x40) != 0)
                    {
                        curOffs += (((val & 0x07) + 1) << 3);
                    }
                    else
                    {
                        // non-ptr arg push

                        curOffs += (val & 0x07);
                        argCnt++;
                        AddNewTransition(new GcTransitionPointer((int)curOffs, argOffs, argCnt, Action.PUSH, Header.EbpFrame, false, false, false));
                    }

                    continue;
                }

                // argOffs was 7 [111] which is reserved for the larger encodings
                switch (val)
                {
                case 0xFF:
                    return;

                case 0xBC:
                    isThis = true;
                    break;

                case 0xBF:
                    iptr = true;
                    break;

                case 0xB8:
                    val      = NativeReader.DecodeUnsignedGc(image, ref offset);
                    curOffs += val;
                    break;

                case 0xF8:
                case 0xFC:
                    isPop   = val & 0x04;
                    argOffs = NativeReader.DecodeUnsignedGc(image, ref offset);
                    ArgEncoding(image, ref isPop, ref argOffs, ref argCnt, ref curOffs, ref isThis, ref iptr);
                    break;

                case 0xFD:
                    argOffs = NativeReader.DecodeUnsignedGc(image, ref offset);
                    AddNewTransition(new GcTransitionPointer((int)curOffs, argOffs, argCnt, Action.KILL, Header.EbpFrame));
                    break;

                case 0xF9:
                    argOffs = NativeReader.DecodeUnsignedGc(image, ref offset);
                    argCnt += argOffs;
                    break;

                default:
                    throw new BadImageFormatException($"Unexpected special code {val}");
                }
            }
        }
Exemplo n.º 8
0
        private unsafe int PatchStatics(TileMatrix matrix, string dataPath, string indexPath, string lookupPath)
        {
            using var staticsDataStream   = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var staticsIndexStream  = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var staticsLookupStream = new FileStream(lookupPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            var staticsIndexReader  = new BinaryReader(staticsIndexStream);
            var staticsLookupReader = new BinaryReader(staticsLookupStream);

            var count = (int)(staticsIndexReader.BaseStream.Length / 4);

            var lists = new TileList[8][];

            for (var x = 0; x < 8; ++x)
            {
                lists[x] = new TileList[8];

                for (var y = 0; y < 8; ++y)
                {
                    lists[x][y] = new TileList();
                }
            }

            for (var i = 0; i < count; ++i)
            {
                var blockID = staticsIndexReader.ReadInt32();
                var blockX  = blockID / matrix.BlockHeight;
                var blockY  = blockID % matrix.BlockHeight;

                var offset = staticsLookupReader.ReadInt32();
                var length = staticsLookupReader.ReadInt32();
                staticsLookupReader.ReadInt32(); // Extra

                if (offset < 0 || length <= 0)
                {
                    matrix.SetStaticBlock(blockX, blockY, matrix.EmptyStaticBlock);
                    continue;
                }

                staticsDataStream.Seek(offset, SeekOrigin.Begin);

                var tileCount = length / 7;

                if (_tileBuffer.Length < tileCount)
                {
                    _tileBuffer = new StaticTile[tileCount];
                }

                var staTiles = _tileBuffer;

                fixed(StaticTile *pTiles = staTiles)
                {
                    NativeReader.Read(staticsDataStream.SafeFileHandle.DangerousGetHandle(), pTiles, length);
                    StaticTile *pCur = pTiles, pEnd = pTiles + tileCount;

                    while (pCur < pEnd)
                    {
                        lists[pCur->X & 0x7][pCur->Y & 0x7].Add(pCur->Id, (sbyte)pCur->Z);
                        pCur += 1;
                    }

                    var tiles = new StaticTile[8][][];

                    for (var x = 0; x < 8; ++x)
                    {
                        tiles[x] = new StaticTile[8][];

                        for (var y = 0; y < 8; ++y)
                        {
                            tiles[x][y] = lists[x][y].ToArray();
                        }
                    }

                    matrix.SetStaticBlock(blockX, blockY, tiles);
                }
            }

            staticsIndexReader.Close();
            staticsLookupReader.Close();

            return(count);
        }
 public static uint Read(this NativeReader reader, uint offset, out long value)
 {
     return(reader.DecodeSignedLong(offset, out value));
 }
Exemplo n.º 10
0
        private static void HighLevelDebugFuncEvalHelper()
        {
            uint parameterBufferSize = RuntimeAugments.RhpGetFuncEvalParameterBufferSize();

            IntPtr writeParameterCommandPointer;
            IntPtr debuggerBufferPointer;

            unsafe
            {
                byte *debuggerBufferRawPointer = stackalloc byte[(int)parameterBufferSize];
                debuggerBufferPointer = new IntPtr(debuggerBufferRawPointer);

                WriteParameterCommand writeParameterCommand = new WriteParameterCommand
                {
                    commandCode   = 1,
                    bufferAddress = debuggerBufferPointer.ToInt64()
                };

                writeParameterCommandPointer = new IntPtr(&writeParameterCommand);

                RuntimeAugments.RhpSendCustomEventToDebugger(writeParameterCommandPointer, Unsafe.SizeOf <WriteParameterCommand>());

                // .. debugger magic ... the debuggerBuffer will be filled with parameter data

                TypesAndValues typesAndValues = new TypesAndValues();

                uint  trash;
                uint  parameterCount;
                uint  parameterValue;
                uint  eeTypeCount;
                ulong eeType;
                uint  offset = 0;

                NativeReader reader = new NativeReader(debuggerBufferRawPointer, parameterBufferSize);
                offset = reader.DecodeUnsigned(offset, out trash); // The VertexSequence always generate a length, I don't really need it.
                offset = reader.DecodeUnsigned(offset, out parameterCount);

                typesAndValues.parameterValues = new int[parameterCount];
                for (int i = 0; i < parameterCount; i++)
                {
                    offset = reader.DecodeUnsigned(offset, out parameterValue);
                    typesAndValues.parameterValues[i] = (int)parameterValue;
                }
                offset = reader.DecodeUnsigned(offset, out eeTypeCount);
                for (int i = 0; i < eeTypeCount; i++)
                {
                    // TODO: Stuff these eeType values into the external reference table
                    offset = reader.DecodeUnsignedLong(offset, out eeType);
                }

                TypeSystemContext typeSystemContext = TypeSystemContextFactory.Create();
                bool       hasThis;
                TypeDesc[] parameters;
                bool[]     parametersWithGenericDependentLayout;
                bool       result = TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature_NativeLayout_Debugger(typeSystemContext, RuntimeSignature.CreateFromNativeLayoutSignatureForDebugger(offset), Instantiation.Empty, Instantiation.Empty, out hasThis, out parameters, out parametersWithGenericDependentLayout, reader);

                typesAndValues.types = new RuntimeTypeHandle[parameters.Length];

                bool needToDynamicallyLoadTypes = false;
                for (int i = 0; i < typesAndValues.types.Length; i++)
                {
                    if (!parameters[i].RetrieveRuntimeTypeHandleIfPossible())
                    {
                        needToDynamicallyLoadTypes = true;
                        break;
                    }

                    typesAndValues.types[i] = parameters[i].GetRuntimeTypeHandle();
                }

                if (needToDynamicallyLoadTypes)
                {
                    TypeLoaderEnvironment.Instance.RunUnderTypeLoaderLock(() =>
                    {
                        typeSystemContext.FlushTypeBuilderStates();

                        GenericDictionaryCell[] cells = new GenericDictionaryCell[parameters.Length];
                        for (int i = 0; i < cells.Length; i++)
                        {
                            cells[i] = GenericDictionaryCell.CreateTypeHandleCell(parameters[i]);
                        }
                        IntPtr[] eetypePointers;
                        TypeBuilder.ResolveMultipleCells(cells, out eetypePointers);

                        for (int i = 0; i < parameters.Length; i++)
                        {
                            typesAndValues.types[i] = ((EEType *)eetypePointers[i])->ToRuntimeTypeHandle();
                        }
                    });
                }

                TypeSystemContextFactory.Recycle(typeSystemContext);

                LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    // TODO: What these false really means? Need to make sure our format contains those information
                    argumentTypes[i] = new LocalVariableType(typesAndValues.types[i], false, false);
                }

                LocalVariableSet.SetupArbitraryLocalVariableSet <TypesAndValues>(HighLevelDebugFuncEvalHelperWithVariables, ref typesAndValues, argumentTypes);
            }
        }
Exemplo n.º 11
0
 public unsafe LowLevelNativeFormatReader(byte *buffer, uint bufferSize)
 {
     _nativeReader = new NativeReader(buffer, bufferSize);
     _offset       = 0;
 }
        private static MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, TypeManagerHandle moduleHandle, uint nativeLayoutOffset)
        {
            NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset);

            string methodName = parser.GetString();

            // Signatures are indirected to through a relative offset so that we don't have to parse them
            // when not comparing signatures (parsing them requires resolving types and is tremendously
            // expensive).
            NativeParser     sigParser = parser.GetParserFromRelativeOffset();
            RuntimeSignature methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, sigParser.Offset);

            return(new MethodNameAndSignature(methodName, methodSig));
        }
Exemplo n.º 13
0
        private unsafe static bool TryGetNativeReaderForBlob(IntPtr module, ReflectionMapBlob blob, out NativeReader reader)
        {
            byte *pBlob;
            uint  cbBlob;

            if (RuntimeAugments.FindBlob(module, (int)blob, (IntPtr)(&pBlob), (IntPtr)(&cbBlob)))
            {
                reader = new NativeReader(pBlob, cbBlob);
                return(true);
            }

            reader = default(NativeReader);
            return(false);
        }
Exemplo n.º 14
0
        private static async void OnImportSoundCommand(bool forceMono)
        {
            var asset     = _currentEditor.Asset;
            var soundWave = (SoundWaveAsset)asset.RootObject;

            byte chunkIndex = 0;

            if (soundWave.Localization != null && soundWave.Localization.Count > 0)
            {
                var english = soundWave.Localization[0];
                chunkIndex = soundWave.RuntimeVariations[english.FirstVariationIndex].ChunkIndex;
            }

            var chunk = soundWave.Chunks[chunkIndex];

            var chunkEntry = App.AssetManager.GetChunkEntry(chunk.ChunkId);

            var ofd = new OpenFileDialog();

            ofd.Filter      = "All Media Files|*.wav;*.mp3";
            ofd.Title       = "Open Audio";
            ofd.Multiselect = true;

            if (ofd.ShowDialog(_mainWindow) != true)
            {
                return;
            }

            FrostyTask2.Begin("Importing Chunk", "");
            await Task.Run(() =>
            {
                var imports        = new List <SoundImport>();
                var totalChunkSize = 0u;

                foreach (var fileName in ofd.FileNames)
                {
                    var tempFile = Path.GetTempFileName();
#if DEBUG
                    var tempFile2 = Path.GetTempFileName();

                    var decoder = new CSCore.Ffmpeg.FfmpegDecoder(fileName);
                    var source  = decoder.ChangeSampleRate(48000);
                    if (forceMono)
                    {
                        decoder.ToMono();
                    }

                    using (var encoder = MediaFoundationEncoder.CreateMP3Encoder(source.WaveFormat,
                                                                                 tempFile2))
                    {
                        var buffer = new byte[source.WaveFormat.BytesPerSecond];
                        int read;
                        while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            encoder.Write(buffer, 0, read);
                        }
                    }
#else
                    var tempFile2 = fileName;
#endif

                    try
                    {
                        var fileNameEncoded = EncodeParameterArgument(tempFile2);
                        App.Logger.Log($"- \"{fileNameEncoded}\"");
                        var result = Primrose.Utility.ExternalTool.Run(@"dandev-el3.exe", $"{fileNameEncoded} -o {tempFile}",
                                                                       out var stdout, out var stderr);

                        if (!string.IsNullOrEmpty(stderr))
                        {
                            App.Logger.LogError(stderr);
                        }

                        if (result == 0)
                        {
                            using (var nativeReader =
                                       new NativeReader(
                                           new FileStream(tempFile, FileMode.Open, FileAccess.Read)))
                            {
                                var end = nativeReader.ReadToEnd();

                                if (end.Length > 0 && end[0] == 0x48)
                                {
                                    var lines = stdout.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                                    foreach (var line in lines)
                                    {
                                        App.Logger.Log("> " + line);
                                    }

                                    var chunkSize =
                                        uint.Parse(lines.First(l => l.StartsWith("ChunkSize:")).Substring(10));
                                    var segmentLength =
                                        float.Parse(lines.First(l => l.StartsWith("SegmentLength:")).Substring(15));

                                    imports.Add(new SoundImport
                                    {
                                        SourceFile    = fileName,
                                        Chunk         = end,
                                        ChunkOffset   = totalChunkSize,
                                        ChunkSize     = chunkSize,
                                        SegmentLength = segmentLength
                                    });
                                    totalChunkSize += chunkSize;
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        App.Logger.LogError(e.Message);
                        App.Logger.LogError(e.StackTrace);
                    }
                    finally
                    {
                        try { File.Delete(tempFile); } catch (Exception) { /* ignored */ }
                        try { File.Delete(tempFile2); } catch (Exception) { /* ignored */ }
                    }
                }

                if (soundWave.Localization.Count > 0)
                {
                    var english = soundWave.Localization[0];

                    if (soundWave.Localization.Count > 1)
                    {
                        soundWave.Localization.RemoveRange(1, soundWave.Localization.Count - 1);
                    }

                    english.FirstVariationIndex = 0;
                    english.VariationCount      = (ushort)imports.Count;
                }

                soundWave.Segments.Clear();
                soundWave.RuntimeVariations.Clear();

                var combinedChunk = new byte[totalChunkSize];

                for (var i = 0; i < imports.Count; i++)
                {
                    var import = imports[i];

                    App.Logger.Log($"Import[{i}] - SampleOffset: {import.ChunkOffset} - SegmentLength: {import.SegmentLength} - SourceFile: {import.SourceFile}");

                    soundWave.Segments.Add(new SoundWaveVariationSegment
                    {
                        SamplesOffset   = import.ChunkOffset,
                        SeekTableOffset = uint.MaxValue,
                        SegmentLength   = import.SegmentLength,
                    });

                    soundWave.RuntimeVariations.Add(new SoundWaveRuntimeVariation
                    {
                        ChunkIndex            = chunkIndex,
                        FirstLoopSegmentIndex = 0,
                        FirstSegmentIndex     = (ushort)i,
                        LastLoopSegmentIndex  = 0,
                        PersistentDataSize    = 0,
                        SegmentCount          = 1,
                        Weight = 100,
                    });

                    Debug.Assert(import.ChunkSize == import.Chunk.Length);

                    Array.Copy(import.Chunk, 0, combinedChunk, (int)import.ChunkOffset, import.ChunkSize);
                }

                App.AssetManager.ModifyChunk(chunkEntry.Id, combinedChunk);

                chunk.ChunkSize = totalChunkSize;
                asset.Update();
                _app.Dispatcher.InvokeAsync(() =>
                {
                    App.AssetManager.ModifyEbx(_currentEditor.AssetEntry.Name, asset);
                });
            });

            FrostyTask2.End();
        }
Exemplo n.º 15
0
        private static unsafe bool TryGetNativeReaderForBlob(TypeManagerHandle module, ReflectionMapBlob blob, out NativeReader reader)
        {
            byte *pBlob;
            uint  cbBlob;

            if (RuntimeImports.RhFindBlob(module, (uint)blob, &pBlob, &cbBlob))
            {
                reader = new NativeReader(pBlob, cbBlob);
                return(true);
            }

            reader = default(NativeReader);
            return(false);
        }
Exemplo n.º 16
0
        internal bool GetCallingConverterDataFromMethodSignature_NativeLayout_Common(TypeSystemContext context, RuntimeSignature methodSig, Instantiation typeInstantiation, Instantiation methodInstantiation, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout, NativeReader nativeReader, ulong[] debuggerPreparedExternalReferences)
        {
            bool isNotDebuggerCall = nativeReader == null;

            hasThis    = false;
            parameters = null;

            NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext();

            nativeLayoutContext._module                = isNotDebuggerCall ? (NativeFormatModuleInfo)methodSig.GetModuleInfo() : null;
            nativeLayoutContext._typeSystemContext     = context;
            nativeLayoutContext._typeArgumentHandles   = typeInstantiation;
            nativeLayoutContext._methodArgumentHandles = methodInstantiation;
            nativeLayoutContext._debuggerPreparedExternalReferences = debuggerPreparedExternalReferences;

            NativeReader           reader = isNotDebuggerCall ? GetNativeLayoutInfoReader(methodSig) : nativeReader;
            NativeFormatModuleInfo module = isNotDebuggerCall ? ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(methodSig.ModuleHandle)) : null;
            NativeParser           parser = new NativeParser(reader, methodSig.NativeLayoutOffset);

            MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned();

            hasThis = !callingConvention.HasFlag(MethodCallingConvention.Static);

            uint numGenArgs = callingConvention.HasFlag(MethodCallingConvention.Generic) ? parser.GetUnsigned() : 0;

            uint parameterCount = parser.GetUnsigned();

            parameters = new TypeDesc[parameterCount + 1];
            parametersWithGenericDependentLayout = new bool[parameterCount + 1];

            // One extra parameter to account for the return type
            for (uint i = 0; i <= parameterCount; i++)
            {
                // NativeParser is a struct, so it can be copied.
                NativeParser parserCopy = parser;

                // Parse the signature twice. The first time to find out the exact type of the signature
                // The second time to identify if the parameter loaded via the signature should be forced to be
                // passed byref as part of the universal generic calling convention.
                parameters[i] = GetConstructedTypeFromParserAndNativeLayoutContext(ref parser, nativeLayoutContext);
                parametersWithGenericDependentLayout[i] = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parserCopy, module, context, HasVarsInvestigationLevel.Parameter);
                if (parameters[i] == null)
                {
                    return(false);
                }
            }

            return(true);
        }
 public static uint Read(this NativeReader reader, uint offset, out byte value)
 {
     value = reader.ReadUInt8(offset);
     return(offset + 1);
 }
Exemplo n.º 18
0
 static public uint Read(this NativeReader reader, uint offset, out string value)
 {
     return(reader.DecodeString(offset, out value));
 }
 public static uint Read(this NativeReader reader, uint offset, out float value)
 {
     value = reader.ReadFloat(offset);
     return(offset + 4);
 }
Exemplo n.º 20
0
 public UnwindInfo(byte[] image, int offset)
 {
     FunctionLength = NativeReader.DecodeUnsignedGc(image, ref offset);
     Size           = sizeof(int);
 }
Exemplo n.º 21
0
        private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
        {
            byte *pBlob;
            uint  cbBlob;

            if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
            {
                reader = new NativeReader(pBlob, cbBlob);
                return(true);
            }

            reader = default(NativeReader);
            return(false);
        }
        private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle instanceTypeHandle, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch, bool defaultMethods)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

#if GVM_RESOLUTION_TRACE
            Debug.WriteLine(" :: Declaring type = " + GetTypeNameDebug(declaringType));
            Debug.WriteLine(" :: Target type = " + GetTypeNameDebug(openTargetTypeHandle));
#endif

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = entryParser.GetUnsigned();

                MethodNameAndSignature targetMethodNameAndSignature = null;
                RuntimeTypeHandle      targetTypeHandle             = default;
                bool isDefaultInterfaceMethodImplementation;

                if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction)
                {
                    targetMethodNameAndSignature           = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken);
                    targetTypeHandle                       = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle);
#if GVM_RESOLUTION_TRACE
                    Debug.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
#endif
                }
                else
                {
                    isDefaultInterfaceMethodImplementation = true;
                }

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

#if GVM_RESOLUTION_TRACE
                    Debug.WriteLine("      -> Current implementing type = " + GetTypeNameDebug(implementingTypeHandle));
#endif

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle) ||
                        defaultMethods != isDefaultInterfaceMethodImplementation)
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                        {
                            entryParser.GetUnsigned();
                        }

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned());

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle))
                        {
#if GVM_RESOLUTION_TRACE
                            Debug.WriteLine("         -> Current interface on type = " + GetTypeNameDebug(currentIfaceTypeHandle));
#endif
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
#if GVM_RESOLUTION_TRACE
                                Debug.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
#endif
                                if (targetMethodNameAndSignature == null)
                                {
                                    if (nameAndSigToken == SpecialGVMInterfaceEntry.Diamond)
                                    {
                                        throw new AmbiguousImplementationException();
                                    }
                                    else
                                    {
                                        Debug.Assert(nameAndSigToken == SpecialGVMInterfaceEntry.Reabstraction);
                                        throw new EntryPointNotFoundException();
                                    }
                                }

                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                if (!RuntimeAugments.IsInterface(targetTypeHandle) || !RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle))
                                {
                                    // Not a default interface method or default interface method on a non-generic type.
                                    // We have a usable type handle.
                                    declaringType = targetTypeHandle;
                                }
                                else if (RuntimeAugments.IsGenericType(currentIfaceTypeHandle) && RuntimeAugments.GetGenericDefinition(currentIfaceTypeHandle).Equals(targetTypeHandle))
                                {
                                    // Default interface method implemented on the same type that declared the slot.
                                    // Use the instantiation as-is from what we found.
                                    declaringType = currentIfaceTypeHandle;
                                }
                                else
                                {
                                    declaringType = default;

                                    // Default interface method implemented on a different generic interface.
                                    // We need to find a usable instantiation. There should be only one match because we
                                    // would be dealing with a diamond otherwise.
                                    int numInstanceInterfaces = RuntimeAugments.GetInterfaceCount(instanceTypeHandle);
                                    for (int instIntfIndex = 0; instIntfIndex < numInstanceInterfaces; instIntfIndex++)
                                    {
                                        RuntimeTypeHandle instIntf = RuntimeAugments.GetInterface(instanceTypeHandle, instIntfIndex);
                                        if (RuntimeAugments.IsGenericType(instIntf) &&
                                            RuntimeAugments.GetGenericDefinition(instIntf).Equals(targetTypeHandle))
                                        {
                                            // Got a potential interface. Check if the implementing interface is in the interface
                                            // list. We don't want IsAssignableFrom because we need an exact match.
                                            int numIntInterfaces = RuntimeAugments.GetInterfaceCount(instIntf);
                                            for (int intIntfIndex = 0; intIntfIndex < numIntInterfaces; intIntfIndex++)
                                            {
                                                if (RuntimeAugments.GetInterface(instIntf, intIntfIndex).Equals(currentIfaceTypeHandle))
                                                {
                                                    Debug.Assert(declaringType.IsNull());
                                                    declaringType = instIntf;
#if !DEBUG
                                                    break;
#endif
                                                }
                                            }
#if !DEBUG
                                            if (!declaringType.IsNull())
                                            {
                                                break;
                                            }
#endif
                                        }
                                    }

                                    Debug.Assert(!declaringType.IsNull());
                                }

                                methodNameAndSignature = targetMethodNameAndSignature;
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 23
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/gcdump/i386/gcdumpx86.cpp">GCDump::DumpGCTable</a>
        /// </summary>
        private void GetTransitionsEbpFrame(byte[] image, ref int offset)
        {
            while (true)
            {
                uint argMask = 0, byrefArgMask = 0;
                uint regMask, byrefRegMask = 0;

                uint argCnt    = 0;
                int  argOffset = offset;
                uint argTabSize;

                uint val, nxt;
                uint curOffs = 0;

                // Get the next byte and check for a 'special' entry
                uint             encType    = image[offset++];
                GcTransitionCall transition = null;

                switch (encType)
                {
                default:
                    // A tiny or small call entry
                    val = encType;

                    if ((val & 0x80) == 0x00)
                    {
                        if ((val & 0x0F) != 0)
                        {
                            // A tiny call entry

                            curOffs += (val & 0x0F);
                            regMask  = (val & 0x70) >> 4;
                            argMask  = 0;
                        }
                        else
                        {
                            Registers reg;
                            if ((val & 0x10) != 0)
                            {
                                reg = Registers.EDI;
                            }
                            else if ((val & 0x20) != 0)
                            {
                                reg = Registers.ESI;
                            }
                            else if ((val & 0x40) != 0)
                            {
                                reg = Registers.EBX;
                            }
                            else
                            {
                                throw new BadImageFormatException("Invalid register");
                            }
                            transition = new GcTransitionCall((int)curOffs);
                            transition.CallRegisters.Add(new GcTransitionCall.CallRegister(reg, false));
                            AddNewTransition(transition);

                            continue;
                        }
                    }
                    else
                    {
                        // A small call entry
                        curOffs += (val & 0x7F);
                        val      = image[offset++];
                        regMask  = val >> 5;
                        argMask  = val & 0x1F;
                    }
                    break;

                case 0xFD:      // medium encoding
                    argMask  = image[offset++];
                    val      = image[offset++];
                    argMask |= (val & 0xF0) << 4;
                    nxt      = image[offset++];
                    curOffs += (val & 0x0F) + ((nxt & 0x1F) << 4);
                    regMask  = nxt >> 5;                      // EBX,ESI,EDI
                    break;

                case 0xF9:      // medium encoding with byrefs
                    curOffs     += image[offset++];
                    val          = image[offset++];
                    argMask      = val & 0x1F;
                    regMask      = val >> 5;
                    val          = image[offset++];
                    byrefArgMask = val & 0x1F;
                    byrefRegMask = val >> 5;
                    break;

                case 0xFE:      // large encoding
                case 0xFA:      // large encoding with byrefs
                    val          = image[offset++];
                    regMask      = val & 0x7;
                    byrefRegMask = val >> 4;

                    curOffs += NativeReader.ReadUInt32(image, ref offset);
                    argMask  = NativeReader.ReadUInt32(image, ref offset);
                    if (encType == 0xFA)     // read byrefArgMask
                    {
                        byrefArgMask = NativeReader.ReadUInt32(image, ref offset);
                    }
                    break;

                case 0xFB:      // huge encoding
                    val          = image[offset++];
                    regMask      = val & 0x7;
                    byrefRegMask = val >> 4;
                    curOffs      = NativeReader.ReadUInt32(image, ref offset);
                    argCnt       = NativeReader.ReadUInt32(image, ref offset);
                    argTabSize   = NativeReader.ReadUInt32(image, ref offset);
                    argOffset    = offset;
                    offset      += (int)argTabSize;
                    break;

                case 0xFF:
                    return;
                }

                /*
                 *  Here we have the following values:
                 *
                 *  curOffs      ...    the code offset of the call
                 *  regMask      ...    mask of live pointer register variables
                 *  argMask      ...    bitmask of pushed pointer arguments
                 *  byrefRegMask ...    byref qualifier for regMask
                 *  byrefArgMask ...    byrer qualifier for argMask
                 */
                transition = new GcTransitionCall((int)curOffs, Header.EbpFrame, regMask, byrefRegMask);
                AddNewTransition(transition);

                if (argCnt != 0)
                {
                    do
                    {
                        val = NativeReader.DecodeUnsignedGc(image, ref argOffset);

                        uint stkOffs = val & ~byref_OFFSET_FLAG;
                        uint lowBit  = val & byref_OFFSET_FLAG;
                        transition.PtrArgs.Add(new GcTransitionCall.PtrArg(stkOffs, lowBit));
                    }while (--argCnt > 0);
                }
                else
                {
                    transition.ArgMask = argMask;
                    if (byrefArgMask != 0)
                    {
                        transition.IArgs = byrefArgMask;
                    }
                }
            }
        }
Exemplo n.º 24
0
        private InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = null;
            nativeLayoutInfoToken  = 0;
            var canonForm = concreteMethod.GetCanonMethodTarget(kind);
            var hashCode  = canonForm.GetHashCode();

            foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules())
            {
                NativeReader nativeLayoutReader = TypeLoaderEnvironment.Instance.GetNativeLayoutInfoReader(moduleInfo.Handle);
                if (nativeLayoutReader == null)
                {
                    continue;
                }

                NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out _);

                if (genericMethodTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var context = new NativeLayoutInfoLoadContext
                {
                    _typeSystemContext     = concreteMethod.Context,
                    _typeArgumentHandles   = concreteMethod.OwningType.Instantiation,
                    _methodArgumentHandles = concreteMethod.Instantiation,
                    _module = moduleInfo
                };

                var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var methodSignatureParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned());

                    // Get the unified generic method holder and convert it to its canonical form
                    var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser);
                    Debug.Assert(candidateTemplate.Instantiation.Length > 0);

                    if (canonForm == candidateTemplate.GetCanonMethodTarget(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoModule = moduleInfo;
                        nativeLayoutInfoToken  = entryParser.GetUnsigned();
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind)));

                        return(candidateTemplate);
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString());
            return(null);
        }
Exemplo n.º 25
0
        private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetExternalNativeLayoutOffset(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken);
                RuntimeTypeHandle      targetTypeHandle             = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

#if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
#endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                        {
                            entryParser.GetUnsigned();
                        }

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetExternalNativeLayoutOffset(entryParser.GetUnsigned()));

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
#if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
#endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType          = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 26
0
        private unsafe static void NewParameterizedArray(byte *parameterBuffer, uint parameterBufferSize)
        {
            uint         offset = 0;
            NativeReader reader = new NativeReader(parameterBuffer, parameterBufferSize);

            ulong[] debuggerPreparedExternalReferences;
            offset = BuildDebuggerPreparedExternalReferences(reader, offset, out debuggerPreparedExternalReferences);

            NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext();
            TypeSystemContext           typeSystemContext   = TypeSystemContextFactory.Create();

            nativeLayoutContext._module                = null;
            nativeLayoutContext._typeSystemContext     = typeSystemContext;
            nativeLayoutContext._typeArgumentHandles   = Instantiation.Empty;
            nativeLayoutContext._methodArgumentHandles = Instantiation.Empty;
            nativeLayoutContext._debuggerPreparedExternalReferences = debuggerPreparedExternalReferences;

            NativeParser parser         = new NativeParser(reader, offset);
            TypeDesc     arrElementType = TypeLoaderEnvironment.Instance.GetConstructedTypeFromParserAndNativeLayoutContext(ref parser, nativeLayoutContext);

            TypeSystemContextFactory.Recycle(typeSystemContext);

            uint rank = parser.GetUnsigned();

            int[] dims        = new int[rank];
            int[] lowerBounds = new int[rank];

            for (uint i = 0; i < rank; ++i)
            {
                dims[i] = (int)parser.GetUnsigned();
            }

            for (uint i = 0; i < rank; ++i)
            {
                lowerBounds[i] = (int)parser.GetUnsigned();
            }

            RuntimeTypeHandle typeHandle      = arrElementType.GetRuntimeTypeHandle();
            RuntimeTypeHandle arrayTypeHandle = default(RuntimeTypeHandle);
            Array             returnValue;
            // Get an array RuntimeTypeHandle given an element's RuntimeTypeHandle and rank.
            // Pass false for isMdArray, and rank == -1 for SzArrays
            bool succeed = false;

            if (rank == 1 && lowerBounds[0] == 0)
            {
                succeed = TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType(
                    typeHandle,
                    false,
                    -1,
                    out arrayTypeHandle);
                Debug.Assert(succeed);

                returnValue = Internal.Runtime.Augments.RuntimeAugments.NewArray(
                    arrayTypeHandle,
                    dims[0]);
            }
            else
            {
                succeed = TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType(
                    typeHandle,
                    true,
                    (int)rank,
                    out arrayTypeHandle
                    );
                Debug.Assert(succeed);
                returnValue = Internal.Runtime.Augments.RuntimeAugments.NewMultiDimArray(
                    arrayTypeHandle,
                    dims,
                    lowerBounds
                    );
            }
            GCHandle returnValueHandle        = GCHandle.Alloc(returnValue);
            IntPtr   returnValueHandlePointer = GCHandle.ToIntPtr(returnValueHandle);
            uint     returnHandleIdentifier   = RuntimeAugments.RhpRecordDebuggeeInitiatedHandle(returnValueHandlePointer);

            ReturnToDebuggerWithReturn(returnHandleIdentifier, returnValueHandlePointer, false);
        }
Exemplo n.º 27
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::GcInfoDecoder</a>
        /// </summary>
        public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion)
        {
            Offset       = offset;
            _gcInfoTypes = new GcInfoTypes(machine);
            _machine     = machine;

            SecurityObjectStackSlot            = -1;
            GSCookieStackSlot                  = -1;
            PSPSymStackSlot                    = -1;
            SecurityObjectStackSlot            = -1;
            GenericsInstContextStackSlot       = -1;
            StackBaseRegister                  = 0xffffffff;
            SizeOfEditAndContinuePreservedArea = 0xffffffff;
            ReversePInvokeFrameStackSlot       = -1;

            Version = ReadyToRunVersionToGcInfoVersion(majorVersion);
            int bitOffset      = offset * 8;
            int startBitOffset = bitOffset;

            ParseHeaderFlags(image, ref bitOffset);

            if (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND) // IsReturnKindAvailable
            {
                int returnKindBits = (_slimHeader) ? _gcInfoTypes.SIZE_OF_RETURN_KIND_SLIM : _gcInfoTypes.SIZE_OF_RETURN_KIND_FAT;
                ReturnKind = (ReturnKinds)NativeReader.ReadBits(image, returnKindBits, ref bitOffset);
            }

            CodeLength = _gcInfoTypes.DenormalizeCodeLength((int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.CODE_LENGTH_ENCBASE, ref bitOffset));

            if (_hasGSCookie)
            {
                uint normPrologSize = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1;
                uint normEpilogSize = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_EPILOG_SIZE_ENCBASE, ref bitOffset);

                ValidRangeStart = normPrologSize;
                ValidRangeEnd   = (uint)CodeLength - normEpilogSize;
            }
            else if (_hasSecurityObject || _hasGenericsInstContext)
            {
                ValidRangeStart = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1;
                ValidRangeEnd   = ValidRangeStart + 1;
            }

            if (_hasSecurityObject)
            {
                SecurityObjectStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.SECURITY_OBJECT_STACK_SLOT_ENCBASE, ref bitOffset));
            }

            if (_hasGSCookie)
            {
                GSCookieStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.GS_COOKIE_STACK_SLOT_ENCBASE, ref bitOffset));
            }

            if (_hasPSPSym)
            {
                PSPSymStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.PSP_SYM_STACK_SLOT_ENCBASE, ref bitOffset));
            }

            if (_hasGenericsInstContext)
            {
                GenericsInstContextStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, ref bitOffset));
            }

            if (_hasStackBaseRegister && !_slimHeader)
            {
                StackBaseRegister = _gcInfoTypes.DenormalizeStackBaseRegister(NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.STACK_BASE_REGISTER_ENCBASE, ref bitOffset));
            }

            if (_hasSizeOfEditAndContinuePreservedArea)
            {
                SizeOfEditAndContinuePreservedArea = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, ref bitOffset);
            }

            if (_hasReversePInvokeFrame)
            {
                ReversePInvokeFrameStackSlot = NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.REVERSE_PINVOKE_FRAME_ENCBASE, ref bitOffset);
            }

            // FIXED_STACK_PARAMETER_SCRATCH_AREA (this macro is always defined in _gcInfoTypes.h)
            if (!_slimHeader)
            {
                SizeOfStackOutgoingAndScratchArea = _gcInfoTypes.DenormalizeSizeOfStackArea(NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.SIZE_OF_STACK_AREA_ENCBASE, ref bitOffset));
            }

            // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in _gcInfoTypes.h)
            NumSafePoints = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NUM_SAFE_POINTS_ENCBASE, ref bitOffset);

            if (!_slimHeader)
            {
                NumInterruptibleRanges = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NUM_INTERRUPTIBLE_RANGES_ENCBASE, ref bitOffset);
            }

            // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in _gcInfoTypes.h)
            SafePointOffsets = EnumerateSafePoints(image, ref bitOffset);

            InterruptibleRanges = EnumerateInterruptibleRanges(image, _gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA1_ENCBASE, _gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA2_ENCBASE, ref bitOffset);

            SlotTable = new GcSlotTable(image, machine, _gcInfoTypes, ref bitOffset);

            // Try partially interruptible first
            if (NumSafePoints > 0)
            {
                LiveSlotsAtSafepoints = GetLiveSlotsAtSafepoints(image, ref bitOffset);
            }
            else
            {
                Transitions = GetTransitions(image, ref bitOffset);
            }

            Size = bitOffset - startBitOffset;
        }
 public static uint Read(this NativeReader reader, uint offset, out double value)
 {
     value = reader.ReadDouble(offset);
     return(offset + 8);
 }
Exemplo n.º 29
0
        /// <summary>
        /// based on end of <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::EnumerateLiveSlots and GcInfoEncoder::Build</a>
        /// </summary>
        public Dictionary <int, List <BaseGcTransition> > GetTransitions(byte[] image, ref int bitOffset)
        {
            int totalInterruptibleLength = 0;

            if (NumInterruptibleRanges == 0)
            {
                totalInterruptibleLength = CodeLength;
            }
            else
            {
                foreach (InterruptibleRange range in InterruptibleRanges)
                {
                    totalInterruptibleLength += (int)(range.StopOffset - range.StartOffset);
                }
            }

            int numChunks         = (totalInterruptibleLength + _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK;
            int numBitsPerPointer = (int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.POINTER_SIZE_ENCBASE, ref bitOffset);

            if (numBitsPerPointer == 0)
            {
                return(new Dictionary <int, List <BaseGcTransition> >());
            }

            // get offsets of each chunk
            int[] chunkPointers = new int[numChunks];
            for (int i = 0; i < numChunks; i++)
            {
                chunkPointers[i] = NativeReader.ReadBits(image, numBitsPerPointer, ref bitOffset);
            }

            // Offset to m_Info2 containing all the info on register liveness
            int info2Offset = (int)Math.Ceiling(bitOffset / 8.0) * 8;

            List <GcTransition> transitions = new List <GcTransition>();

            bool[] liveAtEnd = new bool[SlotTable.NumTracked]; // true if slot is live at the end of the chunk
            for (int currentChunk = 0; currentChunk < numChunks; currentChunk++)
            {
                if (chunkPointers[currentChunk] == 0)
                {
                    continue;
                }
                else
                {
                    bitOffset = info2Offset + chunkPointers[currentChunk] - 1;
                }

                int  couldBeLiveOffset = bitOffset; // points to the couldBeLive bit array (array of bits indicating the slot changed state in the chunk)
                int  slotId            = 0;
                bool fSimple           = (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0);
                bool fSkipFirst        = false;
                int  couldBeLiveCnt    = 0;
                if (!fSimple)
                {
                    fSkipFirst = (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0);
                    slotId     = -1;
                }

                uint numCouldBeLiveSlots = GetNumCouldBeLiveSlots(image, ref bitOffset);                   // count the number of set bits in the couldBeLive array

                int finalStateOffset = bitOffset;                                                          // points to the finalState bit array (array of bits indicating if the slot is live at the end of the chunk)
                bitOffset += (int)numCouldBeLiveSlots;                                                     // points to the array of code offsets

                int normChunkBaseCodeOffset = currentChunk * _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK; // the sum of the sizes of all preceeding chunks
                for (int i = 0; i < numCouldBeLiveSlots; i++)
                {
                    // get the index of the next couldBeLive slot
                    slotId = GetNextSlotId(image, fSimple, fSkipFirst, slotId, ref couldBeLiveCnt, ref couldBeLiveOffset);

                    // set the liveAtEnd for the slot at slotId
                    bool isLive = !liveAtEnd[slotId];
                    liveAtEnd[slotId] = (NativeReader.ReadBits(image, 1, ref finalStateOffset) != 0);

                    // Read all the code offsets where the slot at slotId changed state
                    while (NativeReader.ReadBits(image, 1, ref bitOffset) != 0)
                    {
                        int transitionOffset = NativeReader.ReadBits(image, _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2, ref bitOffset) + normChunkBaseCodeOffset;
                        transitions.Add(new GcTransition(transitionOffset, slotId, isLive, currentChunk, SlotTable, _machine));
                        isLive = !isLive;
                    }
                    slotId++;
                }
            }

            // convert normCodeOffsetDelta to the actual CodeOffset
            transitions.Sort((s1, s2) => s1.CodeOffset.CompareTo(s2.CodeOffset));
            return(UpdateTransitionCodeOffset(transitions));
        }
 public static uint Read(this NativeReader reader, uint offset, out bool value)
 {
     value = (reader.ReadUInt8(offset) != 0) ? true : false;
     return(offset + 1);
 }
Exemplo n.º 31
0
        /// <summary>
        /// Unwinde code parsing is based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
        /// </summary>
        public UnwindCode(byte[] image, ref int frameOffset, ref int offset)
        {
            CodeOffset = NativeReader.ReadByte(image, ref offset);
            byte op = NativeReader.ReadByte(image, ref offset);

            UnwindOp = (UnwindOpCodes)(op & 15);
            OpInfo   = (byte)(op >> 4);

            OffsetLow  = CodeOffset;
            OffsetHigh = OpInfo;

            FrameOffset = frameOffset;

            switch (UnwindOp)
            {
            case UnwindOpCodes.UWOP_PUSH_NONVOL:
                OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
                break;

            case UnwindOpCodes.UWOP_ALLOC_LARGE:
                OpInfoStr = $"{OpInfo} - ";
                if (OpInfo == 0)
                {
                    OpInfoStr      += "Scaled small";
                    NextFrameOffset = 8 * NativeReader.ReadUInt16(image, ref offset);
                }
                else if (OpInfo == 1)
                {
                    OpInfoStr += "Unscaled large";
                    uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                    NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
                }
                else
                {
                    throw new BadImageFormatException();
                }
                break;

            case UnwindOpCodes.UWOP_ALLOC_SMALL:
                int opInfo = OpInfo * 8 + 8;
                OpInfoStr = $"{opInfo}";
                break;

            case UnwindOpCodes.UWOP_SET_FPREG:
                OpInfoStr = $"Unused({OpInfo})";
                break;

            case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
            {
                OpInfoStr = $"Unused({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                nextOffset      = ((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
                NextFrameOffset = (int)nextOffset * 16;
                if ((NextFrameOffset & 0xF0000000) != 0)
                {
                    throw new BadImageFormatException("Warning: Illegal unwindInfo unscaled offset: too large");
                }
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL:
            {
                OpInfoStr       = $"{(Registers)OpInfo}({OpInfo})";
                NextFrameOffset = NativeReader.ReadUInt16(image, ref offset) * 8;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
            {
                OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128:
            {
                OpInfoStr       = $"XMM{OpInfo}({OpInfo})";
                NextFrameOffset = (int)NativeReader.ReadUInt16(image, ref offset) * 16;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
            {
                OpInfoStr = $"XMM{OpInfo}({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
            }
            break;

            default:
                throw new NotImplementedException(UnwindOp.ToString());
            }

            NextFrameOffset = frameOffset;
        }
 public static uint Read(this NativeReader reader, uint offset, out uint value)
 {
     return(reader.DecodeUnsigned(offset, out value));
 }