| Eugene Zelenko | 2db0cfa | 2017-06-23 21:57:40 +0000 | [diff] [blame] | 1 | //===- MSFCommon.cpp - Common types and functions for MSF files -----------===// | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 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 |  | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 10 | #include "llvm/DebugInfo/MSF/MSFCommon.h" | 
|  | 11 | #include "llvm/DebugInfo/MSF/MSFError.h" | 
| Eugene Zelenko | 2db0cfa | 2017-06-23 21:57:40 +0000 | [diff] [blame] | 12 | #include "llvm/Support/Endian.h" | 
|  | 13 | #include "llvm/Support/Error.h" | 
|  | 14 | #include <cstdint> | 
|  | 15 | #include <cstring> | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 16 |  | 
|  | 17 | using namespace llvm; | 
| Zachary Turner | bac69d3 | 2016-07-22 19:56:05 +0000 | [diff] [blame] | 18 | using namespace llvm::msf; | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 19 |  | 
| Zachary Turner | bac69d3 | 2016-07-22 19:56:05 +0000 | [diff] [blame] | 20 | Error llvm::msf::validateSuperBlock(const SuperBlock &SB) { | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 21 | // Check the magic bytes. | 
|  | 22 | if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0) | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 23 | return make_error<MSFError>(msf_error_code::invalid_format, | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 24 | "MSF magic header doesn't match"); | 
|  | 25 |  | 
|  | 26 | if (!isValidBlockSize(SB.BlockSize)) | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 27 | return make_error<MSFError>(msf_error_code::invalid_format, | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 28 | "Unsupported block size."); | 
|  | 29 |  | 
|  | 30 | // We don't support directories whose sizes aren't a multiple of four bytes. | 
|  | 31 | if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0) | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 32 | return make_error<MSFError>(msf_error_code::invalid_format, | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 33 | "Directory size is not multiple of 4."); | 
|  | 34 |  | 
|  | 35 | // The number of blocks which comprise the directory is a simple function of | 
|  | 36 | // the number of bytes it contains. | 
|  | 37 | uint64_t NumDirectoryBlocks = | 
|  | 38 | bytesToBlocks(SB.NumDirectoryBytes, SB.BlockSize); | 
|  | 39 |  | 
|  | 40 | // The directory, as we understand it, is a block which consists of a list of | 
|  | 41 | // block numbers.  It is unclear what would happen if the number of blocks | 
|  | 42 | // couldn't fit on a single block. | 
|  | 43 | if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t)) | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 44 | return make_error<MSFError>(msf_error_code::invalid_format, | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 45 | "Too many directory blocks."); | 
|  | 46 |  | 
|  | 47 | if (SB.BlockMapAddr == 0) | 
| Zachary Turner | a3225b0 | 2016-07-29 20:56:36 +0000 | [diff] [blame] | 48 | return make_error<MSFError>(msf_error_code::invalid_format, | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 49 | "Block 0 is reserved"); | 
|  | 50 |  | 
| David Majnemer | 9bca03b | 2016-12-18 00:41:10 +0000 | [diff] [blame] | 51 | if (SB.BlockMapAddr >= SB.NumBlocks) | 
|  | 52 | return make_error<MSFError>(msf_error_code::invalid_format, | 
|  | 53 | "Block map address is invalid."); | 
|  | 54 |  | 
|  | 55 | if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2) | 
|  | 56 | return make_error<MSFError>( | 
|  | 57 | msf_error_code::invalid_format, | 
|  | 58 | "The free block map isn't at block 1 or block 2."); | 
|  | 59 |  | 
| Zachary Turner | f52a899 | 2016-07-15 20:43:38 +0000 | [diff] [blame] | 60 | return Error::success(); | 
|  | 61 | } | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 62 |  | 
| Zachary Turner | 9fb9d71 | 2017-08-02 22:31:39 +0000 | [diff] [blame] | 63 | MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf, | 
|  | 64 | bool IncludeUnusedFpmData, | 
|  | 65 | bool AltFpm) { | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 66 | MSFStreamLayout FL; | 
| Zachary Turner | 9fb9d71 | 2017-08-02 22:31:39 +0000 | [diff] [blame] | 67 | uint32_t NumFpmIntervals = getNumFpmIntervals(Msf, IncludeUnusedFpmData); | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 68 | support::ulittle32_t FpmBlock = Msf.SB->FreeBlockMapBlock; | 
|  | 69 | assert(FpmBlock == 1 || FpmBlock == 2); | 
| Zachary Turner | 9fb9d71 | 2017-08-02 22:31:39 +0000 | [diff] [blame] | 70 | if (AltFpm) { | 
|  | 71 | // If they requested the alternate FPM, then 2 becomes 1 and 1 becomes 2. | 
|  | 72 | FpmBlock = 3U - FpmBlock; | 
|  | 73 | } | 
|  | 74 | for (uint32_t I = 0; I < NumFpmIntervals; ++I) { | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 75 | FL.Blocks.push_back(FpmBlock); | 
|  | 76 | FpmBlock += msf::getFpmIntervalLength(Msf); | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 77 | } | 
| Zachary Turner | 9fb9d71 | 2017-08-02 22:31:39 +0000 | [diff] [blame] | 78 |  | 
|  | 79 | if (IncludeUnusedFpmData) | 
|  | 80 | FL.Length = NumFpmIntervals * Msf.SB->BlockSize; | 
|  | 81 | else | 
|  | 82 | FL.Length = divideCeil(Msf.SB->NumBlocks, 8); | 
| Zachary Turner | c3d8eec | 2017-08-02 22:25:52 +0000 | [diff] [blame] | 83 |  | 
|  | 84 | return FL; | 
|  | 85 | } |