void ResolveStacktraces(string symbolPath, Regex regex)
        {
            m_ResolvedStacktraces = String.Empty;
            if (string.IsNullOrEmpty(m_Text))
            {
                m_ResolvedStacktraces = string.Format(" <color={0}>(Please add some log with addresses first)</color>", m_RedColor);
                return;
            }

            var lines = m_Text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var l in lines)
            {
                string address;
                string library;
                if (!ParseLine(regex, l, out address, out library))
                {
                    m_ResolvedStacktraces += l;
                }
                else
                {
                    string resolved   = string.Format(" <color={0}>(Not resolved)</color>", m_RedColor);
                    var    symbolFile = AndroidLogcatUtilities.GetSymbolFile(symbolPath, library);
                    if (string.IsNullOrEmpty(symbolFile))
                    {
                        resolved = string.Format(" <color={0}>({1} not found)</color>", m_RedColor, library);
                    }
                    else
                    {
                        try
                        {
                            var result = AndroidLogcatManager.instance.Runtime.Tools.RunAddr2Line(symbolFile, new[] { address });
                            AndroidLogcatInternalLog.Log("addr2line \"{0}\" {1}", symbolFile, address);
                            if (!string.IsNullOrEmpty(result[0]))
                            {
                                resolved = string.Format(" <color={0}>({1})</color>", m_GreenColor, result[0].Trim());
                            }
                        }
                        catch (Exception ex)
                        {
                            m_ResolvedStacktraces = string.Format("Exception while running addr2line ('{0}', {1}):\n{2}", symbolFile, address, ex.Message);
                            return;
                        }
                    }

                    m_ResolvedStacktraces += l.Replace(address, address + resolved);
                }

                m_ResolvedStacktraces += Environment.NewLine;
            }
        }
        private void ResolveStackTrace(List <LogEntry> entries)
        {
            var unresolvedAddresses = new Dictionary <KeyValuePair <BuildInfo, string>, List <UnresolvedAddress> >();

            // Gather unresolved address if there are any
            for (int i = 0; i < entries.Count; i++)
            {
                var entry = entries[i];
                // Only process stacktraces from Error/Fatal priorities
                if (entry.priority != Priority.Error && entry.priority != Priority.Fatal)
                {
                    continue;
                }

                // Only process stacktraces if tag is "CRASH" or "DEBUG"
                if (entry.tag.GetHashCode() != kCrashHashCode && entry.tag.GetHashCode() != kDebugHashCode)
                {
                    continue;
                }

                BuildInfo buildInfo;
                // Unknown build info, that means we don't know where the symbols are located
                if (!m_BuildInfos.TryGetValue(entry.processId, out buildInfo))
                {
                    continue;
                }

                string address, libName;
                if (!AndroidLogcatUtilities.ParseCrashLine(m_Runtime.Settings.StacktraceResolveRegex, entry.message, out address, out libName))
                {
                    continue;
                }

                List <UnresolvedAddress> addresses;
                var key = new KeyValuePair <BuildInfo, string>(buildInfo, libName);
                if (!unresolvedAddresses.TryGetValue(key, out addresses))
                {
                    unresolvedAddresses[key] = new List <UnresolvedAddress>();
                }

                unresolvedAddresses[key].Add(new UnresolvedAddress()
                {
                    logEntryIndex = i, unresolvedAddress = address
                });
            }

            var engineDirectory = BuildPipeline.GetPlaybackEngineDirectory(BuildTarget.Android, BuildOptions.None);


            // Resolve addresses
            foreach (var u in unresolvedAddresses)
            {
                var buildInfo = u.Key.Key;
                var libName   = u.Key.Value;

                var addresses  = u.Value;
                var symbolPath = CombinePaths(engineDirectory, "Variations", buildInfo.scriptingImplementation, buildInfo.buildType, "Symbols", buildInfo.cpu);
                var libpath    = AndroidLogcatUtilities.GetSymbolFile(symbolPath, libName);

                // For optimizations purposes, we batch addresses which belong to same library, so addr2line can be ran less
                try
                {
                    string[] result;
                    if (!string.IsNullOrEmpty(libpath))
                    {
                        result = m_Runtime.Tools.RunAddr2Line(libpath, addresses.Select(m => m.unresolvedAddress).ToArray());
                    }
                    else
                    {
                        result = new string[addresses.Count];
                        for (int i = 0; i < addresses.Count; i++)
                        {
                            result[i] = string.Empty;
                        }
                    }

                    for (int i = 0; i < addresses.Count; i++)
                    {
                        var idx    = addresses[i].logEntryIndex;
                        var append = string.IsNullOrEmpty(result[i]) ? "(Not Resolved)" : result[i];
                        entries[idx] = new LogEntry(entries[idx])
                        {
                            message = ModifyLogEntry(entries[idx].message, append, false)
                        };
                    }
                }
                catch (Exception ex)
                {
                    for (int i = 0; i < addresses.Count; i++)
                    {
                        var idx = addresses[i].logEntryIndex;
                        entries[idx] = new LogEntry(entries[idx])
                        {
                            message = ModifyLogEntry(entries[idx].message, "(Addr2Line failure)", true)
                        };
                        var errorMessage = new StringBuilder();
                        errorMessage.AppendLine("Addr2Line failure");
                        errorMessage.AppendLine("Full Entry Message: " + entries[idx].message);
                        errorMessage.AppendLine("Scripting Backend: " + buildInfo.scriptingImplementation);
                        errorMessage.AppendLine("Build Type: " + buildInfo.buildType);
                        errorMessage.AppendLine("CPU: " + buildInfo.cpu);
                        errorMessage.AppendLine(ex.Message);
                        UnityEngine.Debug.LogError(errorMessage.ToString());
                    }
                }
            }
        }
