12db0cfa6SEugene Zelenko //===- MSFCommon.cpp - Common types and functions for MSF files -----------===//
2a3225b04SZachary Turner //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a3225b04SZachary Turner //
7a3225b04SZachary Turner //===----------------------------------------------------------------------===//
8a3225b04SZachary Turner
9a3225b04SZachary Turner #include "llvm/DebugInfo/MSF/MSFCommon.h"
10a3225b04SZachary Turner #include "llvm/DebugInfo/MSF/MSFError.h"
112db0cfa6SEugene Zelenko #include "llvm/Support/Endian.h"
122db0cfa6SEugene Zelenko #include "llvm/Support/Error.h"
132db0cfa6SEugene Zelenko #include <cstdint>
142db0cfa6SEugene Zelenko #include <cstring>
15a3225b04SZachary Turner
16a3225b04SZachary Turner using namespace llvm;
17a3225b04SZachary Turner using namespace llvm::msf;
18a3225b04SZachary Turner
validateSuperBlock(const SuperBlock & SB)19a3225b04SZachary Turner Error llvm::msf::validateSuperBlock(const SuperBlock &SB) {
20a3225b04SZachary Turner // Check the magic bytes.
21a3225b04SZachary Turner if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0)
22a3225b04SZachary Turner return make_error<MSFError>(msf_error_code::invalid_format,
23a3225b04SZachary Turner "MSF magic header doesn't match");
24a3225b04SZachary Turner
25a3225b04SZachary Turner if (!isValidBlockSize(SB.BlockSize))
26a3225b04SZachary Turner return make_error<MSFError>(msf_error_code::invalid_format,
27a3225b04SZachary Turner "Unsupported block size.");
28a3225b04SZachary Turner
29a3225b04SZachary Turner // We don't support directories whose sizes aren't a multiple of four bytes.
30a3225b04SZachary Turner if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
31a3225b04SZachary Turner return make_error<MSFError>(msf_error_code::invalid_format,
32a3225b04SZachary Turner "Directory size is not multiple of 4.");
33a3225b04SZachary Turner
34a3225b04SZachary Turner // The number of blocks which comprise the directory is a simple function of
35a3225b04SZachary Turner // the number of bytes it contains.
36a3225b04SZachary Turner uint64_t NumDirectoryBlocks =
37a3225b04SZachary Turner bytesToBlocks(SB.NumDirectoryBytes, SB.BlockSize);
38a3225b04SZachary Turner
39a3225b04SZachary Turner // The directory, as we understand it, is a block which consists of a list of
40a3225b04SZachary Turner // block numbers. It is unclear what would happen if the number of blocks
41a3225b04SZachary Turner // couldn't fit on a single block.
42a3225b04SZachary Turner if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t))
43a3225b04SZachary Turner return make_error<MSFError>(msf_error_code::invalid_format,
44a3225b04SZachary Turner "Too many directory blocks.");
45a3225b04SZachary Turner
46a3225b04SZachary Turner if (SB.BlockMapAddr == 0)
47a3225b04SZachary Turner return make_error<MSFError>(msf_error_code::invalid_format,
48a3225b04SZachary Turner "Block 0 is reserved");
49a3225b04SZachary Turner
509bca03bfSDavid Majnemer if (SB.BlockMapAddr >= SB.NumBlocks)
519bca03bfSDavid Majnemer return make_error<MSFError>(msf_error_code::invalid_format,
529bca03bfSDavid Majnemer "Block map address is invalid.");
539bca03bfSDavid Majnemer
549bca03bfSDavid Majnemer if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2)
559bca03bfSDavid Majnemer return make_error<MSFError>(
569bca03bfSDavid Majnemer msf_error_code::invalid_format,
579bca03bfSDavid Majnemer "The free block map isn't at block 1 or block 2.");
589bca03bfSDavid Majnemer
59a3225b04SZachary Turner return Error::success();
60a3225b04SZachary Turner }
61c3d8eec9SZachary Turner
getFpmStreamLayout(const MSFLayout & Msf,bool IncludeUnusedFpmData,bool AltFpm)629fb9d71dSZachary Turner MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf,
639fb9d71dSZachary Turner bool IncludeUnusedFpmData,
649fb9d71dSZachary Turner bool AltFpm) {
65c3d8eec9SZachary Turner MSFStreamLayout FL;
66de6a487dSZachary Turner uint32_t NumFpmIntervals =
67de6a487dSZachary Turner getNumFpmIntervals(Msf, IncludeUnusedFpmData, AltFpm);
68de6a487dSZachary Turner
69de6a487dSZachary Turner uint32_t FpmBlock = AltFpm ? Msf.alternateFpmBlock() : Msf.mainFpmBlock();
70de6a487dSZachary Turner
719fb9d71dSZachary Turner for (uint32_t I = 0; I < NumFpmIntervals; ++I) {
72de6a487dSZachary Turner FL.Blocks.push_back(support::ulittle32_t(FpmBlock));
73c3d8eec9SZachary Turner FpmBlock += msf::getFpmIntervalLength(Msf);
74c3d8eec9SZachary Turner }
759fb9d71dSZachary Turner
769fb9d71dSZachary Turner if (IncludeUnusedFpmData)
779fb9d71dSZachary Turner FL.Length = NumFpmIntervals * Msf.SB->BlockSize;
789fb9d71dSZachary Turner else
799fb9d71dSZachary Turner FL.Length = divideCeil(Msf.SB->NumBlocks, 8);
80c3d8eec9SZachary Turner
81c3d8eec9SZachary Turner return FL;
82c3d8eec9SZachary Turner }
83