mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
1e25f820c0
The PDB reserves certain blocks for the FPM that describe which blocks in the file are allocated and which are free. We weren't filling that out at all, and in some cases we were even stomping it with incorrect data. This patch writes a correct FPM. Differential Revision: https://reviews.llvm.org/D36235 llvm-svn: 309896
86 lines
3.2 KiB
C++
86 lines
3.2 KiB
C++
//===- MSFCommon.cpp - Common types and functions for MSF files -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::msf;
|
|
|
|
Error llvm::msf::validateSuperBlock(const SuperBlock &SB) {
|
|
// Check the magic bytes.
|
|
if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0)
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"MSF magic header doesn't match");
|
|
|
|
if (!isValidBlockSize(SB.BlockSize))
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"Unsupported block size.");
|
|
|
|
// We don't support directories whose sizes aren't a multiple of four bytes.
|
|
if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"Directory size is not multiple of 4.");
|
|
|
|
// The number of blocks which comprise the directory is a simple function of
|
|
// the number of bytes it contains.
|
|
uint64_t NumDirectoryBlocks =
|
|
bytesToBlocks(SB.NumDirectoryBytes, SB.BlockSize);
|
|
|
|
// The directory, as we understand it, is a block which consists of a list of
|
|
// block numbers. It is unclear what would happen if the number of blocks
|
|
// couldn't fit on a single block.
|
|
if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t))
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"Too many directory blocks.");
|
|
|
|
if (SB.BlockMapAddr == 0)
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"Block 0 is reserved");
|
|
|
|
if (SB.BlockMapAddr >= SB.NumBlocks)
|
|
return make_error<MSFError>(msf_error_code::invalid_format,
|
|
"Block map address is invalid.");
|
|
|
|
if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2)
|
|
return make_error<MSFError>(
|
|
msf_error_code::invalid_format,
|
|
"The free block map isn't at block 1 or block 2.");
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf,
|
|
bool IncludeUnusedFpmData,
|
|
bool AltFpm) {
|
|
MSFStreamLayout FL;
|
|
uint32_t NumFpmIntervals = getNumFpmIntervals(Msf, IncludeUnusedFpmData);
|
|
support::ulittle32_t FpmBlock = Msf.SB->FreeBlockMapBlock;
|
|
assert(FpmBlock == 1 || FpmBlock == 2);
|
|
if (AltFpm) {
|
|
// If they requested the alternate FPM, then 2 becomes 1 and 1 becomes 2.
|
|
FpmBlock = 3U - FpmBlock;
|
|
}
|
|
for (uint32_t I = 0; I < NumFpmIntervals; ++I) {
|
|
FL.Blocks.push_back(FpmBlock);
|
|
FpmBlock += msf::getFpmIntervalLength(Msf);
|
|
}
|
|
|
|
if (IncludeUnusedFpmData)
|
|
FL.Length = NumFpmIntervals * Msf.SB->BlockSize;
|
|
else
|
|
FL.Length = divideCeil(Msf.SB->NumBlocks, 8);
|
|
|
|
return FL;
|
|
}
|