841 lines · cpp
1//===-- RegisterValue.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/Utility/RegisterValue.h"10 11#include "lldb/Utility/DataExtractor.h"12#include "lldb/Utility/Scalar.h"13#include "lldb/Utility/Status.h"14#include "lldb/Utility/Stream.h"15#include "lldb/Utility/StreamString.h"16#include "lldb/lldb-defines.h"17#include "lldb/lldb-private-types.h"18 19#include "llvm/ADT/ArrayRef.h"20#include "llvm/ADT/StringRef.h"21 22#include <cstdint>23#include <string>24#include <tuple>25#include <vector>26 27#include <cassert>28#include <cinttypes>29#include <cstdio>30 31using namespace lldb;32using namespace lldb_private;33 34bool RegisterValue::GetData(DataExtractor &data) const {35 return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0;36}37 38uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo ®_info, void *dst,39 uint32_t dst_len,40 lldb::ByteOrder dst_byte_order,41 Status &error) const {42 // ReadRegister should have already been called on this object prior to43 // calling this.44 if (GetType() == eTypeInvalid) {45 // No value has been read into this object...46 error = Status::FromErrorStringWithFormatv(47 "invalid register value type for register {0}", reg_info.name);48 return 0;49 }50 51 const uint32_t src_len = reg_info.byte_size;52 53 // Extract the register data into a data extractor54 DataExtractor reg_data;55 if (!GetData(reg_data)) {56 error = Status::FromErrorString("invalid register value to copy into");57 return 0;58 }59 60 // Prepare a memory buffer that contains some or all of the register value61 const uint32_t bytes_copied =62 reg_data.CopyByteOrderedData(0, // src offset63 src_len, // src length64 dst, // dst buffer65 dst_len, // dst length66 dst_byte_order); // dst byte order67 if (bytes_copied == 0)68 error = Status::FromErrorStringWithFormat(69 "failed to copy data for register write of %s", reg_info.name);70 71 return bytes_copied;72}73 74uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo ®_info,75 const void *src, uint32_t src_len,76 lldb::ByteOrder src_byte_order,77 Status &error) {78 // Moving from addr into a register79 //80 // Case 1: src_len == dst_len81 //82 // |AABBCCDD| Address contents83 // |AABBCCDD| Register contents84 //85 // Case 2: src_len > dst_len86 //87 // Status! (The register should always be big enough to hold the data)88 //89 // Case 3: src_len < dst_len90 //91 // |AABB| Address contents92 // |AABB0000| Register contents [on little-endian hardware]93 // |0000AABB| Register contents [on big-endian hardware]94 const uint32_t dst_len = reg_info.byte_size;95 96 if (src_len > dst_len) {97 error = Status::FromErrorStringWithFormat(98 "%u bytes is too big to store in register %s (%u bytes)", src_len,99 reg_info.name, dst_len);100 return 0;101 }102 103 // Use a data extractor to correctly copy and pad the bytes read into the104 // register value105 DataExtractor src_data(src, src_len, src_byte_order, 4);106 107 error = SetValueFromData(reg_info, src_data, 0, true);108 if (error.Fail())109 return 0;110 111 // If SetValueFromData succeeded, we must have copied all of src_len112 return src_len;113}114 115bool RegisterValue::GetScalarValue(Scalar &scalar) const {116 switch (m_type) {117 case eTypeInvalid:118 break;119 case eTypeBytes: {120 DataExtractor data(buffer.bytes.data(), buffer.bytes.size(),121 buffer.byte_order, 1);122 if (scalar.SetValueFromData(data, lldb::eEncodingUint, buffer.bytes.size())123 .Success())124 return true;125 } break;126 case eTypeUInt8:127 case eTypeUInt16:128 case eTypeUInt32:129 case eTypeUInt64:130 case eTypeUIntN:131 case eTypeFloat:132 case eTypeDouble:133 case eTypeLongDouble:134 scalar = m_scalar;135 return true;136 }137 return false;138}139 140void RegisterValue::Clear() { m_type = eTypeInvalid; }141 142RegisterValue::Type RegisterValue::SetType(const RegisterInfo ®_info) {143 // To change the type, we simply copy the data in again, using the new format144 RegisterValue copy;145 DataExtractor copy_data;146 if (copy.CopyValue(*this) && copy.GetData(copy_data)) {147 Status error = SetValueFromData(reg_info, copy_data, 0, true);148 assert(error.Success() && "Expected SetValueFromData to succeed.");149 UNUSED_IF_ASSERT_DISABLED(error);150 }151 152 return m_type;153}154 155Status RegisterValue::SetValueFromData(const RegisterInfo ®_info,156 DataExtractor &src,157 lldb::offset_t src_offset,158 bool partial_data_ok) {159 Status error;160 161 if (src.GetByteSize() == 0) {162 error = Status::FromErrorString("empty data.");163 return error;164 }165 166 if (reg_info.byte_size == 0) {167 error = Status::FromErrorString("invalid register info.");168 return error;169 }170 171 uint32_t src_len = src.GetByteSize() - src_offset;172 173 if (!partial_data_ok && (src_len < reg_info.byte_size)) {174 error = Status::FromErrorString("not enough data.");175 return error;176 }177 178 // Cap the data length if there is more than enough bytes for this register179 // value180 if (src_len > reg_info.byte_size)181 src_len = reg_info.byte_size;182 183 m_type = eTypeInvalid;184 switch (reg_info.encoding) {185 case eEncodingInvalid:186 break;187 case eEncodingUint:188 case eEncodingSint:189 if (reg_info.byte_size == 1)190 SetUInt8(src.GetMaxU32(&src_offset, src_len));191 else if (reg_info.byte_size <= 2)192 SetUInt16(src.GetMaxU32(&src_offset, src_len));193 else if (reg_info.byte_size <= 4)194 SetUInt32(src.GetMaxU32(&src_offset, src_len));195 else if (reg_info.byte_size <= 8)196 SetUInt64(src.GetMaxU64(&src_offset, src_len));197 else {198 std::vector<uint8_t> native_endian_src(src_len, 0);199 src.ExtractBytes(src_offset, src_len, endian::InlHostByteOrder(),200 native_endian_src.data());201 llvm::APInt uint = llvm::APInt::getZero(src_len * 8);202 llvm::LoadIntFromMemory(uint, native_endian_src.data(), src_len);203 SetUIntN(uint);204 }205 break;206 case eEncodingIEEE754:207 if (reg_info.byte_size == sizeof(float))208 SetFloat(src.GetFloat(&src_offset));209 else if (reg_info.byte_size == sizeof(double))210 SetDouble(src.GetDouble(&src_offset));211 else if (reg_info.byte_size == sizeof(long double))212 SetLongDouble(src.GetLongDouble(&src_offset));213 break;214 case eEncodingVector: {215 m_type = eTypeBytes;216 assert(reg_info.byte_size <= kMaxRegisterByteSize);217 buffer.bytes.resize(reg_info.byte_size);218 buffer.byte_order = src.GetByteOrder();219 if (src.CopyByteOrderedData(220 src_offset, // offset within "src" to start extracting data221 src_len, // src length222 buffer.bytes.data(), // dst buffer223 buffer.bytes.size(), // dst length224 buffer.byte_order) == 0) // dst byte order225 {226 error = Status::FromErrorStringWithFormat(227 "failed to copy data for register write of %s", reg_info.name);228 return error;229 }230 }231 }232 233 if (m_type == eTypeInvalid)234 error = Status::FromErrorStringWithFormat(235 "invalid register value type for register %s", reg_info.name);236 return error;237}238 239// Helper function for RegisterValue::SetValueFromString()240static bool ParseVectorEncoding(const RegisterInfo *reg_info,241 llvm::StringRef vector_str,242 const uint32_t byte_size,243 RegisterValue *reg_value) {244 // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a245 // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".246 vector_str = vector_str.trim();247 vector_str.consume_front("{");248 vector_str.consume_back("}");249 vector_str = vector_str.trim();250 251 char Sep = ' ';252 253 // The first split should give us:254 // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f255 // 0x2a 0x3e').256 llvm::StringRef car;257 llvm::StringRef cdr = vector_str;258 std::tie(car, cdr) = vector_str.split(Sep);259 std::vector<uint8_t> bytes;260 unsigned byte = 0;261 262 // Using radix auto-sensing by passing 0 as the radix. Keep on processing the263 // vector elements as long as the parsing succeeds and the vector size is <264 // byte_size.265 while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) {266 bytes.push_back(byte);267 std::tie(car, cdr) = cdr.split(Sep);268 }269 270 // Check for vector of exact byte_size elements.271 if (bytes.size() != byte_size)272 return false;273 274 reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);275 return true;276}277 278static bool UInt64ValueIsValidForByteSize(uint64_t uval64,279 size_t total_byte_size) {280 if (total_byte_size > 8)281 return false;282 283 if (total_byte_size == 8)284 return true;285 286 const uint64_t max =287 (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) -288 1;289 return uval64 <= max;290}291 292static bool SInt64ValueIsValidForByteSize(int64_t sval64,293 size_t total_byte_size) {294 if (total_byte_size > 8)295 return false;296 297 if (total_byte_size == 8)298 return true;299 300 const int64_t max = (static_cast<int64_t>(1)301 << static_cast<uint64_t>(total_byte_size * 8 - 1)) -302 1;303 const int64_t min = ~(max);304 return min <= sval64 && sval64 <= max;305}306 307Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,308 llvm::StringRef value_str) {309 Status error;310 if (reg_info == nullptr) {311 error = Status::FromErrorString("Invalid register info argument.");312 return error;313 }314 315 m_type = eTypeInvalid;316 if (value_str.empty()) {317 error = Status::FromErrorString("Invalid c-string value string.");318 return error;319 }320 const uint32_t byte_size = reg_info->byte_size;321 322 uint64_t uval64;323 int64_t ival64;324 float flt_val;325 double dbl_val;326 long double ldbl_val;327 switch (reg_info->encoding) {328 case eEncodingInvalid:329 error = Status::FromErrorString("Invalid encoding.");330 break;331 332 case eEncodingUint:333 if (byte_size > sizeof(uint64_t)) {334 error = Status::FromErrorStringWithFormat(335 "unsupported unsigned integer byte size: %u", byte_size);336 break;337 }338 if (value_str.getAsInteger(0, uval64)) {339 error = Status::FromErrorStringWithFormatv(340 "'{0}' is not a valid unsigned integer string value", value_str);341 break;342 }343 344 if (!UInt64ValueIsValidForByteSize(uval64, byte_size)) {345 error = Status::FromErrorStringWithFormat(346 "value 0x%" PRIx64347 " is too large to fit in a %u byte unsigned integer value",348 uval64, byte_size);349 break;350 }351 352 if (!SetUInt(uval64, reg_info->byte_size)) {353 error = Status::FromErrorStringWithFormat(354 "unsupported unsigned integer byte size: %u", byte_size);355 break;356 }357 break;358 359 case eEncodingSint:360 if (byte_size > sizeof(long long)) {361 error = Status::FromErrorStringWithFormat(362 "unsupported signed integer byte size: %u", byte_size);363 break;364 }365 366 if (value_str.getAsInteger(0, ival64)) {367 error = Status::FromErrorStringWithFormatv(368 "'{0}' is not a valid signed integer string value", value_str);369 break;370 }371 372 if (!SInt64ValueIsValidForByteSize(ival64, byte_size)) {373 error = Status::FromErrorStringWithFormat(374 "value 0x%" PRIx64375 " is too large to fit in a %u byte signed integer value",376 ival64, byte_size);377 break;378 }379 380 if (!SetUInt(ival64, reg_info->byte_size)) {381 error = Status::FromErrorStringWithFormat(382 "unsupported signed integer byte size: %u", byte_size);383 break;384 }385 break;386 387 case eEncodingIEEE754: {388 std::string value_string = std::string(value_str);389 if (byte_size == sizeof(float)) {390 if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) {391 error = Status::FromErrorStringWithFormat(392 "'%s' is not a valid float string value", value_string.c_str());393 break;394 }395 m_scalar = flt_val;396 m_type = eTypeFloat;397 } else if (byte_size == sizeof(double)) {398 if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) {399 error = Status::FromErrorStringWithFormat(400 "'%s' is not a valid float string value", value_string.c_str());401 break;402 }403 m_scalar = dbl_val;404 m_type = eTypeDouble;405 } else if (byte_size == sizeof(long double)) {406 if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) {407 error = Status::FromErrorStringWithFormat(408 "'%s' is not a valid float string value", value_string.c_str());409 break;410 }411 m_scalar = ldbl_val;412 m_type = eTypeLongDouble;413 } else {414 error = Status::FromErrorStringWithFormat(415 "unsupported float byte size: %u", byte_size);416 return error;417 }418 break;419 }420 case eEncodingVector:421 if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))422 error =423 Status::FromErrorString("unrecognized vector encoding string value.");424 break;425 }426 427 return error;428}429 430bool RegisterValue::SignExtend(uint32_t sign_bitpos) {431 switch (m_type) {432 case eTypeInvalid:433 break;434 435 case eTypeUInt8:436 case eTypeUInt16:437 case eTypeUInt32:438 case eTypeUInt64:439 case eTypeUIntN:440 return m_scalar.SignExtend(sign_bitpos);441 case eTypeFloat:442 case eTypeDouble:443 case eTypeLongDouble:444 case eTypeBytes:445 break;446 }447 return false;448}449 450bool RegisterValue::CopyValue(const RegisterValue &rhs) {451 if (this == &rhs)452 return rhs.m_type != eTypeInvalid;453 454 m_type = rhs.m_type;455 switch (m_type) {456 case eTypeInvalid:457 return false;458 case eTypeUInt8:459 case eTypeUInt16:460 case eTypeUInt32:461 case eTypeUInt64:462 case eTypeUIntN:463 case eTypeFloat:464 case eTypeDouble:465 case eTypeLongDouble:466 m_scalar = rhs.m_scalar;467 break;468 case eTypeBytes:469 buffer.bytes = rhs.buffer.bytes;470 buffer.byte_order = rhs.buffer.byte_order;471 break;472 }473 return true;474}475 476uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value,477 bool *success_ptr) const {478 if (success_ptr)479 *success_ptr = true;480 481 switch (m_type) {482 default:483 break;484 case eTypeUInt8:485 case eTypeUInt16:486 return m_scalar.UShort(fail_value);487 case eTypeBytes: {488 switch (buffer.bytes.size()) {489 default:490 break;491 case 1:492 case 2:493 return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());494 }495 } break;496 }497 if (success_ptr)498 *success_ptr = false;499 return fail_value;500}501 502uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value,503 bool *success_ptr) const {504 if (success_ptr)505 *success_ptr = true;506 switch (m_type) {507 default:508 break;509 case eTypeUInt8:510 case eTypeUInt16:511 case eTypeUInt32:512 case eTypeFloat:513 case eTypeDouble:514 case eTypeLongDouble:515 return m_scalar.UInt(fail_value);516 case eTypeBytes: {517 switch (buffer.bytes.size()) {518 default:519 break;520 case 1:521 case 2:522 case 4:523 return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());524 }525 } break;526 }527 if (success_ptr)528 *success_ptr = false;529 return fail_value;530}531 532uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value,533 bool *success_ptr) const {534 if (success_ptr)535 *success_ptr = true;536 switch (m_type) {537 default:538 break;539 case eTypeUInt8:540 case eTypeUInt16:541 case eTypeUInt32:542 case eTypeUInt64:543 case eTypeFloat:544 case eTypeDouble:545 case eTypeLongDouble:546 return m_scalar.ULongLong(fail_value);547 case eTypeBytes: {548 switch (buffer.bytes.size()) {549 default:550 break;551 case 1:552 return *(const uint8_t *)buffer.bytes.data();553 case 2:554 return *reinterpret_cast<const uint16_t *>(buffer.bytes.data());555 case 4:556 return *reinterpret_cast<const uint32_t *>(buffer.bytes.data());557 case 8:558 return *reinterpret_cast<const uint64_t *>(buffer.bytes.data());559 }560 } break;561 }562 if (success_ptr)563 *success_ptr = false;564 return fail_value;565}566 567llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value,568 bool *success_ptr) const {569 if (success_ptr)570 *success_ptr = true;571 switch (m_type) {572 default:573 break;574 case eTypeUInt8:575 case eTypeUInt16:576 case eTypeUInt32:577 case eTypeUInt64:578 case eTypeUIntN:579 case eTypeFloat:580 case eTypeDouble:581 case eTypeLongDouble:582 return m_scalar.UInt128(fail_value);583 case eTypeBytes: {584 switch (buffer.bytes.size()) {585 default:586 break;587 case 1:588 case 2:589 case 4:590 case 8:591 case 16:592 return llvm::APInt(593 BITWIDTH_INT128,594 llvm::ArrayRef(595 (reinterpret_cast<const type128 *>(buffer.bytes.data()))->x,596 NUM_OF_WORDS_INT128));597 }598 } break;599 }600 if (success_ptr)601 *success_ptr = false;602 return fail_value;603}604 605float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const {606 if (success_ptr)607 *success_ptr = true;608 switch (m_type) {609 default:610 break;611 case eTypeUInt32:612 case eTypeUInt64:613 case eTypeUIntN:614 case eTypeFloat:615 case eTypeDouble:616 case eTypeLongDouble:617 return m_scalar.Float(fail_value);618 }619 if (success_ptr)620 *success_ptr = false;621 return fail_value;622}623 624double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const {625 if (success_ptr)626 *success_ptr = true;627 switch (m_type) {628 default:629 break;630 631 case eTypeUInt32:632 case eTypeUInt64:633 case eTypeUIntN:634 case eTypeFloat:635 case eTypeDouble:636 case eTypeLongDouble:637 return m_scalar.Double(fail_value);638 }639 if (success_ptr)640 *success_ptr = false;641 return fail_value;642}643 644long double RegisterValue::GetAsLongDouble(long double fail_value,645 bool *success_ptr) const {646 if (success_ptr)647 *success_ptr = true;648 switch (m_type) {649 default:650 break;651 652 case eTypeUInt32:653 case eTypeUInt64:654 case eTypeUIntN:655 case eTypeFloat:656 case eTypeDouble:657 case eTypeLongDouble:658 return m_scalar.LongDouble();659 }660 if (success_ptr)661 *success_ptr = false;662 return fail_value;663}664 665const void *RegisterValue::GetBytes() const {666 switch (m_type) {667 case eTypeInvalid:668 break;669 case eTypeUInt8:670 case eTypeUInt16:671 case eTypeUInt32:672 case eTypeUInt64:673 case eTypeUIntN:674 case eTypeFloat:675 case eTypeDouble:676 case eTypeLongDouble:677 m_scalar.GetBytes(buffer.bytes);678 return buffer.bytes.data();679 case eTypeBytes:680 return buffer.bytes.data();681 }682 return nullptr;683}684 685uint32_t RegisterValue::GetByteSize() const {686 switch (m_type) {687 case eTypeInvalid:688 break;689 case eTypeUInt8:690 return 1;691 case eTypeUInt16:692 return 2;693 case eTypeUInt32:694 case eTypeUInt64:695 case eTypeUIntN:696 case eTypeFloat:697 case eTypeDouble:698 case eTypeLongDouble:699 return m_scalar.GetByteSize();700 case eTypeBytes:701 return buffer.bytes.size();702 }703 return 0;704}705 706bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) {707 if (byte_size == 0) {708 SetUInt64(uint);709 } else if (byte_size == 1) {710 SetUInt8(uint);711 } else if (byte_size <= 2) {712 SetUInt16(uint);713 } else if (byte_size <= 4) {714 SetUInt32(uint);715 } else if (byte_size <= 8) {716 SetUInt64(uint);717 } else if (byte_size <= 16) {718 SetUIntN(llvm::APInt(128, uint));719 } else720 return false;721 return true;722}723 724void RegisterValue::SetBytes(const void *bytes, size_t length,725 lldb::ByteOrder byte_order) {726 if (bytes && length > 0) {727 m_type = eTypeBytes;728 buffer.bytes.resize(length);729 memcpy(buffer.bytes.data(), bytes, length);730 buffer.byte_order = byte_order;731 } else {732 m_type = eTypeInvalid;733 buffer.bytes.resize(0);734 }735}736 737bool RegisterValue::operator==(const RegisterValue &rhs) const {738 if (m_type == rhs.m_type) {739 switch (m_type) {740 case eTypeInvalid:741 return true;742 case eTypeUInt8:743 case eTypeUInt16:744 case eTypeUInt32:745 case eTypeUInt64:746 case eTypeUIntN:747 case eTypeFloat:748 case eTypeDouble:749 case eTypeLongDouble:750 return m_scalar == rhs.m_scalar;751 case eTypeBytes:752 return buffer.bytes == rhs.buffer.bytes;753 }754 }755 return false;756}757 758bool RegisterValue::operator!=(const RegisterValue &rhs) const {759 return !(*this == rhs);760}761 762bool RegisterValue::ClearBit(uint32_t bit) {763 switch (m_type) {764 case eTypeInvalid:765 break;766 767 case eTypeUInt8:768 case eTypeUInt16:769 case eTypeUInt32:770 case eTypeUInt64:771 case eTypeUIntN:772 if (bit < (GetByteSize() * 8)) {773 return m_scalar.ClearBit(bit);774 }775 break;776 777 case eTypeFloat:778 case eTypeDouble:779 case eTypeLongDouble:780 break;781 782 case eTypeBytes:783 if (buffer.byte_order == eByteOrderBig ||784 buffer.byte_order == eByteOrderLittle) {785 uint32_t byte_idx;786 if (buffer.byte_order == eByteOrderBig)787 byte_idx = buffer.bytes.size() - (bit / 8) - 1;788 else789 byte_idx = bit / 8;790 791 const uint32_t byte_bit = bit % 8;792 if (byte_idx < buffer.bytes.size()) {793 buffer.bytes[byte_idx] &= ~(1u << byte_bit);794 return true;795 }796 }797 break;798 }799 return false;800}801 802bool RegisterValue::SetBit(uint32_t bit) {803 switch (m_type) {804 case eTypeInvalid:805 break;806 807 case eTypeUInt8:808 case eTypeUInt16:809 case eTypeUInt32:810 case eTypeUInt64:811 case eTypeUIntN:812 if (bit < (GetByteSize() * 8)) {813 return m_scalar.SetBit(bit);814 }815 break;816 817 case eTypeFloat:818 case eTypeDouble:819 case eTypeLongDouble:820 break;821 822 case eTypeBytes:823 if (buffer.byte_order == eByteOrderBig ||824 buffer.byte_order == eByteOrderLittle) {825 uint32_t byte_idx;826 if (buffer.byte_order == eByteOrderBig)827 byte_idx = buffer.bytes.size() - (bit / 8) - 1;828 else829 byte_idx = bit / 8;830 831 const uint32_t byte_bit = bit % 8;832 if (byte_idx < buffer.bytes.size()) {833 buffer.bytes[byte_idx] |= (1u << byte_bit);834 return true;835 }836 }837 break;838 }839 return false;840}841