1 //===-- LZMA.cpp ----------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Host/Config.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/Support/Error.h"
15 #endif // LLDB_ENABLE_LZMA
17 namespace lldb_private
{
22 bool isAvailable() { return false; }
23 llvm::Expected
<uint64_t>
24 getUncompressedSize(llvm::ArrayRef
<uint8_t> InputBuffer
) {
25 llvm_unreachable("lzma::getUncompressedSize is unavailable");
28 llvm::Error
uncompress(llvm::ArrayRef
<uint8_t> InputBuffer
,
29 llvm::SmallVectorImpl
<uint8_t> &Uncompressed
) {
30 llvm_unreachable("lzma::uncompress is unavailable");
33 #else // LLDB_ENABLE_LZMA
35 bool isAvailable() { return true; }
37 static const char *convertLZMACodeToString(lzma_ret Code
) {
40 return "lzma error: LZMA_STREAM_END";
42 return "lzma error: LZMA_NO_CHECK";
43 case LZMA_UNSUPPORTED_CHECK
:
44 return "lzma error: LZMA_UNSUPPORTED_CHECK";
46 return "lzma error: LZMA_GET_CHECK";
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";
56 return "lzma error: LZMA_DATA_ERROR";
58 return "lzma error: LZMA_BUF_ERROR";
60 return "lzma error: LZMA_PROG_ERROR";
62 llvm_unreachable("unknown or unexpected lzma status code");
66 llvm::Expected
<uint64_t>
67 getUncompressedSize(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
);
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
));
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 "
90 InputBuffer
.size(), (opts
.backward_size
+ LZMA_STREAM_HEADER_SIZE
));
95 uint64_t memlimit(UINT64_MAX
);
97 xzerr
= lzma_index_buffer_decode(
98 &xzindex
, &memlimit
, nullptr,
99 InputBuffer
.take_back(LZMA_STREAM_HEADER_SIZE
+ opts
.backward_size
)
101 &inpos
, InputBuffer
.size());
102 if (xzerr
!= LZMA_OK
) {
103 return llvm::createStringError(llvm::inconvertibleErrorCode(),
104 "lzma_index_buffer_decode()=%s",
105 convertLZMACodeToString(xzerr
));
108 // Get size of uncompressed file to construct an in-memory buffer of the
109 // same size on the calling end (if needed).
110 uint64_t uncompressedSize
= lzma_index_uncompressed_size(xzindex
);
112 // Deallocate xz index as it is no longer needed.
113 lzma_index_end(xzindex
, nullptr);
115 return uncompressedSize
;
118 llvm::Error
uncompress(llvm::ArrayRef
<uint8_t> InputBuffer
,
119 llvm::SmallVectorImpl
<uint8_t> &Uncompressed
) {
120 llvm::Expected
<uint64_t> uncompressedSize
= getUncompressedSize(InputBuffer
);
122 if (auto err
= uncompressedSize
.takeError())
125 Uncompressed
.resize(*uncompressedSize
);
127 // Decompress xz buffer to buffer.
128 uint64_t memlimit
= UINT64_MAX
;
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
));
140 return llvm::Error::success();
143 #endif // LLDB_ENABLE_LZMA
145 } // end of namespace lzma
146 } // namespace lldb_private