brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.2 KiB · 4d762dc Raw
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 &reg_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 &reg_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 &reg_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 &reg_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