| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- //
- // PdbReader.cs
- //
- // Author:
- // Jb Evain (jbevain@gmail.com)
- //
- // Copyright (c) 2008 - 2011 Jb Evain
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Collections.Generic;
- using System.IO;
- using Microsoft.Cci.Pdb;
- using Mono.Cecil.Cil;
- namespace Mono.Cecil.Pdb
- {
- public class PdbReader : ISymbolReader
- {
- int age;
- Guid guid;
- readonly Stream pdb_file;
- readonly Dictionary<string, Document> documents = new Dictionary<string, Document>();
- readonly Dictionary<uint, PdbFunction> functions = new Dictionary<uint, PdbFunction>(new uintCompare());
- internal PdbReader(Stream file)
- {
- this.pdb_file = file;
- }
- /*
- uint Magic = 0x53445352;
- Guid Signature;
- uint Age;
- string FileName;
- */
- public bool ProcessDebugHeader(ImageDebugDirectory directory, byte[] header)
- {
- if (header.Length < 24)
- return false;
- var magic = ReadInt32(header, 0);
- if (magic != 0x53445352)
- return false;
- var guid_bytes = new byte[16];
- Buffer.BlockCopy(header, 4, guid_bytes, 0, 16);
- this.guid = new Guid(guid_bytes);
- this.age = ReadInt32(header, 20);
- return PopulateFunctions();
- }
- static int ReadInt32(byte[] bytes, int start)
- {
- return (bytes[start]
- | (bytes[start + 1] << 8)
- | (bytes[start + 2] << 16)
- | (bytes[start + 3] << 24));
- }
- bool PopulateFunctions()
- {
- using (pdb_file)
- {
- int age;
- Guid guid;
- var funcs = PdbFile.LoadFunctions(pdb_file, true, out age, out guid);
- if (this.age != 0 && this.guid != guid)
- return false;
- foreach (PdbFunction function in funcs)
- functions.Add(function.token, function);
- }
- return true;
- }
- public void Read(MethodBody body, InstructionMapper mapper)
- {
- var method_token = body.Method.MetadataToken;
- PdbFunction function;
- if (!functions.TryGetValue(method_token.ToUInt32(), out function))
- return;
- ReadSequencePoints(function, mapper);
- ReadScopeAndLocals(function.scopes, null, body, mapper);
- }
- static void ReadScopeAndLocals(PdbScope[] scopes, Scope parent, MethodBody body, InstructionMapper mapper)
- {
- foreach (PdbScope scope in scopes)
- ReadScopeAndLocals(scope, parent, body, mapper);
- CreateRootScope(body);
- }
- static void CreateRootScope(MethodBody body)
- {
- if (!body.HasVariables)
- return;
- var instructions = body.Instructions;
- var root = new Scope();
- root.Start = instructions[0];
- root.End = instructions[instructions.Count - 1];
- var variables = body.Variables;
- for (int i = 0; i < variables.Count; i++)
- root.Variables.Add(variables[i]);
- body.Scope = root;
- }
- static void ReadScopeAndLocals(PdbScope scope, Scope parent, MethodBody body, InstructionMapper mapper)
- {
- //Scope s = new Scope ();
- //s.Start = GetInstruction (body, instructions, (int) scope.address);
- //s.End = GetInstruction (body, instructions, (int) scope.length - 1);
- //if (parent != null)
- // parent.Scopes.Add (s);
- //else
- // body.Scopes.Add (s);
- if (scope == null)
- return;
- foreach (PdbSlot slot in scope.slots)
- {
- int index = (int)slot.slot;
- if (index < 0 || index >= body.Variables.Count)
- continue;
- VariableDefinition variable = body.Variables[index];
- variable.Name = slot.name;
- //s.Variables.Add (variable);
- }
- ReadScopeAndLocals(scope.scopes, null /* s */, body, mapper);
- }
- void ReadSequencePoints(PdbFunction function, InstructionMapper mapper)
- {
- if (function.lines == null)
- return;
- foreach (PdbLines lines in function.lines)
- ReadLines(lines, mapper);
- }
- void ReadLines(PdbLines lines, InstructionMapper mapper)
- {
- var document = GetDocument(lines.file);
- foreach (var line in lines.lines)
- ReadLine(line, document, mapper);
- }
- static void ReadLine(PdbLine line, Document document, InstructionMapper mapper)
- {
- var instruction = mapper((int)line.offset);
- if (instruction == null)
- return;
- var sequence_point = new SequencePoint(document);
- sequence_point.StartLine = (int)line.lineBegin;
- sequence_point.StartColumn = (int)line.colBegin;
- sequence_point.EndLine = (int)line.lineEnd;
- sequence_point.EndColumn = (int)line.colEnd;
- instruction.SequencePoint = sequence_point;
- }
- Document GetDocument(PdbSource source)
- {
- string name = source.name;
- Document document;
- if (documents.TryGetValue(name, out document))
- return document;
- document = new Document(name)
- {
- Language = GuidMapping.ToLanguage(source.language),
- LanguageVendor = GuidMapping.ToVendor(source.vendor),
- Type = GuidMapping.ToType(source.doctype),
- };
- documents.Add(name, document);
- return document;
- }
- public void Read(MethodSymbols symbols)
- {
- PdbFunction function;
- if (!functions.TryGetValue(symbols.MethodToken.ToUInt32(), out function))
- return;
- ReadSequencePoints(function, symbols);
- ReadLocals(function.scopes, symbols);
- }
- void ReadLocals(PdbScope[] scopes, MethodSymbols symbols)
- {
- foreach (var scope in scopes)
- ReadLocals(scope, symbols);
- }
- void ReadLocals(PdbScope scope, MethodSymbols symbols)
- {
- if (scope == null)
- return;
- foreach (var slot in scope.slots)
- {
- int index = (int)slot.slot;
- if (index < 0 || index >= symbols.Variables.Count)
- continue;
- var variable = symbols.Variables[index];
- variable.Name = slot.name;
- }
- ReadLocals(scope.scopes, symbols);
- }
- void ReadSequencePoints(PdbFunction function, MethodSymbols symbols)
- {
- if (function.lines == null)
- return;
- foreach (PdbLines lines in function.lines)
- ReadLines(lines, symbols);
- }
- void ReadLines(PdbLines lines, MethodSymbols symbols)
- {
- for (int i = 0; i < lines.lines.Length; i++)
- {
- var line = lines.lines[i];
- symbols.Instructions.Add(new InstructionSymbol((int)line.offset, new SequencePoint(GetDocument(lines.file))
- {
- StartLine = (int)line.lineBegin,
- StartColumn = (int)line.colBegin,
- EndLine = (int)line.lineEnd,
- EndColumn = (int)line.colEnd,
- }));
- }
- }
- public void Dispose()
- {
- pdb_file.Close();
- }
- }
- }
|