// Minidump string llvm::Optional<std::string> lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) { std::string result; const uint32_t *source_length; Status error = consumeObject(data, source_length); if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0) return llvm::None; auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data()); // source_length is the length of the string in bytes // we need the length of the string in UTF-16 characters/code points (16 bits // per char) // that's why it's divided by 2 const auto source_end = source_start + (*source_length) / 2; // resize to worst case length result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * (*source_length) / 2); auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]); const auto result_end = result_start + result.size(); llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, llvm::strictConversion); const auto result_size = std::distance(reinterpret_cast<llvm::UTF8 *>(&result[0]), result_start); result.resize(result_size); // shrink to actual length return result; }
void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { const char *data = reinterpret_cast<const char *>(bytes.data()); PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); PythonObject::Reset(PyRefType::Owned, py_bytes); }
llvm::ArrayRef<MinidumpThread> MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle32_t *thread_count; Status error = consumeObject(data, thread_count); if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size()) return {}; return llvm::ArrayRef<MinidumpThread>( reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count); }
llvm::ArrayRef<MinidumpModule> MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle32_t *modules_count; Status error = consumeObject(data, modules_count); if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size()) return {}; return llvm::ArrayRef<MinidumpModule>( reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count); }
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) { if (auto order_and_width = GetByteOrderAndAddrSize(thread)) { DataExtractor extractor(expr.data(), expr.size(), order_and_width->first, order_and_width->second); if (!DWARFExpression::PrintDWARFExpression(s, extractor, order_and_width->second, /*dwarf_ref_size*/ 4, /*location_expression*/ false)) s.PutCString("invalid-dwarf-expr"); } else s.PutCString("dwarf-expr"); }
llvm::ArrayRef<MinidumpMemoryDescriptor> MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle32_t *mem_ranges_count; Status error = consumeObject(data, mem_ranges_count); if (error.Fail() || *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size()) return {}; return llvm::makeArrayRef( reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()), *mem_ranges_count); }
/// \brief Write a block of data, and get the offset that it starts at. /// \param Bytes the array of bytes to be written. /// \return the offset that this block was written at. /// offset_uint write(llvm::ArrayRef<char> Bytes) { // If the stream doesn't exist, silently ignore the write request. if (!Out) return noOffset(); auto const Size = Bytes.size(); Out->write(Bytes.data(), Size); // Update the current offset and return the original value. auto const WrittenAt = Offset; Offset += Size; return WrittenAt; }
std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t> MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle64_t *mem_ranges_count; Status error = consumeObject(data, mem_ranges_count); if (error.Fail() || *mem_ranges_count * sizeof(MinidumpMemoryDescriptor64) > data.size()) return {}; const llvm::support::ulittle64_t *base_rva; error = consumeObject(data, base_rva); if (error.Fail()) return {}; return std::make_pair( llvm::makeArrayRef( reinterpret_cast<const MinidumpMemoryDescriptor64 *>(data.data()), *mem_ranges_count), *base_rva); }
// Linux Proc Status // it's stored as an ascii string in the file llvm::Optional<LinuxProcStatus> LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) { LinuxProcStatus result; result.proc_status = llvm::StringRef(reinterpret_cast<const char *>(data.data()), data.size()); data = data.drop_front(data.size()); llvm::SmallVector<llvm::StringRef, 0> lines; result.proc_status.split(lines, '\n', 42); // /proc/$pid/status has 41 lines, but why not use 42? for (auto line : lines) { if (line.consume_front("Pid:")) { line = line.trim(); if (!line.getAsInteger(10, result.pid)) return result; } } return llvm::None; }
std::vector<const MinidumpMemoryInfo *> MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) { const MinidumpMemoryInfoListHeader *header; Status error = consumeObject(data, header); if (error.Fail() || header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) || header->size_of_entry < sizeof(MinidumpMemoryInfo)) return {}; data = data.drop_front(header->size_of_header - sizeof(MinidumpMemoryInfoListHeader)); if (header->size_of_entry * header->num_of_entries > data.size()) return {}; std::vector<const MinidumpMemoryInfo *> result; for (uint64_t i = 0; i < header->num_of_entries; ++i) { result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>( data.data() + i * header->size_of_entry)); } return result; }
PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) : PythonByteArray(bytes.data(), bytes.size()) {}