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(s1: SB.MagicBytes, s2: Magic, n: sizeof(Magic)) != 0) |
22 | return make_error<MSFError>(Args: msf_error_code::invalid_format, |
23 | Args: "MSF magic header doesn't match" ); |
24 | |
25 | if (!isValidBlockSize(Size: SB.BlockSize)) |
26 | return make_error<MSFError>(Args: msf_error_code::invalid_format, |
27 | Args: "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>(Args: msf_error_code::invalid_format, |
32 | Args: "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(NumBytes: SB.NumDirectoryBytes, BlockSize: 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>(Args: msf_error_code::invalid_format, |
44 | Args: "Too many directory blocks." ); |
45 | |
46 | if (SB.BlockMapAddr == 0) |
47 | return make_error<MSFError>(Args: msf_error_code::invalid_format, |
48 | Args: "Block 0 is reserved" ); |
49 | |
50 | if (SB.BlockMapAddr >= SB.NumBlocks) |
51 | return make_error<MSFError>(Args: msf_error_code::invalid_format, |
52 | Args: "Block map address is invalid." ); |
53 | |
54 | if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2) |
55 | return make_error<MSFError>( |
56 | Args: msf_error_code::invalid_format, |
57 | Args: "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(L: 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(x: support::ulittle32_t(FpmBlock)); |
73 | FpmBlock += msf::getFpmIntervalLength(L: Msf); |
74 | } |
75 | |
76 | if (IncludeUnusedFpmData) |
77 | FL.Length = NumFpmIntervals * Msf.SB->BlockSize; |
78 | else |
79 | FL.Length = divideCeil(Numerator: Msf.SB->NumBlocks, Denominator: 8); |
80 | |
81 | return FL; |
82 | } |
83 | |