Created
July 4, 2019 13:34
-
-
Save nosami/03f64a58af787fbfa85528e9f85b0369 to your computer and use it in GitHub Desktop.
pdbreader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Security.Cryptography; | |
using System.Text; | |
namespace newtonsoft_snupkg_core | |
{ | |
static class BinaryReaderExtensions | |
{ | |
public static string ReadNullTerminatedString(this BinaryReader stream) | |
{ | |
var builder = new StringBuilder(); | |
char ch; | |
while ((ch = stream.ReadChar()) != 0) | |
builder.Append(ch); | |
return builder.ToString(); | |
} | |
} | |
class Program | |
{ | |
const string pdbStreamName = "#Pdb"; | |
const uint pdbIdSize = 20; | |
private readonly string _pdbFileName; | |
public Program(string pdbFileName) | |
{ | |
_pdbFileName = pdbFileName; | |
} | |
uint GetPdbIdOffset() | |
{ | |
var stream = File.OpenRead(_pdbFileName); | |
using (var reader = new BinaryReader(stream)) | |
{ | |
uint signature = reader.ReadUInt32(); | |
stream.Seek(4 + // Signature | |
2 + // Version Major | |
2 + // Version Minor | |
4, // Reserved) | |
SeekOrigin.Begin); | |
// skip the version string | |
uint versionStringSize = 0; | |
versionStringSize = reader.ReadUInt32(); | |
stream.Seek(versionStringSize, SeekOrigin.Current); | |
// storage header | |
stream.Seek(2, SeekOrigin.Current); | |
// read the stream headers | |
ushort streamCount = reader.ReadUInt16(); | |
uint streamOffset; | |
string streamName; | |
for (int i = 0; i < streamCount; i++) | |
{ | |
var pos = stream.Position; | |
streamOffset = reader.ReadUInt32(); | |
// stream size | |
stream.Seek(4, SeekOrigin.Current); | |
streamName = reader.ReadNullTerminatedString(); | |
Console.WriteLine($"{i}: {streamName}"); | |
if (streamName == pdbStreamName) | |
{ | |
// We found it! | |
return streamOffset; | |
} | |
// streams headers are on a four byte alignment | |
if (stream.Position % 4 != 0) | |
{ | |
stream.Seek(4 - stream.Position % 4, SeekOrigin.Current); | |
} | |
} | |
} | |
throw new ArgumentException("We have a file with a metadata pdb signature but no pdb stream"); | |
} | |
static void Main(string[] args) | |
{ | |
var fileName = "/Users/jasonimison/Newtonsoft.Json.pdb"; | |
var program = new Program(fileName); | |
var offset = program.GetPdbIdOffset(); | |
var bytes = File.ReadAllBytes(fileName); | |
for (var i = 0; i <= pdbIdSize; i++) | |
{ | |
bytes[i + offset] = 0; | |
} | |
var algorithm = HashAlgorithm.Create("SHA256"); | |
if (algorithm != null) | |
{ | |
var hash = algorithm.ComputeHash(bytes); | |
var checksum = ToHexString(hash); | |
Console.WriteLine(checksum); | |
} | |
else | |
{ | |
throw new ArgumentException("Unknown hash algorithm"); | |
} | |
} | |
/// <summary> | |
/// Convert an array of bytes to a lower case hex string. | |
/// </summary> | |
/// <param name="bytes">array of bytes</param> | |
/// <returns>hex string</returns> | |
private static string ToHexString(byte[] bytes) | |
{ | |
if (bytes == null) | |
{ | |
throw new ArgumentNullException(nameof(bytes)); | |
} | |
return string.Concat(bytes.Select(b => b.ToString("x2"))); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment