예제 #1
0
        public void ReadDynamicTable(JumpTable jumpTable)
        {
            if (JumpTable.DynamicTableElems > 1)
            {
                throw new NotSupportedException();
            }

            _dynamicTable.Clear();

            for (int entry = 1; entry <= jumpTable.DynTableEnd; entry++)
            {
                IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry);

                long guestAddress = Marshal.ReadInt64(addr, 0);
                long hostAddress  = Marshal.ReadInt64(addr, 8);

                IndirectHostAddress indirectHostAddress;

                if (hostAddress == DirectCallStubs.IndirectCallStub(false).ToInt64())
                {
                    indirectHostAddress = IndirectHostAddress.CallStub;
                }
                else if (hostAddress == DirectCallStubs.IndirectCallStub(true).ToInt64())
                {
                    indirectHostAddress = IndirectHostAddress.TailCallStub;
                }
                else
                {
                    throw new InvalidOperationException($"({nameof(hostAddress)} = 0x{hostAddress:X16})");
                }

                _dynamicTable.Add(new KeyValuePair <long, IndirectHostAddress>(guestAddress, indirectHostAddress));
            }
        }
    public void Setup()
    {
        _strings  = GetStrings(100);
        _segments = new PathSegment[100];

        for (var i = 0; i < _strings.Length; i++)
        {
            _segments[i] = new PathSegment(0, _strings[i].Length);
        }

        var samples = new int[Count];

        for (var i = 0; i < samples.Length; i++)
        {
            samples[i] = i * (_strings.Length / Count);
        }

        var entries = new List <(string text, int _)>();

        for (var i = 0; i < samples.Length; i++)
        {
            entries.Add((_strings[samples[i]], i));
        }

        _linearSearch = new LinearSearchJumpTable(0, -1, entries.ToArray());
        _dictionary   = new DictionaryJumpTable(0, -1, entries.ToArray());
        _trie         = new ILEmitTrieJumpTable(0, -1, entries.ToArray(), vectorize: false, _dictionary);
        _vectorTrie   = new ILEmitTrieJumpTable(0, -1, entries.ToArray(), vectorize: true, _dictionary);
    }
예제 #3
0
        public void ReadJumpTable(JumpTable jumpTable)
        {
            _jumpTable.Clear();

            for (int entry = 1; entry <= jumpTable.TableEnd; entry++)
            {
                IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry);

                long guestAddress = Marshal.ReadInt64(addr, 0);
                long hostAddress  = Marshal.ReadInt64(addr, 8);

                DirectHostAddress directHostAddress;

                if (hostAddress == DirectCallStubs.DirectCallStub(false).ToInt64())
                {
                    directHostAddress = DirectHostAddress.CallStub;
                }
                else if (hostAddress == DirectCallStubs.DirectCallStub(true).ToInt64())
                {
                    directHostAddress = DirectHostAddress.TailCallStub;
                }
                else
                {
                    directHostAddress = DirectHostAddress.Host;
                }

                _jumpTable.Add(new KeyValuePair <long, DirectHostAddress>(guestAddress, directHostAddress));
            }
        }
예제 #4
0
파일: ResourceFork.cs 프로젝트: heruix/reko
        /// <summary>
        /// Builds the MacOS A5World, based on the contents of the jump table in CODE#0.
        /// </summary>
        /// <param name="jt"></param>
        /// <param name="addr"></param>
        /// <param name="codeSegs"></param>
        /// <returns></returns>
        public ImageSegment LoadA5World(
            JumpTable jt,
            Address addr,
            Dictionary <int, ImageSegment> codeSegs,
            SortedList <Address, ImageSymbol> symbols)
        {
            var size = jt.BelowA5Size + jt.AboveA5Size;
            var mem  = new MemoryArea(addr, new byte[size]);
            var w    = new BeImageWriter(mem, jt.BelowA5Size + jt.JumpTableOffset);
            int i    = 0;

            foreach (var entry in jt.Entries)
            {
                w.WriteBeUInt16(entry.RoutineOffsetFromSegmentStart);
                int iSeg      = (ushort)entry.Instruction;
                var targetSeg = codeSegs[iSeg];
                var addrDst   = targetSeg.Address + entry.RoutineOffsetFromSegmentStart;
                if (!symbols.ContainsKey(addrDst))
                {
                    symbols.Add(addrDst, ImageSymbol.Procedure(arch, addrDst));
                }
                w.WriteBeUInt16(0x4EF9);            // jmp (xxxxxxxxx).L
                w.WriteBeUInt32(addrDst.ToUInt32());
                ++i;
            }
            return(new ImageSegment("A5World", mem, AccessMode.ReadWriteExecute));
        }
예제 #5
0
        public void ReadJumpTable(JumpTable jumpTable)
        {
            // Reads in-memory jump table state and store internally for PtcJumpTable serialization.

            _jumpTable.Clear();

            IEnumerable <int> entries = jumpTable.Table.GetEntries();

            foreach (int entry in entries)
            {
                IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry);

                long guestAddress = Marshal.ReadInt64(addr, 0);
                long hostAddress  = Marshal.ReadInt64(addr, 8);

                DirectHostAddress directHostAddress;

                if (hostAddress == DirectCallStubs.DirectCallStub(false).ToInt64())
                {
                    directHostAddress = DirectHostAddress.CallStub;
                }
                else if (hostAddress == DirectCallStubs.DirectCallStub(true).ToInt64())
                {
                    directHostAddress = DirectHostAddress.TailCallStub;
                }
                else
                {
                    directHostAddress = DirectHostAddress.Host;
                }

                _jumpTable.Add(new TableEntry <DirectHostAddress>(entry, guestAddress, directHostAddress));
            }
        }
예제 #6
0
            public void Deconstruct(out Instruction[] instructions, out Endpoint[] endpoints, out JumpTable[] tables)
            {
                instructions = _instructions.ToArray();
                endpoints    = _endpoints.ToArray();

                tables = new JumpTable[_tables.Count];
                for (var i = 0; i < _tables.Count; i++)
                {
                    tables[i] = _tables[i].Build();
                }
            }
예제 #7
0
 public DfaState(
     Candidate[] candidates,
     IEndpointSelectorPolicy[] policies,
     JumpTable pathTransitions,
     PolicyJumpTable policyTransitions)
 {
     Candidates        = candidates;
     Policies          = policies;
     PathTransitions   = pathTransitions;
     PolicyTransitions = policyTransitions;
 }
예제 #8
0
        public void WriteJumpTable(JumpTable jumpTable, ConcurrentDictionary <ulong, TranslatedFunction> funcs)
        {
            // Writes internal state to jump table in-memory, after PtcJumpTable was deserialized.

            foreach (var tableEntry in _jumpTable)
            {
                long guestAddress = tableEntry.GuestAddress;
                DirectHostAddress directHostAddress = tableEntry.HostAddress;

                long hostAddress;

                if (directHostAddress == DirectHostAddress.CallStub)
                {
                    hostAddress = DirectCallStubs.DirectCallStub(false).ToInt64();
                }
                else if (directHostAddress == DirectHostAddress.TailCallStub)
                {
                    hostAddress = DirectCallStubs.DirectCallStub(true).ToInt64();
                }
                else if (directHostAddress == DirectHostAddress.Host)
                {
                    if (funcs.TryGetValue((ulong)guestAddress, out TranslatedFunction func))
                    {
                        hostAddress = func.FuncPtr.ToInt64();
                    }
                    else
                    {
                        if (!PtcProfiler.ProfiledFuncs.TryGetValue((ulong)guestAddress, out var value) || !value.HighCq)
                        {
                            throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})");
                        }

                        hostAddress = 0L;
                    }
                }
                else
                {
                    throw new InvalidOperationException(nameof(directHostAddress));
                }

                int entry = tableEntry.EntryIndex;

                jumpTable.Table.SetEntry(entry);
                jumpTable.ExpandIfNeededJumpTable(entry);

                IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry);

                Marshal.WriteInt64(addr, 0, guestAddress);
                Marshal.WriteInt64(addr, 8, hostAddress);
            }
        }
예제 #9
0
        public void Initialize(JumpTable jumpTable)
        {
            _targets.Clear();

            foreach (ulong guestAddress in jumpTable.Targets.Keys)
            {
                _targets.Add(guestAddress);
            }

            _dependants.Clear();

            foreach (var item in jumpTable.Dependants)
            {
                _dependants.Add(item.Key, new LinkedList <int>(item.Value));
            }
        }
        public string parse_c_instruction(string instruction)
        {
            string c_instruction_bin;
            string dest = "000";
            string comp = "00000000";
            string jump = "000";
            Symbol Match;
            int    index;

            index = instruction.IndexOf('=');
            if (index > 0)
            {
                jump  = "000";
                dest  = instruction.Substring(0, index);
                Match = DestTable.FirstOrDefault(i => i.Name == dest);
                if (Match != null)
                {
                    dest = Match.Value;
                }
                comp  = instruction.Substring(index + 1, instruction.Length - index - 1);
                Match = CompTable.FirstOrDefault(i => i.Name == comp);
                if (Match != null)
                {
                    comp = Match.Value;
                }
            }
            index = instruction.IndexOf(';');
            if (index > 0)
            {
                dest  = "000";
                comp  = instruction.Substring(0, index);
                Match = CompTable.FirstOrDefault(i => i.Name == comp);
                if (Match != null)
                {
                    comp = Match.Value;
                }
                jump  = instruction.Substring(index + 1, instruction.Length - index - 1);
                Match = JumpTable.FirstOrDefault(i => i.Name == jump);
                if (Match != null)
                {
                    jump = Match.Value;
                }
            }
            c_instruction_bin = "11" + comp + dest + jump;
            return(c_instruction_bin);
        }
예제 #11
0
        public void WriteJumpTable(JumpTable jumpTable, ConcurrentDictionary <ulong, TranslatedFunction> funcs)
        {
            jumpTable.ExpandIfNeededJumpTable(TableEnd);

            int entry = 0;

            foreach (var item in _jumpTable)
            {
                entry += 1;

                long guestAddress = item.Key;
                DirectHostAddress directHostAddress = item.Value;

                long hostAddress;

                if (directHostAddress == DirectHostAddress.CallStub)
                {
                    hostAddress = DirectCallStubs.DirectCallStub(false).ToInt64();
                }
                else if (directHostAddress == DirectHostAddress.TailCallStub)
                {
                    hostAddress = DirectCallStubs.DirectCallStub(true).ToInt64();
                }
                else if (directHostAddress == DirectHostAddress.Host)
                {
                    if (funcs.TryGetValue((ulong)guestAddress, out TranslatedFunction func))
                    {
                        hostAddress = func.FuncPtr.ToInt64();
                    }
                    else
                    {
                        throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})");
                    }
                }
                else
                {
                    throw new InvalidOperationException(nameof(directHostAddress));
                }

                IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry);

                Marshal.WriteInt64(addr, 0, guestAddress);
                Marshal.WriteInt64(addr, 8, hostAddress);
            }
        }
예제 #12
0
파일: Ptc.cs 프로젝트: historria/Ryujinx
        private static void PatchCode(
            Span <byte> code,
            RelocEntry[] relocEntries,
            IntPtr pageTablePointer,
            JumpTable jumpTable,
            EntryTable <uint> countTable,
            out Counter <uint> callCounter)
        {
            callCounter = null;

            foreach (RelocEntry relocEntry in relocEntries)
            {
                ulong imm;

                if (relocEntry.Index == PageTablePointerIndex)
                {
                    imm = (ulong)pageTablePointer.ToInt64();
                }
                else if (relocEntry.Index == JumpPointerIndex)
                {
                    imm = (ulong)jumpTable.JumpPointer.ToInt64();
                }
                else if (relocEntry.Index == DynamicPointerIndex)
                {
                    imm = (ulong)jumpTable.DynamicPointer.ToInt64();
                }
                else if (relocEntry.Index == CountTableIndex)
                {
                    callCounter = new Counter <uint>(countTable);

                    unsafe { imm = (ulong)Unsafe.AsPointer(ref callCounter.Value); }
                }
                else if (Delegates.TryGetDelegateFuncPtrByIndex(relocEntry.Index, out IntPtr funcPtr))
                {
                    imm = (ulong)funcPtr.ToInt64();
                }
                else
                {
                    throw new Exception($"Unexpected reloc entry {relocEntry}.");
                }

                BinaryPrimitives.WriteUInt64LittleEndian(code.Slice(relocEntry.Position, 8), imm);
            }
        }
 public void Setup()
 {
     _table   = new ZeroEntryJumpTable(0, -1);
     _strings = new string[]
     {
         "index/foo/2",
         "index/hello-world1/2",
         "index/hello-world/2",
         "index//2",
         "index/hillo-goodbye/2",
     };
     _segments = new PathSegment[]
     {
         new PathSegment(6, 3),
         new PathSegment(6, 12),
         new PathSegment(6, 11),
         new PathSegment(6, 0),
         new PathSegment(6, 13),
     };
 }
