public bool LookupSymbol(ulong address, out SymbolInfo sym) { sym.FileName = ""; sym.LineNumber = 0; sym.Symbol = ""; sym.Address = address; DbgHelpNative.SYMBOL_INFO data = new DbgHelpNative.SYMBOL_INFO(); data.SizeOfStruct = (uint) Marshal.SizeOf(data) - 1024; data.MaxNameLen = 1024; ulong displacement; if (DbgHelpNative.SymFromAddr(m_Handle, address, out displacement, ref data)) { sym.Symbol = data.Name; } else { return false; } DbgHelpNative.IMAGEHLP_LINE64 line = new DbgHelpNative.IMAGEHLP_LINE64(); line.SizeOfStruct = (uint) Marshal.SizeOf(line); uint disp32; if (DbgHelpNative.SymGetLineFromAddr64(m_Handle, address, out disp32, ref line)) { StringBuilder fn = new StringBuilder(128); for (int i = 0; ; ++i) { byte b = Marshal.ReadByte(IntPtr.Add(line.FileName, i)); if (0 == b) break; fn.Append((char)b); } sym.FileName = fn.ToString(); sym.LineNumber = (int) line.LineNumber; } else { sym.FileName = "(no source)"; } return true; }
public void Load(string fn) { using (var stream = File.Open(fn, FileMode.Open, FileAccess.Read, FileShare.Read)) { FileSize = stream.Length; // Figure out what the footer looks like using (var br = new BinaryReader(stream, Encoding.UTF8, /*leaveOpen:*/ true)) { // Seek to last 8 bytes. stream.Position = stream.Length - 8; // Read position of footer. long footer_pos = br.ReadInt64(); // Stash length of compressed data preceding the footer. FooterPosition = footer_pos; stream.Position = footer_pos; // Slurp in the serialized footer. uint magic = br.ReadUInt32(); Version = Array.IndexOf(AllMagics, magic); if (Version == -1) throw new IOException(String.Format("Expected decorated stream magic {0:x8}, got {1:x8}. Old file?", V2Magic, magic)); PlatformName = br.ReadString(); PointerSizeBytes = br.ReadInt32(); EventCount = br.ReadInt64(); WireSizeBytes = br.ReadInt64(); SourceMachine = br.ReadString(); MaxTimeStamp = br.ReadUInt64(); TimerFrequency = br.ReadUInt64(); EncodedDataSizeBytes = br.ReadInt64(); { int modcount = br.ReadInt32(); Modules = new List<ModuleInfo>(modcount); for (int i = 0; i < modcount; ++i) { var name = br.ReadString(); var baseaddr = br.ReadUInt64(); var size = br.ReadUInt64(); Modules.Add(new ModuleInfo { Name = name, BaseAddress = baseaddr, SizeBytes = size }); } } { int markcount = br.ReadInt32(); m_Marks.Clear(); for (int i = 0; i < markcount; ++i) { var name = br.ReadString(); var time = br.ReadUInt64(); AddMark(new TraceMark { Name = name, TimeStamp = time }); } } { int symcount = br.ReadInt32(); Symbols = new List<ulong>(symcount); for (int i = 0; i < symcount; ++i) { var addr = br.ReadUInt64(); Symbols.Add(addr); } } { ResolvedSymbols.Clear(); int rsymcount = br.ReadInt32(); for (int i = 0; i < rsymcount; ++i) { var sym = new SymbolInfo(); ulong addr = br.ReadUInt64(); sym.FileName = br.ReadString(); sym.LineNumber = br.ReadInt32(); sym.Symbol = br.ReadString(); ResolvedSymbols[addr] = sym; } } if (Version > 0) { MemTraceInitCommonAddress = br.ReadUInt64(); } if (Version > 1) { ExecutableName = br.ReadString(); WarningCount = br.ReadInt32(); } if (Version > 3) { int warnTextCount = br.ReadInt32(); for (int i = 0; i < warnTextCount; ++i) { Warnings.Add(br.ReadString()); } } } } }
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!"); }