Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Commit

Permalink
Normalize "/names" stream string table
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwhite committed Sep 11, 2016
1 parent 82f1e24 commit f4241a1
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 12 deletions.
104 changes: 92 additions & 12 deletions src/patch_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include <stdint.h>
#include <stdlib.h>

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
Expand Down Expand Up @@ -367,10 +368,9 @@ NameMapTable readNameMapTable(const uint8_t* data, const uint8_t* dataEnd) {
}

/**
* Patches the LinkInfo named stream.
* Patches the "/LinkInfo" named stream.
*/
void patchLinkInfoStream(MsfMemoryStream* stream) {

uint8_t* data = stream->data();
const size_t length = stream->length();

Expand All @@ -383,6 +383,69 @@ void patchLinkInfoStream(MsfMemoryStream* stream) {
stream->resize(linkInfo->size);
}

/**
* Patches the "/names" stream.
*/
void patchNamesStream(MsfMemoryStream* stream) {
uint8_t* data = stream->data();
uint8_t* dataEnd = data + stream->length();

// Parse the header
if (size_t(dataEnd - data) < sizeof(StringTableHeader))
throw InvalidPdb("missing string table header");

StringTableHeader* header = (StringTableHeader*)data;

data += sizeof(*header);

if (header->signature != kHashTableSignature)
throw InvalidPdb("got invalid string table signature");

if (header->version != 1 && header->version != 2)
throw InvalidPdb("got invalid or unsupported string table version");

if (size_t(dataEnd - data) < header->stringsSize)
throw InvalidPdb("got partial string table data");

data += header->stringsSize;

if (size_t(dataEnd - data) < sizeof(uint32_t))
throw InvalidPdb("missing string table offset array length");

// Offsets array length
uint32_t offsetsLength = *(uint32_t*)data;

data += sizeof(offsetsLength);

if (size_t(dataEnd - data) < offsetsLength * sizeof(uint32_t))
throw InvalidPdb("got partial string table offsets array");

uint32_t* offsets = (uint32_t*)data;

data += offsetsLength * sizeof(uint32_t);

// Sort the offsets. There is some non-determinism creeping in here somehow.
std::sort(offsets, offsets + offsetsLength);

for (size_t i = 0; i < offsetsLength; ++i) {
const size_t offset = offsets[i];

if (offset == 0)
continue;

if (offset >= header->stringsSize)
throw InvalidPdb("got invalid offset into string table");

char* str = &header->strings[offset];
size_t len = strlen(str);

if (offset + len + 1 > header->stringsSize)
throw InvalidPdb("got invalid offset into string table");

normalizeFileNameGuid(str, len);
}
}

/**
* Patches the PDB header stream.
*/
Expand Down Expand Up @@ -414,21 +477,38 @@ void patchHeaderStream(MsfFile& msf, MsfMemoryStream* stream, const CV_INFO_PDB7
const auto table = readNameMapTable(data, dataEnd);

// Patch the LinkInfo stream.
const auto it = table.find("/LinkInfo");
if (it != table.end()) {
auto origLinkInfoStream = msf.getStream(it->second);
if (!origLinkInfoStream)
throw InvalidPdb("missing named LinkInfo stream");
{
const auto it = table.find("/LinkInfo");
if (it != table.end()) {
auto origLinkInfoStream = msf.getStream(it->second);
if (!origLinkInfoStream)
throw InvalidPdb("missing '/LinkInfo' stream");

auto linkInfoStream = std::shared_ptr<MsfMemoryStream>(
new MsfMemoryStream(origLinkInfoStream.get()));
auto linkInfoStream = std::shared_ptr<MsfMemoryStream>(
new MsfMemoryStream(origLinkInfoStream.get()));

patchLinkInfoStream(linkInfoStream.get());
patchLinkInfoStream(linkInfoStream.get());

msf.replaceStream(it->second, linkInfoStream);
msf.replaceStream(it->second, linkInfoStream);
}
}

// TODO: Rewrite /names hash table
// Rewrite /names hash table
{
const auto it = table.find("/names");
if (it != table.end()) {
auto origNamesStream = msf.getStream(it->second);
if (!origNamesStream)
throw InvalidPdb("missing '/names' stream");

auto namesStream = std::shared_ptr<MsfMemoryStream>(
new MsfMemoryStream(origNamesStream.get()));

patchNamesStream(namesStream.get());

msf.replaceStream(it->second, namesStream);
}
}
}

/**
Expand Down
23 changes: 23 additions & 0 deletions src/pdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,29 @@ struct LinkInfo {
}
};

static_assert(sizeof(LinkInfo) == 24, "invalid struct size");

const uint32_t kHashTableSignature = 0xeffeeffe;

/**
* The header that is present at the start of string tables.
*/
struct StringTableHeader {
// Should be equal to kHashTableSignature
uint32_t signature;

// Either 1 or 2
uint32_t version;

// Size of the string data that follows
uint32_t stringsSize;

// The strings
char strings[];
};

static_assert(sizeof(StringTableHeader) == 12, "invalid struct size");

/**
* Thrown when a PDB is found to be invalid or unsupported.
*/
Expand Down

0 comments on commit f4241a1

Please sign in to comment.