예제 #14
0
        private void ProcessJumpTable(uint jtOffset)
        {
            var         j  = new JumpTable();
            ImageReader ir = new BeImageReader(image, jtOffset);

            j.AboveA5Size     = ir.ReadBeUInt32();
            j.BelowA5Size     = ir.ReadBeUInt32();
            j.JumpTableSize   = ir.ReadBeUInt32();
            j.JumpTableOffset = ir.ReadBeUInt32();
            uint size = j.JumpTableSize;

            while (size > 0)
            {
                JumpTableEntry jte = new JumpTableEntry();
                jte.RoutineOffsetFromSegmentStart = ir.ReadBeUInt16();
                jte.Instruction       = ir.ReadBeUInt32();
                jte.LoadSegTrapNumber = ir.ReadBeUInt16();
                Debug.WriteLine(string.Format("Jump table entry: {0:x2} {1:X4} {2:X2}", jte.RoutineOffsetFromSegmentStart, jte.Instruction, jte.LoadSegTrapNumber));
                size -= 8;
            }
        }
예제 #15
0
        public void WriteDynamicTable(JumpTable jumpTable)
        {
            // Writes internal state to jump table in-memory, after PtcJumpTable was deserialized.

            if (JumpTable.DynamicTableElems > 1)
            {
                throw new NotSupportedException();
            }

            foreach (var tableEntry in _dynamicTable)
            {
                long guestAddress = tableEntry.GuestAddress;
                IndirectHostAddress indirectHostAddress = tableEntry.HostAddress;

                long hostAddress;

                if (indirectHostAddress == IndirectHostAddress.CallStub)
                {
                    hostAddress = DirectCallStubs.IndirectCallStub(false).ToInt64();
                }
                else if (indirectHostAddress == IndirectHostAddress.TailCallStub)
                {
                    hostAddress = DirectCallStubs.IndirectCallStub(true).ToInt64();
                }
                else
                {
                    throw new InvalidOperationException(nameof(indirectHostAddress));
                }

                int entry = tableEntry.EntryIndex;

                jumpTable.DynTable.SetEntry(entry);
                jumpTable.ExpandIfNeededDynamicTable(entry);

                IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry);

                Marshal.WriteInt64(addr, 0, guestAddress);
                Marshal.WriteInt64(addr, 8, hostAddress);
            }
        }
예제 #16
0
        public void WriteDynamicTable(JumpTable jumpTable)
        {
            if (JumpTable.DynamicTableElems > 1)
            {
                throw new NotSupportedException();
            }

            jumpTable.ExpandIfNeededDynamicTable(DynTableEnd);

            int entry = 0;

            foreach (var item in _dynamicTable)
            {
                entry += 1;

                long guestAddress = item.Key;
                IndirectHostAddress indirectHostAddress = item.Value;

                long hostAddress;

                if (indirectHostAddress == IndirectHostAddress.CallStub)
                {
                    hostAddress = DirectCallStubs.IndirectCallStub(false).ToInt64();
                }
                else if (indirectHostAddress == IndirectHostAddress.TailCallStub)
                {
                    hostAddress = DirectCallStubs.IndirectCallStub(true).ToInt64();
                }
                else
                {
                    throw new InvalidOperationException(nameof(indirectHostAddress));
                }

                IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry);

                Marshal.WriteInt64(addr, 0, guestAddress);
                Marshal.WriteInt64(addr, 8, hostAddress);
            }
        }
예제 #17
0
        public void ReadDynamicTable(JumpTable jumpTable)
        {
            // Reads in-memory jump table state and store internally for PtcJumpTable serialization.

            if (JumpTable.DynamicTableElems > 1)
            {
                throw new NotSupportedException();
            }

            _dynamicTable.Clear();

            IEnumerable <int> entries = jumpTable.DynTable.GetEntries();

            foreach (int entry in entries)
            {
                IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry);

                long guestAddress = Marshal.ReadInt64(addr, 0);
                long hostAddress  = Marshal.ReadInt64(addr, 8);

                IndirectHostAddress indirectHostAddress;

                if (hostAddress == DirectCallStubs.IndirectCallStub(false).ToInt64())
                {
                    indirectHostAddress = IndirectHostAddress.CallStub;
                }
                else if (hostAddress == DirectCallStubs.IndirectCallStub(true).ToInt64())
                {
                    indirectHostAddress = IndirectHostAddress.TailCallStub;
                }
                else
                {
                    throw new InvalidOperationException($"({nameof(hostAddress)} = 0x{hostAddress:X16})");
                }

                _dynamicTable.Add(new TableEntry <IndirectHostAddress>(entry, guestAddress, indirectHostAddress));
            }
        }
예제 #18
0
        public void Initialize(JumpTable jumpTable)
        {
            Targets.Clear();

            foreach (ulong guestAddress in jumpTable.Targets.Keys)
            {
                Targets.Add(guestAddress);
            }

            Dependants.Clear();

            foreach (var kv in jumpTable.Dependants)
            {
                Dependants.Add(kv.Key, new List <int>(kv.Value));
            }

            Owners.Clear();

            foreach (var kv in jumpTable.Owners)
            {
                Owners.Add(kv.Key, new List <int>(kv.Value));
            }
        }
예제 #19
0
파일: ResourceFork.cs 프로젝트: heruix/reko
        private JumpTable ProcessJumpTable(MemoryArea memJt, IDictionary <Address, ImageSymbol> symbols)
        {
            var j  = new JumpTable();
            var ir = memJt.CreateBeReader(0);

            j.AboveA5Size     = ir.ReadBeUInt32();
            j.BelowA5Size     = ir.ReadBeUInt32();
            j.JumpTableSize   = ir.ReadBeUInt32();
            j.JumpTableOffset = ir.ReadBeUInt32();
            uint size = j.JumpTableSize;

            while (size > 0)
            {
                JumpTableEntry jte  = new JumpTableEntry();
                var            addr = ir.Address;
                jte.RoutineOffsetFromSegmentStart = ir.ReadBeUInt16();
                jte.Instruction       = ir.ReadBeUInt32();
                jte.LoadSegTrapNumber = ir.ReadBeUInt16();
                j.Entries.Add(jte);
                Debug.Print("{0}", jte);
                size -= 8;
            }
            return(j);
        }
