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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #region
6
7 using System;
8 using System.Collections.Generic;
9 using System.Diagnostics;
10 using System.IO;
11 using System.Linq;
12 using Google.MsAd7.BaseImpl;
13 using Google.MsAd7.BaseImpl.DebugProperties;
14 using Google.MsAd7.BaseImpl.Interfaces;
15 using Google.MsAd7.BaseImpl.Interfaces.SimpleSymbolTypes;
16 using Google.NaClVsx.DebugSupport.DWARF;
17 using NaClVsx;
18
19 #endregion
20
21 namespace Google.NaClVsx.DebugSupport {
22 /// <summary>
23 /// The NaClSymbolProvider provides generic address and code lookups.
24 /// </summary>
25 public class NaClSymbolProvider : ISimpleSymbolProvider {
26 public NaClSymbolProvider(ISimpleDebugger dbg) {
27 BaseAddress = 0;
28 dbg_ = dbg;
29 }
30
31 public ulong BaseAddress { get; set; }
32
33 /// <summary>
34 /// Internally MSVX uses 0-indexed positions. However, DWARF and MSVC's ow n user interface
35 /// do not. This function exists because having the += 1 and -= 1 calcula tions all over the
36 /// place, is extremely error-prone and confusing.
37 /// </summary>
38 /// <param name = "dwarfLineIndex">A 1-based index.</param>
39 /// <returns>The 0-based index.</returns>
40 public static uint GetMSVCLineIndex(uint dwarfLineIndex) {
41 return dwarfLineIndex - 1;
42 }
43
44 /// <summary>
45 /// Internally MSVX uses 0-indexed positions. However, DWARF and MSVC's ow n user interface
46 /// do not. This function exists because having the += 1 and -= 1 calcula tions all over the
47 /// place, is extremely error-prone and confusing.
48 /// </summary>
49 /// <param name = "msvcLineIndex">A 0-based index.</param>
50 /// <returns>The 1-based index</returns>
51 public static uint GetDwarfLineIndex(uint msvcLineIndex) {
52 return msvcLineIndex + 1;
53 }
54
55 /// <summary>
56 /// Uses a CallFrame record from the Symbol Database to apply a set of
57 /// rules to the current registerset, in order to derive the register
58 /// state for the next outer stack frame.
59 /// This function currently uses a short cut and does not result in a
60 /// completely accurate reproduction of the outer frame. Support for
61 /// that will require a more detailed implementation of the CFI analysis
62 /// specified by DWARF and will be added as a feature later.
63 /// </summary>
64 /// <param name = "currentRegisters">The state of the registers in the
65 /// current call frame.</param>
66 /// <returns>The outer callframe's register state.</returns>
67 public RegisterSet GetPreviousFrameState(RegisterSet currentRegisters) {
68 var rip = currentRegisters["RIP"];
69 var pc = rip - BaseAddress;
70 if (pc > BaseAddress) {
71 return null;
72 }
73 var frame =
74 db_.GetCallFrameForAddress(rip - BaseAddress);
75 if (frame == null) {
76 return null;
77 }
78
79 var result = currentRegisters.Clone() as RegisterSet;
80 var rules = new Dictionary<int, SymbolDatabase.CallFrame.Rule>();
81
82 // Find all of the rules that apply at the current address.
83 // Rules are stored in ascending order of address. If two
84 // rules exist for the same register, then the one with the
85 // highest address wins.
86 foreach (var rule in frame.Rules) {
87 if (rule.Address > rip) {
88 break;
89 }
90 rules[rule.RegisterId] = rule;
91 }
92
93 // First we will hit the CFA rule and calculate the value of the previous
94 // Frame offset. Once we have that, the rest of the registers are
95 // updated using memory locations that are relative to the previous CFA.
96 // TODO(mlinck): This seems to end up with stackframes that represent the
97 // functions' return locations, not the call site.
98 foreach (var rule in rules.Values) {
99 switch (rule.RuleType) {
100 case IDwarfReader.CfiRuleType.Expression:
101 throw new NotImplementedException();
102 case IDwarfReader.CfiRuleType.Offset:
103 var addr =
104 (ulong) ((long) result[rule.BaseRegister] + rule.Offset);
105 Debug.WriteLine(
106 "SymbolProvider:: result[rule.BaseRegister]: " +
107 String.Format(
108 "{0,4:X}",
109 result[rule.BaseRegister]) +
110 " rule.Offset: " + rule.Offset +
111 " addr: " + String.Format("{0,4:X}", addr) +
112 " rule.Address: " + String.Format(
113 "{0,4:X}",
114 rule.Address) +
115 " BaseAddress: " + String.Format(
116 "{0,4:X}",
117 BaseAddress));
118 var newValue = dbg_.GetU64(addr - BaseAddress);
119 result[rule.RegisterId] = newValue;
120 break;
121 case IDwarfReader.CfiRuleType.Register:
122 result[rule.RegisterId] = result[rule.BaseRegister];
123 break;
124 case IDwarfReader.CfiRuleType.SameValue:
125 // this rule seems to exist only to restore values that
126 // have gotten munged earlier.
127 result[rule.RegisterId] = currentRegisters[rule.RegisterId];
128 break;
129 case IDwarfReader.CfiRuleType.Undefined:
130 // do nothing
131 break;
132 case IDwarfReader.CfiRuleType.ValExpression:
133 throw new NotImplementedException();
134 case IDwarfReader.CfiRuleType.ValOffset:
135 var baseValue = (long) result[rule.BaseRegister];
136 var offset = (long) rule.Offset;
137 newValue = (ulong) (baseValue + offset);
138 result[rule.RegisterId] = newValue;
139 break;
140 default:
141 throw new IndexOutOfRangeException("Bad rule type for CFI");
142 }
143 }
144 return result;
145 }
146
147 /// <summary>
148 /// Attempts to determine the symbol type for the symbol at the given addr ess.
149 /// </summary>
150 /// <param name = "address">An address. Notes: This address needs to be an address of a DIE
151 /// for an actual symbol. The address is the address of the DIE in the bi nary file, also
152 /// known as its "key" in the Entries dictionary of the SymbolDatabase</pa ram>
153 /// <returns>The windows debugger SymbolType.</returns>
154 public SymbolType GetSymbolType(ulong address) {
155 var result = new SymbolType {
156 Key = 0,
157 Name = "unknown",
158 SizeOf = 0,
159 TypeOf = BaseType.Unknown,
160 };
161 DebugInfoEntry symbolEntry;
162
163 // If we do not find this symbol, then return unknown.
164 if (!db_.Entries.TryGetValue(address, out symbolEntry)) {
165 return result;
166 }
167
168
169 if (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_type)) {
170 var val =
171 (DwarfReference) symbolEntry.Attributes[DwarfAttribute.DW_AT_type];
172 result.Key = val.offset;
173 } else {
174 return result;
175 }
176 result.Name = "";
177 // Process the linked list of modifiers as right associative to the base t ype;
178 while (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_type)) {
179 var val =
180 (DwarfReference) symbolEntry.Attributes[DwarfAttribute.DW_AT_type];
181
182 if (!db_.Entries.TryGetValue(val.offset, out symbolEntry)) {
183 result.Key = 0;
184 result.Name = null;
185 return result;
186 }
187
188 // Set the size of the symbol to the "right most" sized component such t hat
189 // char *p is size 4 since '*' is size 4.
190 if (symbolEntry.Attributes.ContainsKey(DwarfAttribute.DW_AT_byte_size)) {
191 var attrib = symbolEntry.Attributes[DwarfAttribute.DW_AT_byte_size];
192 if (0 == result.SizeOf) {
193 result.SizeOf = (uint) (ulong) attrib;
194 }
195 }
196
197 switch (symbolEntry.Tag) {
198 case DwarfTag.DW_TAG_const_type:
199 result.Name = " const" + result.Name;
200 break;
201
202 case DwarfTag.DW_TAG_pointer_type:
203 result.Name = " *" + result.Name;
204 if (BaseType.Unknown == result.TypeOf) {
205 result.TypeOf = BaseType.Pointer;
206 }
207 break;
208
209 case DwarfTag.DW_TAG_reference_type:
210 result.Name = " &" + result.Name;
211 break;
212
213 case DwarfTag.DW_TAG_volatile_type:
214 result.Name = " volatile" + result.Name;
215 break;
216
217 case DwarfTag.DW_TAG_restrict_type:
218 result.Name = " restrict" + result.Name;
219 break;
220
221 case DwarfTag.DW_TAG_base_type:
222 result.Name =
223 (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
224 result.Name;
225 if (BaseType.Unknown == result.TypeOf) {
226 var enc =
227 (DwarfEncoding)
228 (ulong) symbolEntry.Attributes[DwarfAttribute.DW_AT_encoding];
229 switch (enc) {
230 case DwarfEncoding.DW_ATE_address:
231 result.TypeOf = BaseType.Pointer;
232 break;
233
234 case DwarfEncoding.DW_ATE_boolean:
235 result.TypeOf = BaseType.Bool;
236 break;
237
238 case DwarfEncoding.DW_ATE_signed_char:
239 case DwarfEncoding.DW_ATE_unsigned_char:
240 result.TypeOf = BaseType.Char;
241 break;
242
243 case DwarfEncoding.DW_ATE_signed:
244 result.TypeOf = BaseType.Int;
245 break;
246
247 case DwarfEncoding.DW_ATE_unsigned:
248 result.TypeOf = BaseType.UInt;
249 break;
250
251 case DwarfEncoding.DW_ATE_float:
252 result.TypeOf = BaseType.Float;
253 break;
254 }
255 }
256 return result;
257
258 case DwarfTag.DW_TAG_structure_type:
259 if (symbolEntry.HasAttribute(DwarfAttribute.DW_AT_name)) {
260 result.Name =
261 (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
262 result.Name;
263 }
264 if (BaseType.Unknown == result.TypeOf) {
265 result.TypeOf = BaseType.Struct;
266 }
267 break;
268
269 case DwarfTag.DW_TAG_subroutine_type: {
270 result.Name = " (" + result.Name.TrimStart(null) + ")(";
271 foreach (
272 var parms in
273 db_.GetChildrenForEntry(val.offset)) {
274 if (parms.Tag == DwarfTag.DW_TAG_formal_parameter) {
275 result.Name += GetSymbolType(parms.Key).Name + ", ";
276 }
277 }
278 char[] trim = {',', ' '};
279 result.Name = result.Name.TrimEnd(trim) + ")";
280 break;
281 }
282
283 case DwarfTag.DW_TAG_typedef:
284 result.Name =
285 (string) symbolEntry.Attributes[DwarfAttribute.DW_AT_name] +
286 result.Name;
287 break;
288
289 default:
290 result.Name = "Parse Err";
291 result.Key = 0;
292 break;
293 }
294 }
295
296 return result;
297 }
298
299 #region Implementation of ISimpleSymbolProvider
300
301 public IBreakpointInfo GetBreakpointInfo() {
302 return new BreakpointInfo(db_, this);
303 }
304
305 public ulong GetBaseAddress() {
306 return BaseAddress;
307 }
308
309 public IEnumerable<ulong> AddressesFromPosition(DocumentPosition pos) {
310 var fname = Path.GetFileName(pos.Path);
311 if (!db_.SourceFilesByFilename.ContainsKey(fname)) {
312 return null;
313 }
314
315 var files = db_.SourceFilesByFilename[fname];
316
317 if (files.Count() > 1) {
318 // TODO(ilewis): disambiguate
319 } else if (files.Count() == 0) {
320 return null;
321 }
322
323 // Remember the path that was passed in, since that's where
324 // the current debugging session knows where to find this
325 // file
326 files[0].CurrentAbsolutePath = pos.Path;
327
328 // Internally, MSVC uses zero-based lines. This is in contrast
329 // to both DWARF and MSVC's own user interface, but whatever.
330 //
331 var line = pos.BeginPos.dwLine + 1;
332
333 return from loc in db_.LocationsByFile[files.First().Key]
334 where loc.Line == line
335 select loc.StartAddress + BaseAddress;
336 }
337
338
339 public DocumentPosition PositionFromAddress(ulong address) {
340 var loc =
341 db_.GetLocationForAddress(address - BaseAddress);
342 if (loc != null) {
343 // The DWARF line is 1-based; switch to zero-based for MSVC's benefit.
344 var line = loc.Line - 1;
345 return
346 new DocumentPosition(
347 db_.Files[loc.SourceFileKey].CurrentAbsolutePath, line);
348 }
349 return null;
350 }
351
352 public IEnumerable<UInt64> GetAddressesInScope(UInt64 programCounter) {
353 var result = new List<UInt64>();
354 programCounter -= BaseAddress;
355
356 // Get the scope, current function, and frame pointer
357 var scopeEntry =
358 db_.GetScopeForAddress(programCounter);
359 if (scopeEntry == null) {
360 return result;
361 }
362
363 // Find the parent most DIE which represents this function
364 var fnEntry = scopeEntry;
365 while (fnEntry.Tag != DwarfTag.DW_TAG_subprogram
366 && fnEntry.OuterScope != null) {
367 fnEntry = fnEntry.OuterScope;
368 }
369
370 var functionLowPC =
371 (ulong)
372 fnEntry.Attributes.GetValueOrDefault(DwarfAttribute.DW_AT_low_pc, 0);
373 var fnMax =
374 (ulong)
375 fnEntry.Attributes.GetValueOrDefault(DwarfAttribute.DW_AT_high_pc, 0);
376
377
378 functionLowPC += BaseAddress;
379 fnMax += BaseAddress;
380 while (functionLowPC < fnMax) {
381 result.Add(functionLowPC);
382 functionLowPC = GetNextLocation(functionLowPC);
383 }
384
385 return result;
386 }
387
388 /// <summary>
389 /// This function retrieves the DebugInformationEntries for symbols that
390 /// are in scope at a given instruction address.
391 /// </summary>
392 /// <param name = "instructionAddress">The address for whose scope symbols
393 /// are being requested.</param>
394 /// <returns>A list of symbol descriptors for all the symbols that are in
395 /// scope at this location in the program.</returns>
396 public IEnumerable<Symbol> GetSymbolsInScope(ulong instructionAddress) {
397 var result = new List<Symbol>();
398 // Adjust for the base of the untrusted code space.
399 instructionAddress -= BaseAddress;
400
401 // Get the scope, current function, and frame pointer. The frame pointer
402 // will be used to determine what source code location applies to our
403 // current scope.
404 var scopeEntry = db_.GetScopeForAddress(instructionAddress);
405 if (scopeEntry == null) {
406 return result;
407 }
408 var functionEntry =
409 scopeEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_subprogram);
410 var functionFrameBase = functionEntry.GetFrameBase();
411
412 // The code locations are given addresses relative to the compilation
413 // unit that contains them, so we have to make sure we can come up with
414 // that same offset.
415 var compilationUnitEntry =
416 functionEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_compile_unit);
417 ulong compilationUnitLowPC = 0;
418 if (compilationUnitEntry.HasAttribute(DwarfAttribute.DW_AT_low_pc)) {
419 compilationUnitLowPC = compilationUnitEntry.GetLowPC();
420 } else if (compilationUnitEntry.HasAttribute(DwarfAttribute.DW_AT_ranges)) {
421 // This should never really happen. In case it does, it warrants some
422 // explanation. The reason we look for the functionFrameBase is because
423 // we need the rangelist entry for the location of the function, within
424 // the compilation unit. Any addresses in nested scopes would then be
425 // treated as relative addresses to that offset.
426 var rangeListEntry = db_.GetRangeForAddress(functionFrameBase, compilati onUnitEntry);
427 if (rangeListEntry != null) {
428 compilationUnitLowPC += rangeListEntry.LowPC;
429 }
430 }
431
432 var codeAddress = instructionAddress - compilationUnitLowPC;
433 // The VM inputs object handles feeding the VM whatever it asks for.
434 // This VM will execute the DWARF state machine to do any necessary
435 // low-level address calculations.
436 var vmInputs = new VirtualMachineInputs(dbg_, 0);
437 PrimeVMInputs(codeAddress, functionFrameBase, vmInputs);
438
439 while (scopeEntry != null) {
440 foreach (
441 var entry in
442 db_.GetChildrenForEntry(scopeEntry.Key)) {
443 // The assumption here is that all useful symbols have a location and
444 // a name.
445 if (entry.Attributes.ContainsKey(DwarfAttribute.DW_AT_location)
446 && entry.Attributes.ContainsKey(DwarfAttribute.DW_AT_name)) {
447 var name = (string) entry.Attributes[DwarfAttribute.DW_AT_name];
448 var loc = entry.Attributes[DwarfAttribute.DW_AT_location] as byte[];
449 // Program counter will not be used by ResolveLocation in this case
450 // because the loc we're handing in is always a byte array.
451 var symbolAddr = ResolveLocation(loc, vmInputs);
452 // store the symbolAddr and variable name. Note that symbolAddr is
453 // relative to the base address of the NaCl app. The base address
454 // is something like 0xC00000000, but the base gets added to this
455 // relative address (symbolAddr) later in functions like GetMemory
456 // (located in NaClDebugger.cs).
457 result.Add(
458 new Symbol {
459 Key = entry.Key,
460 Name = name,
461 Offset = symbolAddr,
462 TypeOf = GetSymbolType(entry.Key)
463 });
464 }
465 }
466 scopeEntry = scopeEntry.OuterScope;
467 }
468 return result;
469 }
470
471 /// <summary>
472 /// Determines what function the given address is in.
473 /// </summary>
474 /// <param name = "address">The address whose function is needed.</param>
475 /// <returns>The windows debugger representation of the containing function. </returns>
476 public Function FunctionFromAddress(ulong address) {
477 var result = new Function {
478 Id = 0,
479 Name = "<unknown function>",
480 };
481
482 var scopeEntry =
483 db_.GetScopeForAddress(address - BaseAddress);
484 if (null != scopeEntry) {
485 var fnEntry =
486 scopeEntry.GetNearestAncestorWithTag(DwarfTag.DW_TAG_subprogram);
487 if (null != fnEntry) {
488 result.Id = fnEntry.Key;
489 result.Name =
490 (string) fnEntry.Attributes[DwarfAttribute.DW_AT_name];
491 }
492 }
493
494 return result;
495 }
496
497 public FunctionDetails GetFunctionDetails(Function fn) {
498 throw new NotImplementedException();
499 }
500
501 public bool LoadModule(string path, ulong loadOffset, out string status) {
502 // TODO(ilewis): this should be per-module, not per-database (unless
503 // we decide to make database a per-module thing too)
504 BaseAddress = loadOffset;
505 try {
506 DwarfParser.DwarfParseElf(path, new DwarfReaderImpl(db_));
507 db_.BuildIndices();
508 status = "ELF/DWARF symbols loaded";
509 return true;
510 }
511 catch (Exception e) {
512 status = e.Message;
513 return false;
514 }
515 }
516
517 public ulong GetNextLocation(ulong addr) {
518 var loc =
519 db_.GetLocationForAddress(addr - BaseAddress);
520 return loc.StartAddress + loc.Length + BaseAddress;
521 }
522
523 #endregion
524
525 #region ISimpleSymbolProvider Members
526
527 public String SymbolValueToString(ulong key, ArraySegment<Byte> arrBytes) {
528 var result = GetSymbolType(key);
529 var bytes = arrBytes.Array;
530
531 // If we don't have enough data
532 if (bytes.Count() < result.SizeOf) {
533 return "INVALID";
534 }
535
536 // Or if we were unable to determine the type
537 if (result.TypeOf == BaseType.Unknown) {
538 return "INVALID";
539 }
540
541 Int64 i64 = 0;
542 double d64 = 0;
543
544 try {
545 switch (result.SizeOf) {
546 case 1:
547 // We don't need to convert to number first because the switch
548 // statement below will convert byte[0] to string val.
549 break;
550
551 case 2:
552 i64 = BitConverter.ToInt16(bytes, 0);
553 break;
554
555 case 4:
556 i64 = BitConverter.ToInt32(bytes, 0);
557 d64 = BitConverter.ToSingle(bytes, 0);
558 break;
559
560 case 8:
561 i64 = BitConverter.ToInt64(bytes, 0);
562 d64 = BitConverter.ToDouble(bytes, 0);
563 break;
564 }
565 }
566 catch (Exception e) {
567 // Without a catch here, the VSX SDK catches the exception and we
568 // just don't get a value back... Printing helps us realize this
569 // is happening (when we had a bad conversion for case 1 previously)
570 // and also lets us set a breakpoint inside the catch.
571 Debug.WriteLine(
572 "An exception was caught when calling BitConverter!" +
573 e);
574 }
575
576
577 var typeInfo = result.TypeOf;
578 Debug.WriteLine("typeOf: " + typeInfo + " size: " + result.SizeOf);
579 switch (result.TypeOf) {
580 case BaseType.Pointer:
581 return i64.ToString("X");
582
583 case BaseType.Bool:
584 if (0 != i64) {
585 return "True";
586 } else {
587 return "False";
588 }
589
590 case BaseType.Char:
591 return bytes[0].ToString();
592
593 case BaseType.Int:
594 return i64.ToString();
595
596 case BaseType.UInt:
597 return ((UInt64) i64).ToString();
598
599 case BaseType.Float:
600 return d64.ToString();
601
602 case BaseType.Struct:
603 return "{" + result.Name + "}";
604 }
605 return "INVALID";
606 }
607
608 #endregion
609
610 #region Private Implementation
611
612 readonly SymbolDatabase db_ = new SymbolDatabase();
613 private readonly ISimpleDebugger dbg_;
614
615 #endregion
616
617 #region Private Implementation
618
619 /// <summary>
620 /// Calculates the address on the stack, of a given location in the
621 /// instruction queue.
622 /// </summary>
623 /// <param name = "loc">The location in the instruction space.</param>
624 /// <param name = "vm">The virtual machine that is to be used to calculate
625 /// the stack address. It must be primed with context.</param>
626 /// <returns>The stack address corresponding to loc.</returns>
627 private static ulong ResolveLocation(byte[] loc,
628 VirtualMachineInputs vm) {
629 if (vm == null) {
630 throw new ArgumentNullException("vm");
631 }
632 // A byte[] location is a Dwarf VM program, not an actual location.
633 // We need to run the VM and (possibly) supply inputs.
634 var stackAddress = DwarfParser.DwarfParseVM(vm, loc);
635
636 if (stackAddress < (ulong) DwarfOpcode.DW_OP_regX) {
637 Debug.WriteLine("WARNING: Register vars not currently supported");
638 }
639 return stackAddress;
640 }
641
642 /// <summary>
643 /// Primes the inputs that will be handed to the DWARF VM, by giving it
644 /// relevant context.
645 /// </summary>
646 /// <param name = "codeAddress">The code address for which context will be
647 /// needed.</param>
648 /// <param name = "functionFrameBase">The frame base of the function that
649 /// contains the code address.</param>
650 /// <param name = "vmInputs">This parameter is modified. It is primed with
651 /// A framebase that is calculated for the current context so that future
652 /// DWARF address calculations can be peformed.</param>
653 private void PrimeVMInputs(ulong codeAddress,
654 ulong functionFrameBase,
655 VirtualMachineInputs vmInputs) {
656 var frameBase = ulong.MaxValue;
657 var loclist =
658 db_.LocLists[functionFrameBase];
659 foreach (var locListEntry in loclist) {
660 if (locListEntry.StartAddress == ulong.MaxValue) {
661 frameBase = locListEntry.EndAddress;
662 break;
663 }
664 // Try to determine whether this is the address of a symbol and
665 // return the referenced address in memory.
666 if (locListEntry.StartAddress <= codeAddress
667 && codeAddress <= locListEntry.EndAddress) {
668 frameBase = DwarfParser.DwarfParseVM(vmInputs, locListEntry.Data);
669 break;
670 }
671 }
672
673 if (frameBase < (ulong) DwarfOpcode.DW_OP_regX) {
674 Debug.WriteLine("WARNING: Register vars not currently supported");
675 }
676 vmInputs.FrameBase = frameBase;
677 }
678
679 #endregion
680 }
681 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698