Home | History | Annotate | Download | only in CodeView
      1 //===-- RecordSerialization.cpp -------------------------------------------===//
      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 // Utilities for serializing and deserializing CodeView records.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
     15 #include "llvm/ADT/APInt.h"
     16 #include "llvm/ADT/APSInt.h"
     17 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
     18 
     19 using namespace llvm;
     20 using namespace llvm::codeview;
     21 using namespace llvm::support;
     22 
     23 /// Reinterpret a byte array as an array of characters. Does not interpret as
     24 /// a C string, as StringRef has several helpers (split) that make that easy.
     25 StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
     26   return StringRef(reinterpret_cast<const char *>(LeafData.data()),
     27                    LeafData.size());
     28 }
     29 
     30 StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
     31   return getBytesAsCharacters(LeafData).split('\0').first;
     32 }
     33 
     34 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data, APSInt &Num) {
     35   // Used to avoid overload ambiguity on APInt construtor.
     36   bool FalseVal = false;
     37   if (Data.size() < 2)
     38     return std::make_error_code(std::errc::illegal_byte_sequence);
     39   uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
     40   Data = Data.drop_front(2);
     41   if (Short < LF_NUMERIC) {
     42     Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
     43                  /*isUnsigned=*/true);
     44     return std::error_code();
     45   }
     46   switch (Short) {
     47   case LF_CHAR:
     48     if (Data.size() < 1)
     49       return std::make_error_code(std::errc::illegal_byte_sequence);
     50     Num = APSInt(APInt(/*numBits=*/8,
     51                        *reinterpret_cast<const int8_t *>(Data.data()),
     52                        /*isSigned=*/true),
     53                  /*isUnsigned=*/false);
     54     Data = Data.drop_front(1);
     55     return std::error_code();
     56   case LF_SHORT:
     57     if (Data.size() < 2)
     58       return std::make_error_code(std::errc::illegal_byte_sequence);
     59     Num = APSInt(APInt(/*numBits=*/16,
     60                        *reinterpret_cast<const little16_t *>(Data.data()),
     61                        /*isSigned=*/true),
     62                  /*isUnsigned=*/false);
     63     Data = Data.drop_front(2);
     64     return std::error_code();
     65   case LF_USHORT:
     66     if (Data.size() < 2)
     67       return std::make_error_code(std::errc::illegal_byte_sequence);
     68     Num = APSInt(APInt(/*numBits=*/16,
     69                        *reinterpret_cast<const ulittle16_t *>(Data.data()),
     70                        /*isSigned=*/false),
     71                  /*isUnsigned=*/true);
     72     Data = Data.drop_front(2);
     73     return std::error_code();
     74   case LF_LONG:
     75     if (Data.size() < 4)
     76       return std::make_error_code(std::errc::illegal_byte_sequence);
     77     Num = APSInt(APInt(/*numBits=*/32,
     78                        *reinterpret_cast<const little32_t *>(Data.data()),
     79                        /*isSigned=*/true),
     80                  /*isUnsigned=*/false);
     81     Data = Data.drop_front(4);
     82     return std::error_code();
     83   case LF_ULONG:
     84     if (Data.size() < 4)
     85       return std::make_error_code(std::errc::illegal_byte_sequence);
     86     Num = APSInt(APInt(/*numBits=*/32,
     87                        *reinterpret_cast<const ulittle32_t *>(Data.data()),
     88                        /*isSigned=*/FalseVal),
     89                  /*isUnsigned=*/true);
     90     Data = Data.drop_front(4);
     91     return std::error_code();
     92   case LF_QUADWORD:
     93     if (Data.size() < 8)
     94       return std::make_error_code(std::errc::illegal_byte_sequence);
     95     Num = APSInt(APInt(/*numBits=*/64,
     96                        *reinterpret_cast<const little64_t *>(Data.data()),
     97                        /*isSigned=*/true),
     98                  /*isUnsigned=*/false);
     99     Data = Data.drop_front(8);
    100     return std::error_code();
    101   case LF_UQUADWORD:
    102     if (Data.size() < 8)
    103       return std::make_error_code(std::errc::illegal_byte_sequence);
    104     Num = APSInt(APInt(/*numBits=*/64,
    105                        *reinterpret_cast<const ulittle64_t *>(Data.data()),
    106                        /*isSigned=*/false),
    107                  /*isUnsigned=*/true);
    108     Data = Data.drop_front(8);
    109     return std::error_code();
    110   }
    111   return std::make_error_code(std::errc::illegal_byte_sequence);
    112 }
    113 
    114 std::error_code llvm::codeview::consume(StringRef &Data, APSInt &Num) {
    115   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
    116   auto EC = consume(Bytes, Num);
    117   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
    118   return EC;
    119 }
    120 
    121 /// Decode a numeric leaf value that is known to be a uint64_t.
    122 std::error_code llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data,
    123                                                 uint64_t &Num) {
    124   APSInt N;
    125   if (auto EC = consume(Data, N))
    126     return EC;
    127   if (N.isSigned() || !N.isIntN(64))
    128     return std::make_error_code(std::errc::illegal_byte_sequence);
    129   Num = N.getLimitedValue();
    130   return std::error_code();
    131 }
    132 
    133 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
    134                                         uint32_t &Item) {
    135   const support::ulittle32_t *IntPtr;
    136   if (auto EC = consumeObject(Data, IntPtr))
    137     return EC;
    138   Item = *IntPtr;
    139   return std::error_code();
    140 }
    141 
    142 std::error_code llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
    143   ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
    144   auto EC = consume(Bytes, Item);
    145   Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
    146   return EC;
    147 }
    148 
    149 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
    150                                         int32_t &Item) {
    151   const support::little32_t *IntPtr;
    152   if (auto EC = consumeObject(Data, IntPtr))
    153     return EC;
    154   Item = *IntPtr;
    155   return std::error_code();
    156 }
    157 
    158 std::error_code llvm::codeview::consume(ArrayRef<uint8_t> &Data,
    159                                         StringRef &Item) {
    160   if (Data.empty())
    161     return std::make_error_code(std::errc::illegal_byte_sequence);
    162 
    163   StringRef Rest;
    164   std::tie(Item, Rest) = getBytesAsCharacters(Data).split('\0');
    165   // We expect this to be null terminated.  If it was not, it is an error.
    166   if (Data.size() == Item.size())
    167     return std::make_error_code(std::errc::illegal_byte_sequence);
    168 
    169   Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
    170   return std::error_code();
    171 }
    172