| Index: experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/NaClSymbolProvider.cs
|
| diff --git a/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/NaClSymbolProvider.cs b/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/NaClSymbolProvider.cs
|
| deleted file mode 100644
|
| index a4ae79263700d0e4cbfd7c0228e7fc4f44d73d10..0000000000000000000000000000000000000000
|
| --- a/experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/NaClSymbolProvider.cs
|
| +++ /dev/null
|
| @@ -1,681 +0,0 @@
|
| -// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#region
|
| -
|
| -using System;
|
| -using System.Collections.Generic;
|
| -using System.Diagnostics;
|
| -using System.IO;
|
| -using System.Linq;
|
| -using Google.MsAd7.BaseImpl;
|
| -using Google.MsAd7.BaseImpl.DebugProperties;
|
| -using Google.MsAd7.BaseImpl.Interfaces;
|
| -using Google.MsAd7.BaseImpl.Interfaces.SimpleSymbolTypes;
|
| -using Google.NaClVsx.DebugSupport.DWARF;
|
| -using NaClVsx;
|
| -
|
| -#endregion
|
| -
|
| -namespace Google.NaClVsx.DebugSupport {
|
| - /// <summary>
|
| - /// The NaClSymbolProvider provides generic address and code lookups.
|
| - /// </summary>
|
| - public class NaClSymbolProvider : ISimpleSymbolProvider {
|
| - public NaClSymbolProvider(ISimpleDebugger dbg) {
|
| - BaseAddress = 0;
|
| - dbg_ = dbg;
|
| - }
|
| -
|
| - public ulong BaseAddress { get; set; }
|
| -
|
| - /// <summary>
|
| - /// Internally MSVX uses 0-indexed positions. However, DWARF and MSVC's own user interface
|
| - /// do not. This function exists because having the += 1 and -= 1 calculations all over the
|
| - /// place, is extremely error-prone and confusing.
|
| - /// </summary>
|
| - /// <param name = "dwarfLineIndex">A 1-based index.</param>
|
| - /// <returns>The 0-based index.</returns>
|
| - public static uint GetMSVCLineIndex(uint dwarfLineIndex) {
|
| - return dwarfLineIndex - 1;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Internally MSVX uses 0-indexed positions. However, DWARF and MSVC's own user interface
|
| - /// do not. This function exists because having the += 1 and -= 1 calculations all over the
|
| - /// place, is extremely error-prone and confusing.
|
| - /// </summary>
|
| - /// <param name = "msvcLineIndex">A 0-based index.</param>
|
| - /// <returns>The 1-based index</returns>
|
| - public static uint GetDwarfLineIndex(uint msvcLineIndex) {
|
| - return msvcLineIndex + 1;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Uses a CallFrame record from the Symbol Database to apply a set of
|
| - /// rules to the current registerset, in order to derive the register
|
| - /// state for the next outer stack frame.
|
| - /// This function currently uses a short cut and does not result in a
|
| - /// completely accurate reproduction of the outer frame. Support for
|
| - /// that will require a more detailed implementation of the CFI analysis
|
| - /// specified by DWARF and will be added as a feature later.
|
| - /// </summary>
|
| - /// <param name = "currentRegisters">The state of the registers in the
|
| - /// current call frame.</param>
|
| - /// <returns>The outer callframe's register state.</returns>
|
| - public RegisterSet GetPreviousFrameState(RegisterSet currentRegisters) {
|
| - var rip = currentRegisters["RIP"];
|
| - var pc = rip - BaseAddress;
|
| - if (pc > BaseAddress) {
|
| - return null;
|
| - }
|
| - var frame =
|
| - db_.GetCallFrameForAddress(rip - BaseAddress);
|
| - if (frame == null) {
|
| - return null;
|
| - }
|
| -
|
| - var result = currentRegisters.Clone() as RegisterSet;
|
| - var rules = new Dictionary<int, SymbolDatabase.CallFrame.Rule>();
|
| -
|
| - // Find all of the rules that apply at the current address.
|
| - // Rules are stored in ascending order of address. If two
|
| - // rules exist for the same register, then the one with the
|
| - // highest address wins.
|
| - foreach (var rule in frame.Rules) {
|
| - if (rule.Address > rip) {
|
| - break;
|
| - }
|
| - rules[rule.RegisterId] = rule;
|
| - }
|
| -
|
| - // First we will hit the CFA rule and calculate the value of the previous
|
| - // Frame offset. Once we have that, the rest of the registers are
|
| - // updated using memory locations that are relative to the previous CFA.
|
| - // TODO(mlinck): This seems to end up with stackframes that represent the
|
| - // functions' return locations, not the call site.
|
| - foreach (var rule in rules.Values) {
|
| - switch (rule.RuleType) {
|
| - case IDwarfReader.CfiRuleType.Expression:
|
| - throw new NotImplementedException();
|
| - case IDwarfReader.CfiRuleType.Offset:
|
| - var addr =
|
| - (ulong) ((long) result[rule.BaseRegister] + rule.Offset);
|
| - Debug.WriteLine(
|
| - "SymbolProvider:: result[rule.BaseRegister]: " +
|
| - String.Format(
|
| - "{0,4:X}",
|
| - result[rule.BaseRegister]) +
|
| - " rule.Offset: " + rule.Offset +
|
| - " addr: " + String.Format("{0,4:X}", addr) +
|
| - " rule.Address: " + String.Format(
|
| - "{0,4:X}",
|
| - rule.Address) +
|
| - " BaseAddress: " + String.Format(
|
| - "{0,4:X}",
|
| - BaseAddress));
|
| - var newValue = dbg_.GetU64(addr - BaseAddress);
|
| - result[rule.RegisterId] = newValue;
|
| - break;
|
| - case IDwarfReader.CfiRuleType.Register:
|
| - result[rule.RegisterId] = result[rule.BaseRegister];
|
| - break;
|
| - case IDwarfReader.CfiRuleType.SameValue:
|
| - // this rule seems to exist only to restore values that
|
| - // have gotten munged earlier.
|
| - result[rule.RegisterId] = currentRegisters[rule.RegisterId];
|
| - break;
|
| - case IDwarfReader.CfiRuleType.Undefined:
|
| - // do nothing
|
| - break;
|
| - case IDwarfReader.CfiRuleType.ValExpression:
|
| - throw new NotImplementedException();
|
| - case IDwarfReader.CfiRuleType.ValOffset:
|
| - var baseValue = (long) result[rule.BaseRegister];
|
| - var offset = (long) rule.Offset;
|
| - newValue = (ulong) (baseValue + offset);
|
| - result[rule.RegisterId] = newValue;
|
| - break;
|
| - default:
|
| - throw new IndexOutOfRangeException("Bad rule type for CFI");
|
| - }
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Attempts to determine the symbol type for the symbol at the given address.
|
| - /// </summary>
|
| - /// <param name = "address">An address. Notes: This address needs to be an address of a DIE
|
| - /// for an actual symbol. The address is the address of the DIE in the binary file, also
|
| - /// known as its "key" in the Entries dictionary of the SymbolDatabase</param>
|
| - /// <returns>The windows debugger SymbolType.</returns>
|
| - public SymbolType GetSymbolType(ulong address) {
|
| - var result = new SymbolType {
|
| - Key = 0,
|
| - Name = "unknown",
|
| - SizeOf = 0,
|
| - TypeOf = BaseType.Unknown,
|
| - };
|
| - DebugInfoEntry symbolEntry;
|
| -
|
| - // If we do not find this symbol, then return unknown.
|
| - if (!db_.Entries.TryGetValue(address, out symbolEntry)) {
|
| - return result;
|
| - }
|
| -
|
| -
|
| - if (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_type)) {
|
| - var val =
|
| - (DwarfReference) symbolEntry.Attributes[DwarfAttribute.DW_AT_type];
|
| - result.Key = val.offset;
|
| - } else {
|
| - return result;
|
| - }
|
| - result.Name = "";
|
| - // Process the linked list of modifiers as right associative to the base type;
|
| - while (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_type)) {
|
| - var val =
|
| - (DwarfReference) symbolEntry.Attributes[DwarfAttribute.DW_AT_type];
|
| -
|
| - if (!db_.Entries.TryGetValue(val.offset, out symbolEntry)) {
|
| - result.Key = 0;
|
| - result.Name = null;
|
| - return result;
|
| - }
|
| -
|
| - // Set the size of the symbol to the "right most" sized component such that
|
| - // char *p is size 4 since '*' is size 4.
|
| - if (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_byte_size)) {
|
| - var attrib = symbolEntry.Attributes[DwarfAttribute.DW_AT_byte_size];
|
| - if (0 == result.SizeOf) {
|
| - result.SizeOf = (uint) (ulong) attrib;
|
| - }
|
| - }
|
| -
|
| - switch (symbolEntry.Tag) {
|
| - case DwarfTag.DW_TAG_const_type:
|
| - result.Name = " const" + result.Name;
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_pointer_type:
|
| - result.Name = " *" + result.Name;
|
| - if (BaseType.Unknown == result.TypeOf) {
|
| - result.TypeOf = BaseType.Pointer;
|
| - }
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_reference_type:
|
| - result.Name = " &" + result.Name;
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_volatile_type:
|
| - result.Name = " volatile" + result.Name;
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_restrict_type:
|
| - result.Name = " restrict" + result.Name;
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_base_type:
|
| - result.Name =
|
| - (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
|
| - result.Name;
|
| - if (BaseType.Unknown == result.TypeOf) {
|
| - var enc =
|
| - (DwarfEncoding)
|
| - (ulong) symbolEntry.Attributes[DwarfAttribute.DW_AT_encoding];
|
| - switch (enc) {
|
| - case DwarfEncoding.DW_ATE_address:
|
| - result.TypeOf = BaseType.Pointer;
|
| - break;
|
| -
|
| - case DwarfEncoding.DW_ATE_boolean:
|
| - result.TypeOf = BaseType.Bool;
|
| - break;
|
| -
|
| - case DwarfEncoding.DW_ATE_signed_char:
|
| - case DwarfEncoding.DW_ATE_unsigned_char:
|
| - result.TypeOf = BaseType.Char;
|
| - break;
|
| -
|
| - case DwarfEncoding.DW_ATE_signed:
|
| - result.TypeOf = BaseType.Int;
|
| - break;
|
| -
|
| - case DwarfEncoding.DW_ATE_unsigned:
|
| - result.TypeOf = BaseType.UInt;
|
| - break;
|
| -
|
| - case DwarfEncoding.DW_ATE_float:
|
| - result.TypeOf = BaseType.Float;
|
| - break;
|
| - }
|
| - }
|
| - return result;
|
| -
|
| - case DwarfTag.DW_TAG_structure_type:
|
| - if (symbolEntry.HasAttribute(DwarfAttribute.DW_AT_name)) {
|
| - result.Name =
|
| - (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
|
| - result.Name;
|
| - }
|
| - if (BaseType.Unknown == result.TypeOf) {
|
| - result.TypeOf = BaseType.Struct;
|
| - }
|
| - break;
|
| -
|
| - case DwarfTag.DW_TAG_subroutine_type: {
|
| - result.Name = " (" + result.Name.TrimStart(null) + ")(";
|
| - foreach (
|
| - var parms in
|
| - db_.GetChildrenForEntry(val.offset)) {
|
| - if (parms.Tag == DwarfTag.DW_TAG_formal_parameter) {
|
| - result.Name += GetSymbolType(parms.Key).Name + ", ";
|
| - }
|
| - }
|
| - char[] trim = {',', ' '};
|
| - result.Name = result.Name.TrimEnd(trim) + ")";
|
| - break;
|
| - }
|
| -
|
| - case DwarfTag.DW_TAG_typedef:
|
| - result.Name =
|
| - (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
|
| - result.Name;
|
| - break;
|
| -
|
| - default:
|
| - result.Name = "Parse Err";
|
| - result.Key = 0;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - return result;
|
| - }
|
| -
|
| - #region Implementation of ISimpleSymbolProvider
|
| -
|
| - public IBreakpointInfo GetBreakpointInfo() {
|
| - return new BreakpointInfo(db_, this);
|
| - }
|
| -
|
| - public ulong GetBaseAddress() {
|
| - return BaseAddress;
|
| - }
|
| -
|
| - public IEnumerable<ulong> AddressesFromPosition(DocumentPosition pos) {
|
| - var fname = Path.GetFileName(pos.Path);
|
| - if (!db_.SourceFilesByFilename.ContainsKey(fname)) {
|
| - return null;
|
| - }
|
| -
|
| - var files = db_.SourceFilesByFilename[fname];
|
| -
|
| - if (files.Count() > 1) {
|
| - // TODO(ilewis): disambiguate
|
| - } else if (files.Count() == 0) {
|
| - return null;
|
| - }
|
| -
|
| - // Remember the path that was passed in, since that's where
|
| - // the current debugging session knows where to find this
|
| - // file
|
| - files[0].CurrentAbsolutePath = pos.Path;
|
| -
|
| - // Internally, MSVC uses zero-based lines. This is in contrast
|
| - // to both DWARF and MSVC's own user interface, but whatever.
|
| - //
|
| - var line = pos.BeginPos.dwLine + 1;
|
| -
|
| - return from loc in db_.LocationsByFile[files.First().Key]
|
| - where loc.Line == line
|
| - select loc.StartAddress + BaseAddress;
|
| - }
|
| -
|
| -
|
| - public DocumentPosition PositionFromAddress(ulong address) {
|
| - var loc =
|
| - db_.GetLocationForAddress(address - BaseAddress);
|
| - if (loc != null) {
|
| - // The DWARF line is 1-based; switch to zero-based for MSVC's benefit.
|
| - var line = loc.Line - 1;
|
| - return
|
| - new DocumentPosition(
|
| - db_.Files[loc.SourceFileKey].CurrentAbsolutePath, line);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - public IEnumerable<UInt64> GetAddressesInScope(UInt64 programCounter) {
|
| - var result = new List<UInt64>();
|
| - programCounter -= BaseAddress;
|
| -
|
| - // Get the scope, current function, and frame pointer
|
| - var scopeEntry =
|
| - db_.GetScopeForAddress(programCounter);
|
| - if (scopeEntry == null) {
|
| - return result;
|
| - }
|
| -
|
| - // Find the parent most DIE which represents this function
|
| - var fnEntry = scopeEntry;
|
| - while (fnEntry.Tag != DwarfTag.DW_TAG_subprogram
|
| - && fnEntry.OuterScope != null) {
|
| - fnEntry = fnEntry.OuterScope;
|
| - }
|
| -
|
| - var functionLowPC =
|
| - (ulong)
|
| - fnEntry.Attributes.GetValueOrDefault(DwarfAttribute.DW_AT_low_pc, 0);
|
| - var fnMax =
|
| - (ulong)
|
| - fnEntry.Attributes.GetValueOrDefault(DwarfAttribute.DW_AT_high_pc, 0);
|
| -
|
| -
|
| - functionLowPC += BaseAddress;
|
| - fnMax += BaseAddress;
|
| - while (functionLowPC < fnMax) {
|
| - result.Add(functionLowPC);
|
| - functionLowPC = GetNextLocation(functionLowPC);
|
| - }
|
| -
|
| - return result;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// This function retrieves the DebugInformationEntries for symbols that
|
| - /// are in scope at a given instruction address.
|
| - /// </summary>
|
| - /// <param name = "instructionAddress">The address for whose scope symbols
|
| - /// are being requested.</param>
|
| - /// <returns>A list of symbol descriptors for all the symbols that are in
|
| - /// scope at this location in the program.</returns>
|
| - public IEnumerable<Symbol> GetSymbolsInScope(ulong instructionAddress) {
|
| - var result = new List<Symbol>();
|
| - // Adjust for the base of the untrusted code space.
|
| - instructionAddress -= BaseAddress;
|
| -
|
| - // Get the scope, current function, and frame pointer. The frame pointer
|
| - // will be used to determine what source code location applies to our
|
| - // current scope.
|
| - var scopeEntry = db_.GetScopeForAddress(instructionAddress);
|
| - if (scopeEntry == null) {
|
| - return result;
|
| - }
|
| - var functionEntry =
|
| - scopeEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_subprogram);
|
| - var functionFrameBase = functionEntry.GetFrameBase();
|
| -
|
| - // The code locations are given addresses relative to the compilation
|
| - // unit that contains them, so we have to make sure we can come up with
|
| - // that same offset.
|
| - var compilationUnitEntry =
|
| - functionEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_compile_unit);
|
| - ulong compilationUnitLowPC = 0;
|
| - if (compilationUnitEntry.HasAttribute(DwarfAttribute.DW_AT_low_pc)) {
|
| - compilationUnitLowPC = compilationUnitEntry.GetLowPC();
|
| - } else if (compilationUnitEntry.HasAttribute(DwarfAttribute.DW_AT_ranges)) {
|
| - // This should never really happen. In case it does, it warrants some
|
| - // explanation. The reason we look for the functionFrameBase is because
|
| - // we need the rangelist entry for the location of the function, within
|
| - // the compilation unit. Any addresses in nested scopes would then be
|
| - // treated as relative addresses to that offset.
|
| - var rangeListEntry = db_.GetRangeForAddress(functionFrameBase, compilationUnitEntry);
|
| - if (rangeListEntry != null) {
|
| - compilationUnitLowPC += rangeListEntry.LowPC;
|
| - }
|
| - }
|
| -
|
| - var codeAddress = instructionAddress - compilationUnitLowPC;
|
| - // The VM inputs object handles feeding the VM whatever it asks for.
|
| - // This VM will execute the DWARF state machine to do any necessary
|
| - // low-level address calculations.
|
| - var vmInputs = new VirtualMachineInputs(dbg_, 0);
|
| - PrimeVMInputs(codeAddress, functionFrameBase, vmInputs);
|
| -
|
| - while (scopeEntry != null) {
|
| - foreach (
|
| - var entry in
|
| - db_.GetChildrenForEntry(scopeEntry.Key)) {
|
| - // The assumption here is that all useful symbols have a location and
|
| - // a name.
|
| - if (entry.Attributes.ContainsKey(DwarfAttribute.DW_AT_location)
|
| - && entry.Attributes.ContainsKey(DwarfAttribute.DW_AT_name)) {
|
| - var name = (string) entry.Attributes[DwarfAttribute.DW_AT_name];
|
| - var loc = entry.Attributes[DwarfAttribute.DW_AT_location] as byte[];
|
| - // Program counter will not be used by ResolveLocation in this case
|
| - // because the loc we're handing in is always a byte array.
|
| - var symbolAddr = ResolveLocation(loc, vmInputs);
|
| - // store the symbolAddr and variable name. Note that symbolAddr is
|
| - // relative to the base address of the NaCl app. The base address
|
| - // is something like 0xC00000000, but the base gets added to this
|
| - // relative address (symbolAddr) later in functions like GetMemory
|
| - // (located in NaClDebugger.cs).
|
| - result.Add(
|
| - new Symbol {
|
| - Key = entry.Key,
|
| - Name = name,
|
| - Offset = symbolAddr,
|
| - TypeOf = GetSymbolType(entry.Key)
|
| - });
|
| - }
|
| - }
|
| - scopeEntry = scopeEntry.OuterScope;
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Determines what function the given address is in.
|
| - /// </summary>
|
| - /// <param name = "address">The address whose function is needed.</param>
|
| - /// <returns>The windows debugger representation of the containing function.</returns>
|
| - public Function FunctionFromAddress(ulong address) {
|
| - var result = new Function {
|
| - Id = 0,
|
| - Name = "<unknown function>",
|
| - };
|
| -
|
| - var scopeEntry =
|
| - db_.GetScopeForAddress(address - BaseAddress);
|
| - if (null != scopeEntry) {
|
| - var fnEntry =
|
| - scopeEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_subprogram);
|
| - if (null != fnEntry) {
|
| - result.Id = fnEntry.Key;
|
| - result.Name =
|
| - (string) fnEntry.Attributes[DwarfAttribute.DW_AT_name];
|
| - }
|
| - }
|
| -
|
| - return result;
|
| - }
|
| -
|
| - public FunctionDetails GetFunctionDetails(Function fn) {
|
| - throw new NotImplementedException();
|
| - }
|
| -
|
| - public bool LoadModule(string path, ulong loadOffset, out string status) {
|
| - // TODO(ilewis): this should be per-module, not per-database (unless
|
| - // we decide to make database a per-module thing too)
|
| - BaseAddress = loadOffset;
|
| - try {
|
| - DwarfParser.DwarfParseElf(path, new DwarfReaderImpl(db_));
|
| - db_.BuildIndices();
|
| - status = "ELF/DWARF symbols loaded";
|
| - return true;
|
| - }
|
| - catch (Exception e) {
|
| - status = e.Message;
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - public ulong GetNextLocation(ulong addr) {
|
| - var loc =
|
| - db_.GetLocationForAddress(addr - BaseAddress);
|
| - return loc.StartAddress + loc.Length + BaseAddress;
|
| - }
|
| -
|
| - #endregion
|
| -
|
| - #region ISimpleSymbolProvider Members
|
| -
|
| - public String SymbolValueToString(ulong key, ArraySegment<Byte> arrBytes) {
|
| - var result = GetSymbolType(key);
|
| - var bytes = arrBytes.Array;
|
| -
|
| - // If we don't have enough data
|
| - if (bytes.Count() < result.SizeOf) {
|
| - return "INVALID";
|
| - }
|
| -
|
| - // Or if we were unable to determine the type
|
| - if (result.TypeOf == BaseType.Unknown) {
|
| - return "INVALID";
|
| - }
|
| -
|
| - Int64 i64 = 0;
|
| - double d64 = 0;
|
| -
|
| - try {
|
| - switch (result.SizeOf) {
|
| - case 1:
|
| - // We don't need to convert to number first because the switch
|
| - // statement below will convert byte[0] to string val.
|
| - break;
|
| -
|
| - case 2:
|
| - i64 = BitConverter.ToInt16(bytes, 0);
|
| - break;
|
| -
|
| - case 4:
|
| - i64 = BitConverter.ToInt32(bytes, 0);
|
| - d64 = BitConverter.ToSingle(bytes, 0);
|
| - break;
|
| -
|
| - case 8:
|
| - i64 = BitConverter.ToInt64(bytes, 0);
|
| - d64 = BitConverter.ToDouble(bytes, 0);
|
| - break;
|
| - }
|
| - }
|
| - catch (Exception e) {
|
| - // Without a catch here, the VSX SDK catches the exception and we
|
| - // just don't get a value back... Printing helps us realize this
|
| - // is happening (when we had a bad conversion for case 1 previously)
|
| - // and also lets us set a breakpoint inside the catch.
|
| - Debug.WriteLine(
|
| - "An exception was caught when calling BitConverter!" +
|
| - e);
|
| - }
|
| -
|
| -
|
| - var typeInfo = result.TypeOf;
|
| - Debug.WriteLine("typeOf: " + typeInfo + " size: " + result.SizeOf);
|
| - switch (result.TypeOf) {
|
| - case BaseType.Pointer:
|
| - return i64.ToString("X");
|
| -
|
| - case BaseType.Bool:
|
| - if (0 != i64) {
|
| - return "True";
|
| - } else {
|
| - return "False";
|
| - }
|
| -
|
| - case BaseType.Char:
|
| - return bytes[0].ToString();
|
| -
|
| - case BaseType.Int:
|
| - return i64.ToString();
|
| -
|
| - case BaseType.UInt:
|
| - return ((UInt64) i64).ToString();
|
| -
|
| - case BaseType.Float:
|
| - return d64.ToString();
|
| -
|
| - case BaseType.Struct:
|
| - return "{" + result.Name + "}";
|
| - }
|
| - return "INVALID";
|
| - }
|
| -
|
| - #endregion
|
| -
|
| - #region Private Implementation
|
| -
|
| - readonly SymbolDatabase db_ = new SymbolDatabase();
|
| - private readonly ISimpleDebugger dbg_;
|
| -
|
| - #endregion
|
| -
|
| - #region Private Implementation
|
| -
|
| - /// <summary>
|
| - /// Calculates the address on the stack, of a given location in the
|
| - /// instruction queue.
|
| - /// </summary>
|
| - /// <param name = "loc">The location in the instruction space.</param>
|
| - /// <param name = "vm">The virtual machine that is to be used to calculate
|
| - /// the stack address. It must be primed with context.</param>
|
| - /// <returns>The stack address corresponding to loc.</returns>
|
| - private static ulong ResolveLocation(byte[] loc,
|
| - VirtualMachineInputs vm) {
|
| - if (vm == null) {
|
| - throw new ArgumentNullException("vm");
|
| - }
|
| - // A byte[] location is a Dwarf VM program, not an actual location.
|
| - // We need to run the VM and (possibly) supply inputs.
|
| - var stackAddress = DwarfParser.DwarfParseVM(vm, loc);
|
| -
|
| - if (stackAddress < (ulong) DwarfOpcode.DW_OP_regX) {
|
| - Debug.WriteLine("WARNING: Register vars not currently supported");
|
| - }
|
| - return stackAddress;
|
| - }
|
| -
|
| - /// <summary>
|
| - /// Primes the inputs that will be handed to the DWARF VM, by giving it
|
| - /// relevant context.
|
| - /// </summary>
|
| - /// <param name = "codeAddress">The code address for which context will be
|
| - /// needed.</param>
|
| - /// <param name = "functionFrameBase">The frame base of the function that
|
| - /// contains the code address.</param>
|
| - /// <param name = "vmInputs">This parameter is modified. It is primed with
|
| - /// A framebase that is calculated for the current context so that future
|
| - /// DWARF address calculations can be peformed.</param>
|
| - private void PrimeVMInputs(ulong codeAddress,
|
| - ulong functionFrameBase,
|
| - VirtualMachineInputs vmInputs) {
|
| - var frameBase = ulong.MaxValue;
|
| - var loclist =
|
| - db_.LocLists[functionFrameBase];
|
| - foreach (var locListEntry in loclist) {
|
| - if (locListEntry.StartAddress == ulong.MaxValue) {
|
| - frameBase = locListEntry.EndAddress;
|
| - break;
|
| - }
|
| - // Try to determine whether this is the address of a symbol and
|
| - // return the referenced address in memory.
|
| - if (locListEntry.StartAddress <= codeAddress
|
| - && codeAddress <= locListEntry.EndAddress) {
|
| - frameBase = DwarfParser.DwarfParseVM(vmInputs, locListEntry.Data);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (frameBase < (ulong) DwarfOpcode.DW_OP_regX) {
|
| - Debug.WriteLine("WARNING: Register vars not currently supported");
|
| - }
|
| - vmInputs.FrameBase = frameBase;
|
| - }
|
| -
|
| - #endregion
|
| - }
|
| -}
|
|
|