brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 5b457f0 Raw
147 lines · cpp
1//===-- LZMA.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/Config.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/Support/Error.h"12 13#if LLDB_ENABLE_LZMA14#include <lzma.h>15#endif // LLDB_ENABLE_LZMA16 17namespace lldb_private {18 19namespace lzma {20 21#if !LLDB_ENABLE_LZMA22bool isAvailable() { return false; }23llvm::Expected<uint64_t>24getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) {25  llvm_unreachable("lzma::getUncompressedSize is unavailable");26}27 28llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer,29                       llvm::SmallVectorImpl<uint8_t> &Uncompressed) {30  llvm_unreachable("lzma::uncompress is unavailable");31}32 33#else // LLDB_ENABLE_LZMA34 35bool isAvailable() { return true; }36 37static const char *convertLZMACodeToString(lzma_ret Code) {38  switch (Code) {39  case LZMA_STREAM_END:40    return "lzma error: LZMA_STREAM_END";41  case LZMA_NO_CHECK:42    return "lzma error: LZMA_NO_CHECK";43  case LZMA_UNSUPPORTED_CHECK:44    return "lzma error: LZMA_UNSUPPORTED_CHECK";45  case LZMA_GET_CHECK:46    return "lzma error: LZMA_GET_CHECK";47  case LZMA_MEM_ERROR:48    return "lzma error: LZMA_MEM_ERROR";49  case LZMA_MEMLIMIT_ERROR:50    return "lzma error: LZMA_MEMLIMIT_ERROR";51  case LZMA_FORMAT_ERROR:52    return "lzma error: LZMA_FORMAT_ERROR";53  case LZMA_OPTIONS_ERROR:54    return "lzma error: LZMA_OPTIONS_ERROR";55  case LZMA_DATA_ERROR:56    return "lzma error: LZMA_DATA_ERROR";57  case LZMA_BUF_ERROR:58    return "lzma error: LZMA_BUF_ERROR";59  case LZMA_PROG_ERROR:60    return "lzma error: LZMA_PROG_ERROR";61  default:62    llvm_unreachable("unknown or unexpected lzma status code");63  }64}65 66llvm::Expected<uint64_t>67getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) {68  lzma_stream_flags opts{};69  if (InputBuffer.size() < LZMA_STREAM_HEADER_SIZE) {70    return llvm::createStringError(71        llvm::inconvertibleErrorCode(),72        "size of xz-compressed blob (%lu bytes) is smaller than the "73        "LZMA_STREAM_HEADER_SIZE (%lu bytes)",74        InputBuffer.size(), LZMA_STREAM_HEADER_SIZE);75  }76 77  // Decode xz footer.78  lzma_ret xzerr = lzma_stream_footer_decode(79      &opts, InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE).data());80  if (xzerr != LZMA_OK) {81    return llvm::createStringError(llvm::inconvertibleErrorCode(),82                                   "lzma_stream_footer_decode()=%s",83                                   convertLZMACodeToString(xzerr));84  }85  if (InputBuffer.size() < (opts.backward_size + LZMA_STREAM_HEADER_SIZE)) {86    return llvm::createStringError(87        llvm::inconvertibleErrorCode(),88        "xz-compressed buffer size (%lu bytes) too small (required at "89        "least %lu bytes) ",90        InputBuffer.size(), (opts.backward_size + LZMA_STREAM_HEADER_SIZE));91  }92 93  // Decode xz index.94  lzma_index *xzindex;95  uint64_t memlimit(UINT64_MAX);96  size_t inpos = 0;97  xzerr = lzma_index_buffer_decode(98      &xzindex, &memlimit, nullptr,99      InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE + opts.backward_size)100          .data(),101      &inpos, InputBuffer.size());102  if (xzerr != LZMA_OK) {103    return llvm::createStringError(llvm::inconvertibleErrorCode(),104                                   "lzma_index_buffer_decode()=%s",105                                   convertLZMACodeToString(xzerr));106  }107 108  // Get size of uncompressed file to construct an in-memory buffer of the109  // same size on the calling end (if needed).110  uint64_t uncompressedSize = lzma_index_uncompressed_size(xzindex);111 112  // Deallocate xz index as it is no longer needed.113  lzma_index_end(xzindex, nullptr);114 115  return uncompressedSize;116}117 118llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer,119                       llvm::SmallVectorImpl<uint8_t> &Uncompressed) {120  llvm::Expected<uint64_t> uncompressedSize = getUncompressedSize(InputBuffer);121 122  if (auto err = uncompressedSize.takeError())123    return err;124 125  Uncompressed.resize(*uncompressedSize);126 127  // Decompress xz buffer to buffer.128  uint64_t memlimit = UINT64_MAX;129  size_t inpos = 0;130  size_t outpos = 0;131  lzma_ret ret = lzma_stream_buffer_decode(132      &memlimit, 0, nullptr, InputBuffer.data(), &inpos, InputBuffer.size(),133      Uncompressed.data(), &outpos, Uncompressed.size());134  if (ret != LZMA_OK) {135    return llvm::createStringError(llvm::inconvertibleErrorCode(),136                                   "lzma_stream_buffer_decode()=%s",137                                   convertLZMACodeToString(ret));138  }139 140  return llvm::Error::success();141}142 143#endif // LLDB_ENABLE_LZMA144 145} // end of namespace lzma146} // namespace lldb_private147