예제 #20
0
파일: Ptc.cs 프로젝트: historria/Ryujinx
        internal static void LoadTranslations(
            ConcurrentDictionary <ulong, TranslatedFunction> funcs,
            IMemoryManager memory,
            JumpTable jumpTable,
            EntryTable <uint> countTable)
        {
            if (AreCarriersEmpty())
            {
                return;
            }

            long infosStreamLength       = _infosStream.Length;
            long relocsStreamLength      = _relocsStream.Length;
            long unwindInfosStreamLength = _unwindInfosStream.Length;

            _infosStream.Seek(0L, SeekOrigin.Begin);
            _relocsStream.Seek(0L, SeekOrigin.Begin);
            _unwindInfosStream.Seek(0L, SeekOrigin.Begin);

            using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true))
                using (BinaryReader unwindInfosReader = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true))
                {
                    for (int index = 0; index < GetEntriesCount(); index++)
                    {
                        InfoEntry infoEntry = DeserializeStructure <InfoEntry>(_infosStream);

                        if (infoEntry.Stubbed)
                        {
                            SkipCode(index, infoEntry.CodeLength);
                            SkipReloc(infoEntry.RelocEntriesCount);
                            SkipUnwindInfo(unwindInfosReader);

                            continue;
                        }

                        bool isEntryChanged = infoEntry.Hash != ComputeHash(memory, infoEntry.Address, infoEntry.GuestSize);

                        if (isEntryChanged || (!infoEntry.HighCq && PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq))
                        {
                            infoEntry.Stubbed    = true;
                            infoEntry.CodeLength = 0;
                            UpdateInfo(infoEntry);

                            StubCode(index);
                            StubReloc(infoEntry.RelocEntriesCount);
                            StubUnwindInfo(unwindInfosReader);

                            if (isEntryChanged)
                            {
                                PtcJumpTable.Clean(infoEntry.Address);

                                Logger.Info?.Print(LogClass.Ptc, $"Invalidated translated function (address: 0x{infoEntry.Address:X16})");
                            }

                            continue;
                        }

                        byte[] code = ReadCode(index, infoEntry.CodeLength);

                        Counter <uint> callCounter = null;

                        if (infoEntry.RelocEntriesCount != 0)
                        {
                            RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount);

                            PatchCode(code, relocEntries, memory.PageTablePointer, jumpTable, countTable, out callCounter);
                        }

                        UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader);

                        TranslatedFunction func = FastTranslate(code, callCounter, infoEntry.GuestSize, unwindInfo, infoEntry.HighCq);

                        bool isAddressUnique = funcs.TryAdd(infoEntry.Address, func);

                        Debug.Assert(isAddressUnique, $"The address 0x{infoEntry.Address:X16} is not unique.");
                    }
                }

            if (_infosStream.Length != infosStreamLength || _infosStream.Position != infosStreamLength ||
                _relocsStream.Length != relocsStreamLength || _relocsStream.Position != relocsStreamLength ||
                _unwindInfosStream.Length != unwindInfosStreamLength || _unwindInfosStream.Position != unwindInfosStreamLength)
            {
                throw new Exception("The length of a memory stream has changed, or its position has not reached or has exceeded its end.");
            }

            jumpTable.Initialize(PtcJumpTable, funcs);

            PtcJumpTable.WriteJumpTable(jumpTable, funcs);
            PtcJumpTable.WriteDynamicTable(jumpTable);

            Logger.Info?.Print(LogClass.Ptc, $"{funcs.Count} translated functions loaded");
        }
예제 #21
0
파일: ResourceFork.cs 프로젝트: heruix/reko
        public void AddResourcesToImageMap(
            Address addrLoad,
            MemoryArea mem,
            SegmentMap segmentMap,
            List <ImageSymbol> entryPoints,
            SortedList <Address, ImageSymbol> symbols)
        {
            JumpTable jt       = null;
            var       codeSegs = new Dictionary <int, ImageSegment>();

            foreach (ResourceType type in ResourceTypes)
            {
                foreach (ResourceReference rsrc in type.References)
                {
                    uint uSegOffset  = rsrc.DataOffset + rsrcDataOff;
                    int  segmentSize = mem.ReadBeInt32(uSegOffset);

                    // Skip the size longword at the beginning of the segment, and an extra 4
                    // if it is a code segement other than CODE#0.
                    int bytesToSkip = 4;
                    if (type.Name == "CODE" && rsrc.ResourceID != 0)
                    {
                        bytesToSkip += 4;
                    }
                    var abSegment = new byte[segmentSize];
                    Array.Copy(mem.Bytes, uSegOffset + bytesToSkip, abSegment, 0, segmentSize);

                    Address addrSegment = addrLoad + uSegOffset + bytesToSkip;    //$TODO pad to 16-byte boundary?
                    var     memSeg      = new MemoryArea(addrSegment, abSegment);
                    var     segment     = segmentMap.AddSegment(new ImageSegment(
                                                                    ResourceDescriptiveName(type, rsrc),
                                                                    memSeg,
                                                                    AccessMode.Read));
                    if (type.Name == "CODE")
                    {
                        if (rsrc.ResourceID == 0)
                        {
                            jt = ProcessJumpTable(memSeg, symbols);
                        }
                        else
                        {
                            codeSegs.Add(rsrc.ResourceID, segment);
                            var macsBug   = new MacsBugSymbolScanner(arch, segment.MemoryArea);
                            var mbSymbols = macsBug.ScanForSymbols();
                            foreach (var symbol in mbSymbols)
                            {
                                symbols[symbol.Address] = symbol;
                            }
                        }
                    }
                }
            }

            // We have found a jump table, so we allocate an A5World.
            if (jt != null)
            {
                // Find an address beyond all known segments.
                var addr    = segmentMap.Segments.Values.Max(s => s.Address + s.Size).Align(0x10);
                var a5world = LoadA5World(jt, addr, codeSegs, symbols);
                platform.A5World  = a5world;
                platform.A5Offset = jt.BelowA5Size;
                segmentMap.AddSegment(a5world);


                // Find first (and only!) segment containing the name %A5Init.
                var a5dataSegment = segmentMap.Segments.Values.SingleOrDefault(SegmentNamedA5Init);
                if (a5dataSegment == null)
                {
                    return;
                }

                // Get an image reader to the start of the data.
                var a5dr = GetA5InitImageReader(a5dataSegment);
                if (a5dr == null)
                {
                    return;
                }

                var a5dbelow    = a5dr.ReadBeUInt32();
                var a5dbankSize = a5dr.ReadBeUInt32();
                var a5doffset   = a5dr.ReadBeUInt32();
                var a5dreloc    = a5dr.ReadBeUInt32();
                var a5dhdrend   = a5dr.ReadBeUInt32();
                if (a5dbankSize != 0x00010000)
                {
                    // bank size not supported for compressed global data
                    return;
                }
                A5Expand(a5dr, a5dbelow);
            }
        }
