Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Unified Diff: experimental/visual_studio_plugin/src/NaClVsx.Package/DebugSupport/NaClSymbolProvider.cs

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
- }
-}

Powered by Google App Engine
This is Rietveld 408576698