Пример #1
0
TEST(MinidumpFile, getModuleList) {
  std::vector<uint8_t> OneModule{
      // Header
      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
      1, 0, 0, 0,                           // NumberOfStreams,
      32, 0, 0, 0,                          // StreamDirectoryRVA
      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
                                            // Stream Directory
      4, 0, 0, 0, 112, 0, 0, 0,             // Type, DataSize,
      44, 0, 0, 0,                          // RVA
      // ModuleList
      1, 0, 0, 0,             // NumberOfModules
      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
      0, 0, 0, 0,             // FileOS
      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
  };
  // Same as before, but with a padded module list.
  std::vector<uint8_t> PaddedModule{
      // Header
      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
      1, 0, 0, 0,                           // NumberOfStreams,
      32, 0, 0, 0,                          // StreamDirectoryRVA
      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
                                            // Stream Directory
      4, 0, 0, 0, 116, 0, 0, 0,             // Type, DataSize,
      44, 0, 0, 0,                          // RVA
      // ModuleList
      1, 0, 0, 0,             // NumberOfModules
      0, 0, 0, 0,             // Padding
      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
      0, 0, 0, 0,             // FileOS
      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
  };

  for (const std::vector<uint8_t> &Data : {OneModule, PaddedModule}) {
    auto ExpectedFile = create(Data);
    ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
    const MinidumpFile &File = **ExpectedFile;
    Expected<ArrayRef<Module>> ExpectedModule = File.getModuleList();
    ASSERT_THAT_EXPECTED(ExpectedModule, Succeeded());
    ASSERT_EQ(1u, ExpectedModule->size());
    const Module &M = ExpectedModule.get()[0];
    EXPECT_EQ(0x0807060504030201u, M.BaseOfImage);
    EXPECT_EQ(0x02010009u, M.SizeOfImage);
    EXPECT_EQ(0x06050403u, M.Checksum);
    EXPECT_EQ(0x00090807u, M.TimeDateStamp);
    EXPECT_EQ(0x04030201u, M.ModuleNameRVA);
    EXPECT_EQ(0x04030201u, M.CvRecord.DataSize);
    EXPECT_EQ(0x08070605u, M.CvRecord.RVA);
    EXPECT_EQ(0x02010009u, M.MiscRecord.DataSize);
    EXPECT_EQ(0x06050403u, M.MiscRecord.RVA);
    EXPECT_EQ(0x0403020100090807u, M.Reserved0);
    EXPECT_EQ(0x0201000908070605u, M.Reserved1);
  }

  std::vector<uint8_t> StreamTooShort{
      // Header
      'M', 'D', 'M', 'P', 0x93, 0xa7, 0, 0, // Signature, Version
      1, 0, 0, 0,                           // NumberOfStreams,
      32, 0, 0, 0,                          // StreamDirectoryRVA
      0, 1, 2, 3, 4, 5, 6, 7,               // Checksum, TimeDateStamp
      0, 0, 0, 0, 0, 0, 0, 0,               // Flags
                                            // Stream Directory
      4, 0, 0, 0, 111, 0, 0, 0,             // Type, DataSize,
      44, 0, 0, 0,                          // RVA
      // ModuleList
      1, 0, 0, 0,             // NumberOfModules
      1, 2, 3, 4, 5, 6, 7, 8, // BaseOfImage
      9, 0, 1, 2, 3, 4, 5, 6, // SizeOfImage, Checksum
      7, 8, 9, 0, 1, 2, 3, 4, // TimeDateStamp, ModuleNameRVA
      0, 0, 0, 0, 0, 0, 0, 0, // Signature, StructVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileVersion
      0, 0, 0, 0, 0, 0, 0, 0, // ProductVersion
      0, 0, 0, 0, 0, 0, 0, 0, // FileFlagsMask, FileFlags
      0, 0, 0, 0,             // FileOS
      0, 0, 0, 0, 0, 0, 0, 0, // FileType, FileSubType
      0, 0, 0, 0, 0, 0, 0, 0, // FileDate
      1, 2, 3, 4, 5, 6, 7, 8, // CvRecord
      9, 0, 1, 2, 3, 4, 5, 6, // MiscRecord
      7, 8, 9, 0, 1, 2, 3, 4, // Reserved0
      5, 6, 7, 8, 9, 0, 1, 2, // Reserved1
  };
  auto ExpectedFile = create(StreamTooShort);
  ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
  const MinidumpFile &File = **ExpectedFile;
  EXPECT_THAT_EXPECTED(File.getModuleList(), Failed<BinaryError>());
}
Пример #2
0
Expected<std::vector<typename ELFT::Rela>>
ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {
  // This function reads relocations in Android's packed relocation format,
  // which is based on SLEB128 and delta encoding.
  Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
  if (!ContentsOrErr)
    return ContentsOrErr.takeError();
  const uint8_t *Cur = ContentsOrErr->begin();
  const uint8_t *End = ContentsOrErr->end();
  if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
      Cur[2] != 'S' || Cur[3] != '2')
    return createError("invalid packed relocation header");
  Cur += 4;

  const char *ErrStr = nullptr;
  auto ReadSLEB = [&]() -> int64_t {
    if (ErrStr)
      return 0;
    unsigned Len;
    int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
    Cur += Len;
    return Result;
  };

  uint64_t NumRelocs = ReadSLEB();
  uint64_t Offset = ReadSLEB();
  uint64_t Addend = 0;

  if (ErrStr)
    return createError(ErrStr);

  std::vector<Elf_Rela> Relocs;
  Relocs.reserve(NumRelocs);
  while (NumRelocs) {
    uint64_t NumRelocsInGroup = ReadSLEB();
    if (NumRelocsInGroup > NumRelocs)
      return createError("relocation group unexpectedly large");
    NumRelocs -= NumRelocsInGroup;

    uint64_t GroupFlags = ReadSLEB();
    bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
    bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
    bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
    bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;

    uint64_t GroupOffsetDelta;
    if (GroupedByOffsetDelta)
      GroupOffsetDelta = ReadSLEB();

    uint64_t GroupRInfo;
    if (GroupedByInfo)
      GroupRInfo = ReadSLEB();

    if (GroupedByAddend && GroupHasAddend)
      Addend += ReadSLEB();

    if (!GroupHasAddend)
      Addend = 0;

    for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
      Elf_Rela R;
      Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
      R.r_offset = Offset;
      R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
      if (GroupHasAddend && !GroupedByAddend)
        Addend += ReadSLEB();
      R.r_addend = Addend;
      Relocs.push_back(R);

      if (ErrStr)
        return createError(ErrStr);
    }

    if (ErrStr)
      return createError(ErrStr);
  }

  return Relocs;
}