예제 #22
0
        string OpCodeToString(OpCode opcode, Class currentClass, Method method, JumpTable jumpTable)
        {
            switch (opcode.Instruction)
            {
            case Instructions.Const:
            case Instructions.Const4:
            case Instructions.Const16:
            case Instructions.ConstHigh:
            case Instructions.ConstWide16:
            case Instructions.ConstWide32:
            case Instructions.ConstWide:
            case Instructions.ConstWideHigh:
                dynamic constOpCode = opcode;
                return(string.Format("{1} = #{2}", constOpCode.Name, GetRegisterName(constOpCode.Destination, method), constOpCode.Value));

            case Instructions.Move:
            case Instructions.MoveFrom16:
            case Instructions.Move16:
            case Instructions.MoveWide:
            case Instructions.MoveWideFrom16:
            case Instructions.MoveWide16:
            case Instructions.MoveObject:
            case Instructions.MoveObjectFrom16:
            case Instructions.MoveObject16:
                dynamic moveOpCode = opcode;
                return(string.Format("{1} = {2}", moveOpCode.Name, GetRegisterName(moveOpCode.To, method), GetRegisterName(moveOpCode.From, method)));

            case Instructions.MoveResult:
            case Instructions.MoveResultWide:
            case Instructions.MoveResultObject:
            case Instructions.MoveException:
                dynamic moveResultOpCode = opcode;
                return(string.Format("{0} {1}", moveResultOpCode.Name, GetRegisterName(moveResultOpCode.Destination, method)));

            case Instructions.ConstString:
            case Instructions.ConstStringJumbo:
                dynamic constStringOpCode = opcode;
                return(string.Format("{1} = \"{2}\"", constStringOpCode.Name, GetRegisterName(constStringOpCode.Destination, method), _dex.GetString(constStringOpCode.StringIndex).Replace("\n", "\\n")));

            case Instructions.ConstClass:
                return(string.Format("{0} = {1}", GetRegisterName(((ConstClassOpCode)opcode).Destination, method), _dex.GetTypeName(((ConstClassOpCode)opcode).TypeIndex)));

            case Instructions.CheckCast:
                var typeCheckCast = _dex.GetTypeName(((CheckCastOpCode)opcode).TypeIndex);
                return(string.Format("({1}){0}", GetRegisterName(((CheckCastOpCode)opcode).Destination, method), typeCheckCast));

            case Instructions.InstanceOf:
                var typeInstanceOf = _dex.GetTypeName(((InstanceOfOpCode)opcode).TypeIndex);
                return(string.Format("instance-of v{0}, v{1}, {2}", ((InstanceOfOpCode)opcode).Destination, ((InstanceOfOpCode)opcode).Reference, typeInstanceOf));

            case Instructions.NewInstance:
                var typeNewInstance = _dex.GetTypeName(((NewInstanceOpCode)opcode).TypeIndex);
                return(string.Format("{0} = new {1}", GetRegisterName(((NewInstanceOpCode)opcode).Destination, method), typeNewInstance));

            case Instructions.NewArrayOf:
                var newArrayOpCode       = (NewArrayOfOpCode)opcode;
                var typeNewArrayOfOpCode = _dex.GetTypeName(newArrayOpCode.TypeIndex);
                return(string.Format("{0} = new {1}", GetRegisterName(newArrayOpCode.Destination, method),
                                     typeNewArrayOfOpCode.Replace("[]", string.Format("[{0}]", GetRegisterName(newArrayOpCode.Size, method)))));

            case Instructions.FilledNewArrayOf:
                var typeFilledNewArrayOf = _dex.GetTypeName(((FilledNewArrayOfOpCode)opcode).TypeIndex);
                return(string.Format("filled-new-array {0}, {1}", string.Join(",", ((FilledNewArrayOfOpCode)opcode).Values), typeFilledNewArrayOf));

            case Instructions.FilledNewArrayRange:
                var typeFilledNewArrayRange = _dex.GetTypeName(((FilledNewArrayRangeOpCode)opcode).TypeIndex);
                return(string.Format("filled-new-array/range {0}, {1}", string.Join(",", ((FilledNewArrayRangeOpCode)opcode).Values), typeFilledNewArrayRange));

            case Instructions.ArrayLength:
                var arrayLengthOpcode = (ArrayLengthOpCode)opcode;
                return(string.Format("{0} = {1}.length", GetRegisterName(arrayLengthOpcode.Destination, method), GetRegisterName(arrayLengthOpcode.ArrayReference, method)));

            case Instructions.InvokeVirtual:
            case Instructions.InvokeSuper:
            case Instructions.InvokeDirect:
            case Instructions.InvokeStatic:
            case Instructions.InvokeInterface:
                var invokeOpcode = (InvokeOpCode)opcode;
                var invokeMethod = _dex.GetMethod(invokeOpcode.MethodIndex);

                string invokeObject;
                if (invokeMethod.IsStatic() || invokeOpcode.Instruction == Instructions.InvokeStatic)
                {
                    invokeObject = _dex.GetTypeName(invokeMethod.ClassIndex);
                }
                else
                {
                    invokeObject = GetRegisterName(invokeOpcode.ArgumentRegisters [0], method);
                }

                string[] registerNames = {};
                if (invokeOpcode.ArgumentRegisters.Length > 0)
                {
                    var instanceAdjustment = invokeMethod.IsStatic()?0:1;
                    registerNames = new string[invokeOpcode.ArgumentRegisters.Length - instanceAdjustment];
                    for (int i = 0; i < registerNames.Length; i++)
                    {
                        registerNames [i] = GetRegisterName(invokeOpcode.ArgumentRegisters[i + instanceAdjustment], method);
                    }
                }
                return(string.Format("{2}.{3}({1})", ((InvokeOpCode)opcode).Name, string.Join(",", registerNames), invokeObject, invokeMethod.Name));

            case Instructions.Sput:
            case Instructions.SputWide:
            case Instructions.SputObject:
            case Instructions.SputBoolean:
            case Instructions.SputChar:
            case Instructions.SputShort:
            case Instructions.SputByte:
                var sputOpcode = (StaticOpOpCode)opcode;
                return(string.Format("{2} = {1}", sputOpcode.Name, GetRegisterName(sputOpcode.Destination, method), GetFieldName(sputOpcode.Index, currentClass, true)));

            case Instructions.Sget:
            case Instructions.SgetWide:
            case Instructions.SgetObject:
            case Instructions.SgetBoolean:
            case Instructions.SgetChar:
            case Instructions.SgetShort:
            case Instructions.SgetByte:
                var sgetOpcode = (StaticOpOpCode)opcode;
                return(string.Format("{1} = {2}", sgetOpcode.Name, GetRegisterName(sgetOpcode.Destination, method), GetFieldName(sgetOpcode.Index, currentClass, true)));

            case Instructions.Iput:
            case Instructions.IputWide:
            case Instructions.IputObject:
            case Instructions.IputBoolean:
            case Instructions.IputChar:
            case Instructions.IputShort:
            case Instructions.IputByte:
                var iputOpCode = (IinstanceOpOpCode)opcode;
                return(string.Format("{2} = {1}", iputOpCode.Name, GetRegisterName(iputOpCode.Destination, method), GetFieldName(iputOpCode.Index, currentClass)));

            case Instructions.Iget:
            case Instructions.IgetWide:
            case Instructions.IgetObject:
            case Instructions.IgetBoolean:
            case Instructions.IgetChar:
            case Instructions.IgetShort:
            case Instructions.IgetByte:
                var igetOpCode = (IinstanceOpOpCode)opcode;
                return(string.Format("{1} = {2}", igetOpCode.Name, GetRegisterName(igetOpCode.Destination, method), GetFieldName(igetOpCode.Index, currentClass)));

            case Instructions.Aput:
            case Instructions.AputWide:
            case Instructions.AputObject:
            case Instructions.AputBoolean:
            case Instructions.AputChar:
            case Instructions.AputShort:
            case Instructions.AputByte:
                var aputOpCode = (ArrayOpOpCode)opcode;
                return(string.Format("{2}[{3}] = {1}", aputOpCode.Name, GetRegisterName(aputOpCode.Destination, method), GetRegisterName(aputOpCode.Array, method), GetRegisterName(aputOpCode.Index, method)));

            case Instructions.Aget:
            case Instructions.AgetWide:
            case Instructions.AgetObject:
            case Instructions.AgetBoolean:
            case Instructions.AgetChar:
            case Instructions.AgetShort:
            case Instructions.AgetByte:
                var agetOpCode = (ArrayOpOpCode)opcode;
                return(string.Format("{1} = {2}[{3}]", agetOpCode.Name, GetRegisterName(agetOpCode.Destination, method), GetRegisterName(agetOpCode.Array, method), GetRegisterName(agetOpCode.Index, method)));

            case Instructions.AddInt:
            case Instructions.AddLong:
            case Instructions.AddFloat:
            case Instructions.AddDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "+", method));

            case Instructions.SubInt:
            case Instructions.SubLong:
            case Instructions.SubFloat:
            case Instructions.SubDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "-", method));

            case Instructions.MulInt:
            case Instructions.MulLong:
            case Instructions.MulFloat:
            case Instructions.MulDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "*", method));

            case Instructions.DivInt:
            case Instructions.DivLong:
            case Instructions.DivFloat:
            case Instructions.DivDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "/", method));

            case Instructions.RemInt:
            case Instructions.RemLong:
            case Instructions.RemFloat:
            case Instructions.RemDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "&", method));

            case Instructions.AndInt:
            case Instructions.AndLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "&", method));

            case Instructions.OrInt:
            case Instructions.OrLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "|", method));

            case Instructions.XorInt:
            case Instructions.XorLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "^", method));

            case Instructions.ShlInt:
            case Instructions.ShlLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "<<", method));

            case Instructions.ShrInt:
            case Instructions.UshrInt:
            case Instructions.ShrLong:
            case Instructions.UshrLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, ">>", method));

            case Instructions.IfEq:
                return(FormatIfOperation((IfOpCode)opcode, "=", method, jumpTable));

            case Instructions.IfNe:
                return(FormatIfOperation((IfOpCode)opcode, "!=", method, jumpTable));

            case Instructions.IfLt:
                return(FormatIfOperation((IfOpCode)opcode, "<", method, jumpTable));

            case Instructions.IfGe:
                return(FormatIfOperation((IfOpCode)opcode, ">=", method, jumpTable));

            case Instructions.IfGt:
                return(FormatIfOperation((IfOpCode)opcode, ">", method, jumpTable));

            case Instructions.IfLe:
                return(FormatIfOperation((IfOpCode)opcode, "<=", method, jumpTable));

            case Instructions.IfEqz:
                return(FormatIfzOperation((IfzOpCode)opcode, "=", method, jumpTable));

            case Instructions.IfNez:
                return(FormatIfzOperation((IfzOpCode)opcode, "!=", method, jumpTable));

            case Instructions.IfLtz:
                return(FormatIfzOperation((IfzOpCode)opcode, "<", method, jumpTable));

            case Instructions.IfGez:
                return(FormatIfzOperation((IfzOpCode)opcode, ">=", method, jumpTable));

            case Instructions.IfGtz:
                return(FormatIfzOperation((IfzOpCode)opcode, ">", method, jumpTable));

            case Instructions.IfLez:
                return(FormatIfzOperation((IfzOpCode)opcode, "<=", method, jumpTable));

            case Instructions.RsubInt:
            case Instructions.RsubIntLit8:
                dynamic rsubIntOpCode = opcode;
                return(string.Format("{0} = #{2} - {1}", GetRegisterName(rsubIntOpCode.Destination, method), GetRegisterName(rsubIntOpCode.Source, method), rsubIntOpCode.Constant));

            case Instructions.AddIntLit16:
            case Instructions.AddIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "+", method));

            case Instructions.MulIntLit16:
            case Instructions.MulIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "*", method));

            case Instructions.DivIntLit16:
            case Instructions.DivIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "/", method));

            case Instructions.RemIntLit16:
            case Instructions.RemIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "%", method));

            case Instructions.AndIntLit16:
            case Instructions.AndIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "&", method));

            case Instructions.OrIntLit16:
            case Instructions.OrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "|", method));

            case Instructions.XorIntLit16:
            case Instructions.XorIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "^", method));

            case Instructions.ShlIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "<<", method));

            case Instructions.ShrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, ">>", method));

            case Instructions.UshrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, ">>", method));

            case Instructions.AddInt2Addr:
            case Instructions.AddLong2Addr:
            case Instructions.AddFloat2Addr:
            case Instructions.AddDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "+", method));

            case Instructions.SubInt2Addr:
            case Instructions.SubLong2Addr:
            case Instructions.SubFloat2Addr:
            case Instructions.SubDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "-", method));

            case Instructions.MulInt2Addr:
            case Instructions.MulLong2Addr:
            case Instructions.MulFloat2Addr:
            case Instructions.MulDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "*", method));

            case Instructions.DivInt2Addr:
            case Instructions.DivLong2Addr:
            case Instructions.DivFloat2Addr:
            case Instructions.DivDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "/", method));

            case Instructions.RemInt2Addr:
            case Instructions.RemLong2Addr:
            case Instructions.RemFloat2Addr:
            case Instructions.RemDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "&", method));

            case Instructions.AndInt2Addr:
            case Instructions.AndLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "&", method));

            case Instructions.OrInt2Addr:
            case Instructions.OrLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "|", method));

            case Instructions.XorInt2Addr:
            case Instructions.XorLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "^", method));

            case Instructions.ShlInt2Addr:
            case Instructions.ShlLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "<<", method));

            case Instructions.ShrInt2Addr:
            case Instructions.UshrInt2Addr:
            case Instructions.ShrLong2Addr:
            case Instructions.UshrLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, ">>", method));

            case Instructions.Goto:
            case Instructions.Goto16:
            case Instructions.Goto32:
                dynamic gotoOpCode = opcode;
                return(string.Format("{0} {1}", gotoOpCode.Name, jumpTable.GetReferrerLabel(gotoOpCode.OpCodeOffset)));

            case Instructions.PackedSwitch:
                var packedSwitchOpCode = (PackedSwitchOpCode)opcode;
                return(string.Format("{0} {1} - First:{2} - [{3}]", opcode.Name, GetRegisterName(packedSwitchOpCode.Destination, method), packedSwitchOpCode.FirstKey, string.Join(",", jumpTable.GetReferrerLabels(packedSwitchOpCode.OpCodeOffset))));

            case Instructions.SparseSwitch:
                var sparseSwitchOpCode = (SparseSwitchOpCode)opcode;
                return(string.Format("{0} {1} - Keys:[{2}] Targets:[{3}]", opcode.Name, GetRegisterName(sparseSwitchOpCode.Destination, method), string.Join(",", sparseSwitchOpCode.Keys), string.Join(",", jumpTable.GetReferrerLabels(sparseSwitchOpCode.OpCodeOffset))));

            default:
                return(opcode.ToString());
            }
        }
