This is an archive of the discontinued LLVM Phabricator instance.

Add the ability to edit stream contents with llvm-pdbutil
Needs ReviewPublic

Authored by zturner on Jun 28 2018, 1:08 PM.

Details

Reviewers
inglorion
Summary

For experimentation and diagnostic purposes, it's often useful to be able to replace the contents of one stream with a binary blob. For example, if you have one PDB that works and one that doesn't, this can be useful for helping understand why the broken one is broken. You can replace stream contents 1 by 1 until something starts working. This is trickier than it sounds though, because if a stream's size changes it changes the stream directory as well, and in some cases could even cause the file to grow (or shrink).

To do this we load the old MSF layout and create an MSFBuilder out of it with the exact same properties as the existing file. Then we load the new stream contents and update the stream size, which should automatically decide how big the new file should be and where the new stream's blocks will be. Finally, we re-open the original file in a special mode that allows partial writes, keeping any untouched data intact, then write out only the modified MSF layout and new stream contents. In some cases -- particularly if a stream shrinks -- there will be "stale" data in the PDB file, but this shouldn't matter because the stream directory keeps track of a stream's *actual* size, so any tool reading the PDB would just ignore the stale data.

Diff Detail

Event Timeline

zturner created this revision.Jun 28 2018, 1:08 PM

This is really useful. Thanks for doing this. I got a couple of questions and comments in-line.

llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h
125

It's not clear to me from the names and the comments what exactly this method does and what the parameters mean. I think something like commitUpdate(StringRef Path, MSFLayout NewLayout) would make it clearer that we're committing an update to an existing MSF file, and the parameter is supposed to be the new layout and not the old one.

llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
51

Why +2?

llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
688

nit: in llvm/Option/ArgList.h, we have a similar method, but it's called hasArg. I would use the same name here, in part because it's shorter. :-)

1250

Shouldn't this assert that StreamFile was _not_ passed?

1263

Is there a way to preserve the original error information here, so that one can distinguish between for example a non-existent file and a file one does not have permission to read?

1277

I think this should be ExitOnErr rather than cantFail, similar to other uses of FileBufferByteStream::commit().