Home | History | Annotate | Line # | Download | only in MSF
      1 //===- MSFCommon.cpp - Common types and functions for MSF files -----------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/DebugInfo/MSF/MSFCommon.h"
     10 #include "llvm/DebugInfo/MSF/MSFError.h"
     11 #include "llvm/Support/Endian.h"
     12 #include "llvm/Support/Error.h"
     13 #include <cstdint>
     14 #include <cstring>
     15 
     16 using namespace llvm;
     17 using namespace llvm::msf;
     18 
     19 Error llvm::msf::validateSuperBlock(const SuperBlock &SB) {
     20   // Check the magic bytes.
     21   if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0)
     22     return make_error<MSFError>(msf_error_code::invalid_format,
     23                                 "MSF magic header doesn't match");
     24 
     25   if (!isValidBlockSize(SB.BlockSize))
     26     return make_error<MSFError>(msf_error_code::invalid_format,
     27                                 "Unsupported block size.");
     28 
     29   // We don't support directories whose sizes aren't a multiple of four bytes.
     30   if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
     31     return make_error<MSFError>(msf_error_code::invalid_format,
     32                                 "Directory size is not multiple of 4.");
     33 
     34   // The number of blocks which comprise the directory is a simple function of
     35   // the number of bytes it contains.
     36   uint64_t NumDirectoryBlocks =
     37       bytesToBlocks(SB.NumDirectoryBytes, SB.BlockSize);
     38 
     39   // The directory, as we understand it, is a block which consists of a list of
     40   // block numbers.  It is unclear what would happen if the number of blocks
     41   // couldn't fit on a single block.
     42   if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t))
     43     return make_error<MSFError>(msf_error_code::invalid_format,
     44                                 "Too many directory blocks.");
     45 
     46   if (SB.BlockMapAddr == 0)
     47     return make_error<MSFError>(msf_error_code::invalid_format,
     48                                 "Block 0 is reserved");
     49 
     50   if (SB.BlockMapAddr >= SB.NumBlocks)
     51     return make_error<MSFError>(msf_error_code::invalid_format,
     52                                 "Block map address is invalid.");
     53 
     54   if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2)
     55     return make_error<MSFError>(
     56         msf_error_code::invalid_format,
     57         "The free block map isn't at block 1 or block 2.");
     58 
     59   return Error::success();
     60 }
     61 
     62 MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf,
     63                                               bool IncludeUnusedFpmData,
     64                                               bool AltFpm) {
     65   MSFStreamLayout FL;
     66   uint32_t NumFpmIntervals =
     67       getNumFpmIntervals(Msf, IncludeUnusedFpmData, AltFpm);
     68 
     69   uint32_t FpmBlock = AltFpm ? Msf.alternateFpmBlock() : Msf.mainFpmBlock();
     70 
     71   for (uint32_t I = 0; I < NumFpmIntervals; ++I) {
     72     FL.Blocks.push_back(support::ulittle32_t(FpmBlock));
     73     FpmBlock += msf::getFpmIntervalLength(Msf);
     74   }
     75 
     76   if (IncludeUnusedFpmData)
     77     FL.Length = NumFpmIntervals * Msf.SB->BlockSize;
     78   else
     79     FL.Length = divideCeil(Msf.SB->NumBlocks, 8);
     80 
     81   return FL;
     82 }
     83