예제 #23
0
        JumpTable BuildJumpTable(Method method)
        {
            var jumpTable = new JumpTable();

            int gotoCounter   = 0;
            int ifCounter     = 0;
            int switchCounter = 0;

            foreach (var opcode in method.GetInstructions())
            {
                switch (opcode.Instruction)
                {
                case Instructions.Goto:
                case Instructions.Goto16:
                case Instructions.Goto32:
                    var gotoOpCode = (dynamic)opcode;
                    jumpTable.AddTarget(gotoOpCode.OpCodeOffset, gotoOpCode.GetTargetAddress(), "goto_", ref gotoCounter);
                    break;

                case Instructions.PackedSwitch:
                case Instructions.SparseSwitch:
                    dynamic switchOpCode = opcode;
                    foreach (var switchTarget in switchOpCode.GetTargetAddresses())
                    {
                        jumpTable.AddTarget(switchOpCode.OpCodeOffset, switchTarget, "switch_", ref switchCounter);
                    }
                    break;

                case Instructions.IfEq:
                case Instructions.IfNe:
                case Instructions.IfLt:
                case Instructions.IfGe:
                case Instructions.IfGt:
                case Instructions.IfLe:
                case Instructions.IfEqz:
                case Instructions.IfNez:
                case Instructions.IfLtz:
                case Instructions.IfGez:
                case Instructions.IfGtz:
                case Instructions.IfLez:
                    dynamic ifOpCode = opcode;
                    jumpTable.AddTarget(ifOpCode.OpCodeOffset, ifOpCode.GetTargetAddress(), "if_", ref ifCounter);
                    break;
                }
            }

            var catchCounter = 0;

            if (method.TryCatchBlocks != null)
            {
                foreach (var tryBlock in method.TryCatchBlocks)
                {
                    foreach (var catchBlock in tryBlock.Handlers)
                    {
                        jumpTable.AddHandler(catchBlock, "catch_", ref catchCounter);
                    }
                }
            }

            return(jumpTable);
        }
