1 //===- MSFCommon.h - Common types and functions for MSF files ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_DEBUGINFO_MSF_MSFCOMMON_H 11 #define LLVM_DEBUGINFO_MSF_MSFCOMMON_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/BitVector.h" 15 #include "llvm/Support/Endian.h" 16 #include "llvm/Support/Error.h" 17 #include "llvm/Support/MathExtras.h" 18 #include <cstdint> 19 #include <vector> 20 21 namespace llvm { 22 namespace msf { 23 24 static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 25 't', ' ', 'C', '/', 'C', '+', '+', ' ', 26 'M', 'S', 'F', ' ', '7', '.', '0', '0', 27 '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'}; 28 29 // The superblock is overlaid at the beginning of the file (offset 0). 30 // It starts with a magic header and is followed by information which 31 // describes the layout of the file system. 32 struct SuperBlock { 33 char MagicBytes[sizeof(Magic)]; 34 // The file system is split into a variable number of fixed size elements. 35 // These elements are referred to as blocks. The size of a block may vary 36 // from system to system. 37 support::ulittle32_t BlockSize; 38 // The index of the free block map. 39 support::ulittle32_t FreeBlockMapBlock; 40 // This contains the number of blocks resident in the file system. In 41 // practice, NumBlocks * BlockSize is equivalent to the size of the MSF 42 // file. 43 support::ulittle32_t NumBlocks; 44 // This contains the number of bytes which make up the directory. 45 support::ulittle32_t NumDirectoryBytes; 46 // This field's purpose is not yet known. 47 support::ulittle32_t Unknown1; 48 // This contains the block # of the block map. 49 support::ulittle32_t BlockMapAddr; 50 }; 51 52 struct MSFLayout { 53 MSFLayout() = default; 54 55 const SuperBlock *SB = nullptr; 56 BitVector FreePageMap; 57 ArrayRef<support::ulittle32_t> DirectoryBlocks; 58 ArrayRef<support::ulittle32_t> StreamSizes; 59 std::vector<ArrayRef<support::ulittle32_t>> StreamMap; 60 }; 61 62 /// \brief Describes the layout of a stream in an MSF layout. A "stream" here 63 /// is defined as any logical unit of data which may be arranged inside the MSF 64 /// file as a sequence of (possibly discontiguous) blocks. When we want to read 65 /// from a particular MSF Stream, we fill out a stream layout structure and the 66 /// reader uses it to determine which blocks in the underlying MSF file contain 67 /// the data, so that it can be pieced together in the right order. 68 class MSFStreamLayout { 69 public: 70 uint32_t Length; 71 std::vector<support::ulittle32_t> Blocks; 72 }; 73 74 /// \brief Determine the layout of the FPM stream, given the MSF layout. An FPM 75 /// stream spans 1 or more blocks, each at equally spaced intervals throughout 76 /// the file. 77 MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf, 78 bool IncludeUnusedFpmData = false, 79 bool AltFpm = false); 80 81 inline bool isValidBlockSize(uint32_t Size) { 82 switch (Size) { 83 case 512: 84 case 1024: 85 case 2048: 86 case 4096: 87 return true; 88 } 89 return false; 90 } 91 92 // Super Block, Fpm0, Fpm1, and Block Map 93 inline uint32_t getMinimumBlockCount() { return 4; } 94 95 // Super Block, Fpm0, and Fpm1 are reserved. The Block Map, although required 96 // need not be at block 3. 97 inline uint32_t getFirstUnreservedBlock() { return 3; } 98 99 inline uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) { 100 return divideCeil(NumBytes, BlockSize); 101 } 102 103 inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) { 104 return BlockNumber * BlockSize; 105 } 106 107 inline uint32_t getFpmIntervalLength(const MSFLayout &L) { 108 return L.SB->BlockSize; 109 } 110 111 inline uint32_t getNumFpmIntervals(const MSFLayout &L, 112 bool IncludeUnusedFpmData = false) { 113 if (IncludeUnusedFpmData) 114 return divideCeil(L.SB->NumBlocks, L.SB->BlockSize); 115 116 // We want the minimum number of intervals required, where each interval can 117 // represent BlockSize * 8 blocks. 118 return divideCeil(L.SB->NumBlocks, 8 * L.SB->BlockSize); 119 } 120 121 Error validateSuperBlock(const SuperBlock &SB); 122 123 } // end namespace msf 124 } // end namespace llvm 125 126 #endif // LLVM_DEBUGINFO_MSF_MSFCOMMON_H 127