This is a patch to dump the free page map.
Details
Diff Detail
Event Timeline
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
49–52 | Would SparseBitVector be a more appropriate API to use? | |
53–56 | This will only read a single block right? Microsoft's code suggests that the FPM could span two blocks: |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | How about adding another field to the MsfLayout class called FreePageMap? You will need to set the value in MsfBuilder::build() before returning, and you will also need to set it in PDBFile::parseFileHeaders(). This way you wouldn't need to return an Expected<std::vector<uint32_t>> but rather a const BitVector&, and the reading / writing code would share the same common structures. | |
53–56 | It doesn't span 2 pages. But it's *either* page 1 or page 2. Which one it is depends on the second field in the super block. But whichever one it is, it's only that 1 page. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | I don't think that's right: | |
53–56 |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | Hmm, but there is also:
https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L49 |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | Yea, but read the very next line: According to hdr.pnFpm, the first or the second free page map is valid. What I'm not sure about is this line: In the interest of the on-disk size of the file, the FPM has been split across the file at regular intervals, with new intervals introduced as needed |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | At least, the test PDB file I was using contains a seemingly valid FPM in FPM2, and FPM1 contents doesn't seem to make sense. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | Wait, I think I get it. As you deduced, the maximum number of a single page of bits can represent is BlockSize * 8. But the SuperBlock tells you exactly how many pages are in the file. If the number of pages in the SuperBlock are more than the number that can be represented by a single page of bits, then there will be a page in the middle of the file that "continues" the Free Page Map. It will probably be precisely the page with index BlockSize * 8 |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
53–56 | Yeah, that seems to match my reading of things. Would be good to check with a big pdb like chrome_child. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | What is a bit annoying is that BitVector doesn't provide a way to map itself onto an existing bitmap, so I need to examine each bit and flip a bit in a BitVector. But, because the number of bits we have here is small anyways, it is probably okay to copy bit by bit. I'll try to add BitVector to MsfLayout. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | It seems like we could just add a new constructor to the BitVector class like this: BitVector(BitWord *Buffer, uint32_t NumBits); |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | BitWord is an internal thing of BitVector, so it probably should be uint8_t * and NumBits, or ArrayRef<uint8_t>. I'll try to see if I can add a new constructor. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | It already has BitVector::setBitsInMask. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | I took a look at the function and noticed that it takes a pointer to uint32_t. So the endianess matters here, so I cannot use it for an array read from file (unless swapping bytes before passing it to setBitsInMask). |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | You could just loop and call setBitsInMask. |
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | How? |
In MsfBuilder::build(), can you set the value of FreePageMap before returning?
lib/DebugInfo/PDB/Raw/PDBFile.cpp | ||
---|---|---|
52 | All we really want is a simple memset though. The function is already there init_words(), it's just private. |
Would SparseBitVector be a more appropriate API to use?