Ejemplo n.º 1
0
        private void ResolveSymbols(ISymbolProgressListener listener, TraceReplayStateful replay, string elfFile, string sdkDir, ulong elfBase)
        {
            var result = new Dictionary <ulong, SymbolInfo>();

            var procInfo = new ProcessStartInfo
            {
                // Need to merge stdout and stderr together
                Arguments              = String.Format("--infile=\"{0}\" -a2l", elfFile),
                UseShellExecute        = false,
                WindowStyle            = ProcessWindowStyle.Hidden,
                CreateNoWindow         = true,
                FileName               = Path.Combine(sdkDir, @"host_tools\bin\orbis-bin.exe"),
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
            };

            var stdout = new List <string>();

            using (var proc = Process.Start(procInfo))
            {
                proc.OutputDataReceived += (object sender, DataReceivedEventArgs args) =>
                {
                    if (!String.IsNullOrEmpty(args.Data) && !args.Data.StartsWith("WARNING:"))
                    {
                        stdout.Add(args.Data);
                    }
                };

                proc.ErrorDataReceived += (object sender, DataReceivedEventArgs args) =>
                {
                    // Throw it on the floor.
                };

                proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();

                int x           = 0;
                var lastUpdate  = DateTime.Now;
                var updateThres = new TimeSpan(0, 0, 0, 0, 100);

                foreach (ulong address in replay.MetaData.Symbols)
                {
                    if (x % 100 == 0 || DateTime.Now - lastUpdate > updateThres)
                    {
                        listener.UpdateProgress(String.Format("Resolving symbol {0}/{1}..", x + 1, replay.MetaData.Symbols.Count), (x + 1) / (double)replay.MetaData.Symbols.Count);
                        lastUpdate = DateTime.Now;
                    }

                    if (address != 0)
                    {
                        proc.StandardInput.WriteLine("0x{0:x16}", address - elfBase);
                    }

                    ++x;
                }

                proc.StandardInput.Close();
                proc.WaitForExit();
            }

            // Now deal with orbis-bin's wonky output format
            for (int k = 0; k < stdout.Count;)
            {
                var    addrStr   = MatchPrefix(stdout[k++], "Address:");
                ulong  addr      = UInt64.Parse(addrStr.Substring(2), NumberStyles.HexNumber);
                string directory = MatchPrefix(stdout[k++], "Directory:").Replace('/', Path.DirectorySeparatorChar);
                string filename  = MatchPrefix(stdout[k++], "File Name:");

                var sym = new SymbolInfo();

                sym.Address = addr + elfBase;
                if (filename != "??")
                {
                    sym.FileName = Path.Combine(directory, filename);
                }
                else
                {
                    sym.FileName = "Unknown";
                }
                sym.LineNumber = Int32.Parse(MatchPrefix(stdout[k++], "Line Number:"));
                sym.Symbol     = MatchPrefix(stdout[k++], "Symbol:");

                // Try to discard function signature data.
                int firstParenPos = sym.Symbol.IndexOf('(');
                if (-1 != firstParenPos)
                {
                    sym.Symbol = sym.Symbol.Substring(0, firstParenPos);
                }

                result[addr + elfBase] = sym;
            }

            listener.UpdateProgress("Saving..", 1.0);
            listener.UpdateMessage("Writing resolved symbols back to trace file");

            replay.UpdateResolvedSymbols(result);

            listener.UpdateProgress("Done", 1.0);
            listener.UpdateMessage("Finished!");
        }
Ejemplo n.º 2
0
        public void BeginResolve(string ignored, ISymbolProgressListener listener, TraceReplayStateful replay, ICollection <string> symbolPaths, ICollection <ModulePathRemapping> remappings)
        {
            Task.Run(() =>
            {
                var result   = new Dictionary <ulong, SymbolInfo>();
                var metadata = replay.MetaData;
                var platform = metadata.PlatformName;

                using (var dbghelp = new DbgHelp(symbolPaths))
                {
                    for (int i = 0, count = metadata.Modules.Count; i < count; ++i)
                    {
                        var mod = metadata.Modules[i];

                        listener.UpdateProgress(String.Format("Loading module {0}/{1}..", i + 1, count), (i + 1) / (double)count);

                        // TEMP! Ignore empty module from Durango.
                        if (mod.Name == "")
                        {
                            continue;
                        }

                        var fn = mod.Name;
                        foreach (var rm in remappings)
                        {
                            if (0 != StringComparer.InvariantCultureIgnoreCase.Compare(rm.Platform, platform))
                            {
                                continue;
                            }

                            if (fn.ToLower().StartsWith(rm.Path.ToLower()))
                            {
                                var oldfn = fn;
                                fn        = rm.ReplacementPath + fn.Substring(rm.Path.Length);
                                listener.UpdateMessage(String.Format("Remapped {0} -> {1}", oldfn, fn));
                            }
                        }

                        listener.UpdateMessage(String.Format("Loading {0} at {1:x16}, size={2:n0} bytes", fn, mod.BaseAddress, mod.SizeBytes));
                        dbghelp.LoadModule(fn, mod.BaseAddress, mod.SizeBytes);
                    }

                    int x = 0;
                    foreach (ulong address in metadata.Symbols)
                    {
                        if (x % 100 == 0)
                        {
                            listener.UpdateProgress(String.Format("Resolving symbol {0}/{1}..", x + 1, metadata.Symbols.Count), (x + 1) / (double)metadata.Symbols.Count);
                        }

                        SymbolInfo sym;
                        if (dbghelp.LookupSymbol(address, out sym))
                        {
                            result[address] = sym;
                        }
                        else
                        {
                            sym.Symbol = "(unknown)";
                            foreach (var mod in metadata.Modules)
                            {
                                if (address >= mod.BaseAddress && address <= mod.BaseAddress + mod.SizeBytes)
                                {
                                    sym.Symbol      = String.Format("{0}!0x{1:x16}", Path.GetFileNameWithoutExtension(mod.Name), address);
                                    result[address] = sym;
                                    break;
                                }
                            }
                            //UpdateMessage(String.Format("Failed to resolve address {0:x}\n", address));
                        }

                        ++x;
                    }
                }

                listener.UpdateProgress("Saving..", 1.0);
                listener.UpdateMessage("Writing resolved symbols back to trace file");

                replay.UpdateResolvedSymbols(result);

                listener.UpdateProgress("Done", 1.0);
                listener.UpdateMessage("Finished!");

                listener.Done();
            });
        }