Skip to content

Instantly share code, notes, and snippets.

@nosami
Created July 4, 2019 13:34
Show Gist options
  • Save nosami/03f64a58af787fbfa85528e9f85b0369 to your computer and use it in GitHub Desktop.
Save nosami/03f64a58af787fbfa85528e9f85b0369 to your computer and use it in GitHub Desktop.
pdbreader
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