mirror of https://github.com/icsharpcode/ILSpy.git
10 changed files with 190 additions and 77 deletions
@ -1,19 +1,38 @@ |
|||||||
using System; |
using System; |
||||||
using System.ComponentModel.DataAnnotations; |
using System.ComponentModel.DataAnnotations; |
||||||
|
using System.IO; |
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.Console |
namespace ICSharpCode.Decompiler.Console |
||||||
{ |
{ |
||||||
[AttributeUsage(AttributeTargets.Class)] |
[AttributeUsage(AttributeTargets.Class)] |
||||||
public class ProjectOptionRequiresOutputDirectoryValidationAttribute : ValidationAttribute |
public sealed class ProjectOptionRequiresOutputDirectoryValidationAttribute : ValidationAttribute |
||||||
{ |
{ |
||||||
|
public ProjectOptionRequiresOutputDirectoryValidationAttribute() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
protected override ValidationResult IsValid(object value, ValidationContext context) |
protected override ValidationResult IsValid(object value, ValidationContext context) |
||||||
{ |
{ |
||||||
if (value is ILSpyCmdProgram obj) { |
if (value is ILSpyCmdProgram obj) { |
||||||
if (obj.CreateCompilableProjectFlag && String.IsNullOrEmpty(obj.OutputDirectory)) { |
if (obj.CreateCompilableProjectFlag && string.IsNullOrEmpty(obj.OutputDirectory)) { |
||||||
return new ValidationResult("--project cannot be used unless --outputdir is also specified"); |
return new ValidationResult("--project cannot be used unless --outputdir is also specified"); |
||||||
} |
} |
||||||
} |
} |
||||||
return ValidationResult.Success; |
return ValidationResult.Success; |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Property)] |
||||||
|
public sealed class FileExistsOrNullAttribute : ValidationAttribute |
||||||
|
{ |
||||||
|
protected override ValidationResult IsValid(object value, ValidationContext context) |
||||||
|
{ |
||||||
|
var s = value as string; |
||||||
|
if (string.IsNullOrEmpty(s)) |
||||||
|
return ValidationResult.Success; |
||||||
|
if (File.Exists(s)) |
||||||
|
return ValidationResult.Success; |
||||||
|
return new ValidationResult($"File '{s}' does not exist!"); |
||||||
|
} |
||||||
|
} |
||||||
} |
} |
||||||
|
@ -0,0 +1,113 @@ |
|||||||
|
// Copyright (c) 2018 Siegfried Pammer
|
||||||
|
//
|
||||||
|
// 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.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection.Metadata; |
||||||
|
using System.Reflection.PortableExecutable; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
using ICSharpCode.Decompiler.DebugInfo; |
||||||
|
using ICSharpCode.Decompiler.Metadata; |
||||||
|
|
||||||
|
namespace ICSharpCode.Decompiler.PdbProvider |
||||||
|
{ |
||||||
|
static class DebugInfoUtils |
||||||
|
{ |
||||||
|
public static IDebugInfoProvider LoadSymbols(PEFile module) |
||||||
|
{ |
||||||
|
try { |
||||||
|
var reader = module.Reader; |
||||||
|
// try to open portable pdb file/embedded pdb info:
|
||||||
|
if (TryOpenPortablePdb(module, out var provider, out var pdbFileName)) { |
||||||
|
return new PortableDebugInfoProvider(pdbFileName, provider); |
||||||
|
} else { |
||||||
|
// search for pdb in same directory as dll
|
||||||
|
pdbFileName = Path.Combine(Path.GetDirectoryName(module.FileName), Path.GetFileNameWithoutExtension(module.FileName) + ".pdb"); |
||||||
|
if (File.Exists(pdbFileName)) { |
||||||
|
return new MonoCecilDebugInfoProvider(module, pdbFileName); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception ex) when (ex is BadImageFormatException || ex is COMException) { |
||||||
|
// Ignore PDB load errors
|
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public static IDebugInfoProvider FromFile(PEFile module, string pdbFileName) |
||||||
|
{ |
||||||
|
if (string.IsNullOrEmpty(pdbFileName)) |
||||||
|
return null; |
||||||
|
|
||||||
|
Stream stream = OpenStream(pdbFileName); |
||||||
|
if (stream == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
if (stream.Read(buffer, 0, buffer.Length) == LegacyPDBPrefix.Length |
||||||
|
&& System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) { |
||||||
|
stream.Position = 0; |
||||||
|
return new MonoCecilDebugInfoProvider(module, pdbFileName); |
||||||
|
} else { |
||||||
|
stream.Position = 0; |
||||||
|
var provider = MetadataReaderProvider.FromPortablePdbStream(stream); |
||||||
|
return new PortableDebugInfoProvider(pdbFileName, provider); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const string LegacyPDBPrefix = "Microsoft C/C++ MSF 7.00"; |
||||||
|
static readonly byte[] buffer = new byte[LegacyPDBPrefix.Length]; |
||||||
|
|
||||||
|
static bool TryOpenPortablePdb(PEFile module, out MetadataReaderProvider provider, out string pdbFileName) |
||||||
|
{ |
||||||
|
provider = null; |
||||||
|
pdbFileName = null; |
||||||
|
var reader = module.Reader; |
||||||
|
foreach (var entry in reader.ReadDebugDirectory()) { |
||||||
|
if (entry.IsPortableCodeView) { |
||||||
|
return reader.TryOpenAssociatedPortablePdb(module.FileName, OpenStream, out provider, out pdbFileName); |
||||||
|
} |
||||||
|
if (entry.Type == DebugDirectoryEntryType.CodeView) { |
||||||
|
string pdbDirectory = Path.GetDirectoryName(module.FileName); |
||||||
|
pdbFileName = Path.Combine(pdbDirectory, Path.GetFileNameWithoutExtension(module.FileName) + ".pdb"); |
||||||
|
if (File.Exists(pdbFileName)) { |
||||||
|
Stream stream = OpenStream(pdbFileName); |
||||||
|
if (stream.Read(buffer, 0, buffer.Length) == LegacyPDBPrefix.Length |
||||||
|
&& System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
stream.Position = 0; |
||||||
|
provider = MetadataReaderProvider.FromPortablePdbStream(stream); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
static Stream OpenStream(string fileName) |
||||||
|
{ |
||||||
|
if (!File.Exists(fileName)) |
||||||
|
return null; |
||||||
|
var memory = new MemoryStream(); |
||||||
|
using (var stream = File.OpenRead(fileName)) |
||||||
|
stream.CopyTo(memory); |
||||||
|
memory.Position = 0; |
||||||
|
return memory; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue