Decompressor.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //===-- Decompressor.cpp --------------------------------------------------===//
  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. #include "llvm/Object/Decompressor.h"
  9. #include "llvm/BinaryFormat/ELF.h"
  10. #include "llvm/Object/ObjectFile.h"
  11. #include "llvm/Support/Compression.h"
  12. #include "llvm/Support/DataExtractor.h"
  13. #include "llvm/Support/Endian.h"
  14. using namespace llvm;
  15. using namespace llvm::support::endian;
  16. using namespace object;
  17. Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
  18. bool IsLE, bool Is64Bit) {
  19. Decompressor D(Data);
  20. if (Error Err = D.consumeCompressedHeader(Is64Bit, IsLE))
  21. return std::move(Err);
  22. return D;
  23. }
  24. Decompressor::Decompressor(StringRef Data)
  25. : SectionData(Data), DecompressedSize(0) {}
  26. Error Decompressor::consumeCompressedHeader(bool Is64Bit, bool IsLittleEndian) {
  27. using namespace ELF;
  28. uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
  29. if (SectionData.size() < HdrSize)
  30. return createError("corrupted compressed section header");
  31. DataExtractor Extractor(SectionData, IsLittleEndian, 0);
  32. uint64_t Offset = 0;
  33. auto ChType = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
  34. : sizeof(Elf32_Word));
  35. switch (ChType) {
  36. case ELFCOMPRESS_ZLIB:
  37. CompressionType = DebugCompressionType::Zlib;
  38. break;
  39. case ELFCOMPRESS_ZSTD:
  40. CompressionType = DebugCompressionType::Zstd;
  41. break;
  42. default:
  43. return createError("unsupported compression type (" + Twine(ChType) + ")");
  44. }
  45. if (const char *Reason = llvm::compression::getReasonIfUnsupported(
  46. compression::formatFor(CompressionType)))
  47. return createError(Reason);
  48. // Skip Elf64_Chdr::ch_reserved field.
  49. if (Is64Bit)
  50. Offset += sizeof(Elf64_Word);
  51. DecompressedSize = Extractor.getUnsigned(
  52. &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word));
  53. SectionData = SectionData.substr(HdrSize);
  54. return Error::success();
  55. }
  56. Error Decompressor::decompress(MutableArrayRef<uint8_t> Output) {
  57. return compression::decompress(CompressionType,
  58. arrayRefFromStringRef(SectionData),
  59. Output.data(), Output.size());
  60. }