xref: /llvm-project/llvm/lib/DebugInfo/MSF/MSFCommon.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
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