示例#3
0
        internal static string ResolveAddresses(string[] lines, IReadOnlyList <ReordableListItem> regexes, IReadOnlyList <ReordableListItem> symbolPaths, AndroidTools tools)
        {
            var output = string.Empty;
            // Calling addr2line for every address is costly, that's why we need to do it in batch
            var unresolved = new UnresolvedAddresses();

            foreach (var l in lines)
            {
                string address;
                string library;
                if (!AndroidLogcatUtilities.ParseCrashLine(regexes, l, out address, out library))
                {
                    continue;
                }
                unresolved.CreateAddressEntry(library, address);
            }

            var libraries = unresolved.GetAllLibraries();

            foreach (var library in libraries)
            {
                var addresses  = unresolved.GetAllAddresses(library);
                var symbolFile = AndroidLogcatUtilities.GetSymbolFile(symbolPaths, library);

                // Symbol file not found, set 'not found' messages for all addresses of this library
                if (string.IsNullOrEmpty(symbolFile))
                {
                    var value = $"<color={m_RedColor}>({library} not found)</color>";
                    foreach (var a in addresses)
                    {
                        unresolved.SetAddressValue(library, a, value);
                    }
                    continue;
                }


                try
                {
                    var result = tools.RunAddr2Line(symbolFile, addresses.ToArray());

                    if (result.Length != addresses.Count)
                    {
                        return($"Failed to run addr2line, expected to receive {addresses.Count} addresses, but received {result.Length}");
                    }

                    for (int i = 0; i < addresses.Count; i++)
                    {
                        AndroidLogcatInternalLog.Log($"{addresses[i]} ---> {result[i]}");
                        unresolved.SetAddressValue(library, addresses[i], $"<color={m_GreenColor}>({result[i].Trim()})</color>");
                    }
                }
                catch (Exception ex)
                {
                    return($"Exception while running addr2line:\n{ex.Message}");
                }
            }


            foreach (var l in lines)
            {
                string address;
                string library;
                if (!AndroidLogcatUtilities.ParseCrashLine(regexes, l, out address, out library))
                {
                    output += l;
                }
                else
                {
                    /*
                     * string resolved = string.Format(" <color={0}>(Not resolved)</color>", m_RedColor);
                     * var symbolFile = AndroidLogcatUtilities.GetSymbolFile(symbolPaths, library);
                     * if (string.IsNullOrEmpty(symbolFile))
                     * {
                     *  resolved = string.Format(" <color={0}>({1} not found)</color>", m_RedColor, library);
                     * }
                     * else
                     * {
                     *  try
                     *  {
                     *      var result = tools.RunAddr2Line(symbolFile, new[] { address });
                     *      AndroidLogcatInternalLog.Log("addr2line \"{0}\" {1}", symbolFile, address);
                     *      if (!string.IsNullOrEmpty(result[0]))
                     *          resolved = string.Format(" <color={0}>({1})</color>", m_GreenColor, result[0].Trim());
                     *  }
                     *  catch (Exception ex)
                     *  {
                     *      return string.Format("Exception while running addr2line ('{0}', {1}):\n{2}", symbolFile, address, ex.Message);
                     *  }
                     * }
                     */

                    output += l.Replace(address, address + " " + unresolved.GetAddressValue(library, address));
                }

                output += Environment.NewLine;
            }

            return(output);
        }
        internal static string ResolveAddresses(string[] lines, IReadOnlyList <ReordableListItem> regexes, IReadOnlyList <ReordableListItem> symbolPaths, AndroidTools tools)
        {
            var output = string.Empty;
            // Calling addr2line for every address is costly, that's why we need to do it in batch
            var unresolved = new UnresolvedAddresses();

            foreach (var l in lines)
            {
                string address;
                string library;
                string abi;
                if (!AndroidLogcatUtilities.ParseCrashLine(regexes, l, out abi, out address, out library))
                {
                    continue;
                }
                unresolved.CreateAddressEntry(new UnresolvedAddresses.AddressKey()
                {
                    ABI = abi, Library = library
                }, address);
            }

            var keys = unresolved.GetKeys();

            foreach (var key in keys)
            {
                var addresses  = unresolved.GetAllAddresses(key);
                var symbolFile = AndroidLogcatUtilities.GetSymbolFile(symbolPaths, key.ABI, key.Library);

                // Symbol file not found, set 'not found' messages for all addresses of this library
                if (string.IsNullOrEmpty(symbolFile))
                {
                    var value = $"<color={m_RedColor}>({key.Library} not found)</color>";
                    foreach (var a in addresses)
                    {
                        unresolved.SetAddressValue(key, a, value);
                    }
                    continue;
                }

                try
                {
                    var result = tools.RunAddr2Line(symbolFile, addresses.ToArray());

                    if (result.Length != addresses.Count)
                    {
                        return($"Failed to run addr2line, expected to receive {addresses.Count} addresses, but received {result.Length}");
                    }

                    for (int i = 0; i < addresses.Count; i++)
                    {
                        AndroidLogcatInternalLog.Log($"{addresses[i]} ---> {result[i]}");
                        unresolved.SetAddressValue(key, addresses[i], $"<color={m_GreenColor}>({result[i].Trim()})</color>");
                    }
                }
                catch (Exception ex)
                {
                    return($"Exception while running addr2line:\n{ex.Message}");
                }
            }


            foreach (var l in lines)
            {
                string address;
                string library;
                string abi;
                if (!AndroidLogcatUtilities.ParseCrashLine(regexes, l, out abi, out address, out library))
                {
                    output += l;
                }
                else
                {
                    output += l.Replace(address, address + " " + unresolved.GetAddressValue(new UnresolvedAddresses.AddressKey()
                    {
                        ABI = abi, Library = library
                    }, address));
                }

                output += Environment.NewLine;
            }

            return(output);
        }