예제 #24
0
 private void WriteOutCatchStatements(TextWriter output, Indentation indent, TryCatchBlock currentTryBlock, JumpTable jumpTable)
 {
     indent--;
     foreach (var catchBlock in currentTryBlock.Handlers)
     {
         output.WriteLine(string.Format("{0}catch({1}) :{2}",
                                        indent.ToString(),
                                        catchBlock.TypeIndex == 0 ? "ALL" : _dex.GetTypeName(catchBlock.TypeIndex),
                                        jumpTable.GetHandlerLabel(catchBlock)));
     }
 }
예제 #25
0
 private string FormatIfzOperation(IfzOpCode opcode, string comparison, Method method, JumpTable jumpTable)
 {
     return(string.Format("if ({0} {2} 0) :{1}", GetRegisterName(opcode.Destination, method), jumpTable.GetReferrerLabel(opcode.OpCodeOffset), comparison));
 }
예제 #26
0
 private string FormatIfOperation(IfOpCode opcode, string comparison, Method method, JumpTable jumpTable)
 {
     return(string.Format("if ({0} {3} {1}) :{2}", GetRegisterName(opcode.First, method), GetRegisterName(opcode.Second, method), jumpTable.GetReferrerLabel(opcode.OpCodeOffset), comparison));
 }
예제 #27
0
파일: Ptc.cs 프로젝트: headassbtw/Ryujinx
        internal static void MakeAndSaveTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable)
        {
            var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(funcs);

            if (profiledFuncsToTranslate.Count == 0)
            {
                return;
            }

            _translateCount = 0;

            ThreadPool.QueueUserWorkItem(TranslationLogger, profiledFuncsToTranslate.Count);

            void TranslateFuncs()
            {
                while (profiledFuncsToTranslate.TryDequeue(out var item))
                {
                    ulong address = item.address;

                    Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));

                    TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.mode, item.highCq);

                    bool isAddressUnique = funcs.TryAdd(address, func);

                    Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");

                    if (func.HighCq)
                    {
                        jumpTable.RegisterFunction(address, func);
                    }

                    Interlocked.Increment(ref _translateCount);

                    if (State != PtcState.Enabled)
                    {
                        break;
                    }
                }
            }

            int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4;

            List <Thread> threads = new List <Thread>();

            for (int i = 0; i < maxDegreeOfParallelism; i++)
            {
                Thread thread = new Thread(TranslateFuncs);
                thread.IsBackground = true;

                threads.Add(thread);
            }

            threads.ForEach((thread) => thread.Start());
            threads.ForEach((thread) => thread.Join());

            threads.Clear();

            Translator.ResetPools();

            _loggerEvent.Set();

            PtcJumpTable.Initialize(jumpTable);

            PtcJumpTable.ReadJumpTable(jumpTable);
            PtcJumpTable.ReadDynamicTable(jumpTable);

            ThreadPool.QueueUserWorkItem(PreSave);
        }
