Exemple #1
0
    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;
    }
Exemple #2
0
    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!");

    }