예제 #28
0
파일: Ptc.cs 프로젝트: headassbtw/Ryujinx
        internal static void LoadTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable)
        {
            if ((int)_infosStream.Length == 0 ||
                (int)_codesStream.Length == 0 ||
                (int)_relocsStream.Length == 0 ||
                (int)_unwindInfosStream.Length == 0)
            {
                return;
            }

            Debug.Assert(funcs.Count == 0);

            _infosStream.Seek(0L, SeekOrigin.Begin);
            _codesStream.Seek(0L, SeekOrigin.Begin);
            _relocsStream.Seek(0L, SeekOrigin.Begin);
            _unwindInfosStream.Seek(0L, SeekOrigin.Begin);

            using (BinaryReader infosReader = new BinaryReader(_infosStream, EncodingCache.UTF8NoBOM, true))
                using (BinaryReader codesReader = new BinaryReader(_codesStream, EncodingCache.UTF8NoBOM, true))
                    using (BinaryReader relocsReader = new BinaryReader(_relocsStream, EncodingCache.UTF8NoBOM, true))
                        using (BinaryReader unwindInfosReader = new BinaryReader(_unwindInfosStream, EncodingCache.UTF8NoBOM, true))
                        {
                            for (int i = 0; i < GetInfosEntriesCount(); i++)
                            {
                                InfoEntry infoEntry = ReadInfo(infosReader);

                                if (infoEntry.Stubbed)
                                {
                                    SkipCode(infoEntry.CodeLen);
                                    SkipReloc(infoEntry.RelocEntriesCount);
                                    SkipUnwindInfo(unwindInfosReader);
                                }
                                else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.highCq)
                                {
                                    byte[] code = ReadCode(codesReader, infoEntry.CodeLen);

                                    if (infoEntry.RelocEntriesCount != 0)
                                    {
                                        RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount);

                                        PatchCode(code, relocEntries, memory.PageTablePointer, jumpTable);
                                    }

                                    UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader);

                                    TranslatedFunction func = FastTranslate(code, infoEntry.GuestSize, unwindInfo, infoEntry.HighCq);

                                    bool isAddressUnique = funcs.TryAdd(infoEntry.Address, func);

                                    Debug.Assert(isAddressUnique, $"The address 0x{infoEntry.Address:X16} is not unique.");
                                }
                                else
                                {
                                    infoEntry.Stubbed = true;
                                    UpdateInfo(infoEntry);

                                    StubCode(infoEntry.CodeLen);
                                    StubReloc(infoEntry.RelocEntriesCount);
                                    StubUnwindInfo(unwindInfosReader);
                                }
                            }
                        }

            if (_infosStream.Position < _infosStream.Length ||
                _codesStream.Position < _codesStream.Length ||
                _relocsStream.Position < _relocsStream.Length ||
                _unwindInfosStream.Position < _unwindInfosStream.Length)
            {
                throw new Exception("Could not reach the end of one or more memory streams.");
            }

            jumpTable.Initialize(PtcJumpTable, funcs);

            PtcJumpTable.WriteJumpTable(jumpTable, funcs);
            PtcJumpTable.WriteDynamicTable(jumpTable);

            Logger.Info?.Print(LogClass.Ptc, $"{funcs.Count} translated functions loaded");
        }
예제 #29
0
        internal static void MakeAndSaveTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable)
        {
            if (PtcProfiler.ProfiledFuncs.Count == 0)
            {
                return;
            }

            _translateCount = 0;
            _rejitCount     = 0;

            ThreadPool.QueueUserWorkItem(TranslationLogger, (funcs.Count, PtcProfiler.ProfiledFuncs.Count));

            int maxDegreeOfParallelism = (Environment.ProcessorCount * 3) / 4;

            Parallel.ForEach(PtcProfiler.ProfiledFuncs, new ParallelOptions {
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            }, (item, state) =>
            {
                ulong address = item.Key;

                Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));

                if (!funcs.ContainsKey(address))
                {
                    TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.Value.mode, item.Value.highCq);

                    funcs.TryAdd(address, func);

                    if (func.HighCq)
                    {
                        jumpTable.RegisterFunction(address, func);
                    }

                    Interlocked.Increment(ref _translateCount);
                }
                else if (item.Value.highCq && !funcs[address].HighCq)
                {
                    TranslatedFunction func = Translator.Translate(memory, jumpTable, address, item.Value.mode, highCq: true);

                    funcs[address] = func;

                    jumpTable.RegisterFunction(address, func);

                    Interlocked.Increment(ref _rejitCount);
                }

                if (State != PtcState.Enabled)
                {
                    state.Stop();
                }
            });

            _loggerEvent.Set();

            if (_translateCount != 0 || _rejitCount != 0)
            {
                PtcJumpTable.Initialize(jumpTable);

                PtcJumpTable.ReadJumpTable(jumpTable);
                PtcJumpTable.ReadDynamicTable(jumpTable);

                ThreadPool.QueueUserWorkItem(PreSave);
            }
        }
예제 #30
0
 public override void Eval(Executor exec)
 {
     int n = exec.PopInt();
     Function f = exec.TypedPop<Function>();
     Function g = exec.TypedPeek<Function>();
     if (g is JumpTable)
     {
         JumpTable jt = g as JumpTable;
         jt.AddCase(n, f);                    
     }
     else
     {
         exec.Pop(); 
         JumpTable jt = new JumpTable(g);
         exec.Push(jt);                        
     }
 }
예제 #31
0
파일: Ptc.cs 프로젝트: historria/Ryujinx
        internal static void MakeAndSaveTranslations(
            ConcurrentDictionary <ulong, TranslatedFunction> funcs,
            IMemoryManager memory,
            JumpTable jumpTable,
            EntryTable <uint> countTable)
        {
            var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(funcs);

            _translateCount      = 0;
            _translateTotalCount = profiledFuncsToTranslate.Count;

            int degreeOfParallelism = new DegreeOfParallelism(4d, 75d, 12.5d).GetDegreeOfParallelism(0, 32);

            if (_translateTotalCount == 0 || degreeOfParallelism == 0)
            {
                ResetCarriersIfNeeded();
                PtcJumpTable.ClearIfNeeded();

                GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;

                return;
            }

            Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}");

            PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount);

            using AutoResetEvent progressReportEvent = new AutoResetEvent(false);

            Thread progressReportThread = new Thread(ReportProgress)
            {
                Name         = "Ptc.ProgressReporter",
                Priority     = ThreadPriority.Lowest,
                IsBackground = true
            };

            progressReportThread.Start(progressReportEvent);

            void TranslateFuncs()
            {
                while (profiledFuncsToTranslate.TryDequeue(out var item))
                {
                    ulong address = item.address;

                    Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));

                    TranslatedFunction func = Translator.Translate(memory, jumpTable, countTable, address, item.funcProfile.Mode, item.funcProfile.HighCq);

                    bool isAddressUnique = funcs.TryAdd(address, func);

                    Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");

                    if (func.HighCq)
                    {
                        jumpTable.RegisterFunction(address, func);
                    }

                    Interlocked.Increment(ref _translateCount);

                    if (State != PtcState.Enabled)
                    {
                        break;
                    }
                }

                Translator.DisposePools();
            }

            List <Thread> threads = new List <Thread>();

            for (int i = 0; i < degreeOfParallelism; i++)
            {
                Thread thread = new Thread(TranslateFuncs);
                thread.IsBackground = true;

                threads.Add(thread);
            }

            threads.ForEach((thread) => thread.Start());
            threads.ForEach((thread) => thread.Join());

            threads.Clear();

            progressReportEvent.Set();
            progressReportThread.Join();

            PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);

            Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}");

            PtcJumpTable.Initialize(jumpTable);

            PtcJumpTable.ReadJumpTable(jumpTable);
            PtcJumpTable.ReadDynamicTable(jumpTable);

            Thread preSaveThread = new Thread(PreSave);

            preSaveThread.IsBackground = true;
            preSaveThread.Start();
        }
예제 #32
0
 public override void Eval(Executor exec)
 {
     QuotedFunction f = exec.TypedPop<QuotedFunction>();
     f.GetSubFxns().Insert(0, new Pop());
     JumpTable jt = new JumpTable(f);
     exec.Push(jt);
 }