_ZNK6google4hoth8internal17PayloadUpdateImpl8initiateEv:
   56|  2.14k|{
   57|  2.14k|    sendCommand(PAYLOAD_UPDATE_INITIATE);
  ------------------
  |  |  180|  2.14k|#define PAYLOAD_UPDATE_INITIATE 0
  ------------------
   58|  2.14k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl5eraseEjj:
   61|    723|{
   62|    723|    sendCommand(PAYLOAD_UPDATE_ERASE, offset, size);
  ------------------
  |  |  188|    723|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
   63|    723|}
_ZNK6google4hoth8internal17PayloadUpdateImpl14findDescriptorERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPj:
   67|  2.81k|{
   68|  2.81k|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
   69|       |
   70|  2.81k|    if (*fd < 0)
  ------------------
  |  Branch (70:9): [True: 0, False: 2.81k]
  ------------------
   71|      0|    {
   72|      0|        (void)fd.release();
   73|      0|        throw errnoException(std::format("Failed to open file {}", path));
   74|      0|    }
   75|       |
   76|  2.81k|    auto seekRet = sys->lseek(*fd, 0, SEEK_END);
   77|  2.81k|    size_t fsize = seekRet;
   78|       |
   79|  2.81k|    if (seekRet < 0)
  ------------------
  |  Branch (79:9): [True: 0, False: 2.81k]
  ------------------
   80|      0|    {
   81|      0|        throw errnoException(std::format("Error seeking on file", path));
   82|      0|    }
   83|       |
   84|  2.81k|    uint64_t read_data = 0;
   85|  2.81k|    bool desc_found = false;
   86|       |
   87|       |    // Find the nearest aligned address to the end of the file. We can't
   88|       |    // assume that the file-size is aligned.
   89|  2.81k|    ssize_t offset = static_cast<ssize_t>(
   90|  2.81k|        (fsize / kImageDescriptorAlignment) * kImageDescriptorAlignment);
   91|  2.81k|    if (offset + sizeof(kDescriptorMagic) > fsize)
  ------------------
  |  Branch (91:9): [True: 454, False: 2.36k]
  ------------------
   92|    454|    {
   93|    454|        offset -= kImageDescriptorAlignment;
   94|    454|    }
   95|       |
   96|  3.97k|    for (; offset >= 0; offset -= kImageDescriptorAlignment)
  ------------------
  |  Branch (96:12): [True: 3.08k, False: 891]
  ------------------
   97|  3.08k|    {
   98|  3.08k|        auto seek = sys->lseek(*fd, offset, SEEK_SET);
   99|  3.08k|        if (seek < 0)
  ------------------
  |  Branch (99:13): [True: 0, False: 3.08k]
  ------------------
  100|      0|        {
  101|      0|            throw errnoException(std::format("Error seeking on file", path));
  102|      0|        }
  103|       |
  104|  3.08k|        auto actualReadSize = sys->read(*fd, &read_data, sizeof(read_data));
  105|       |
  106|  3.08k|        if (actualReadSize < 0)
  ------------------
  |  Branch (106:13): [True: 0, False: 3.08k]
  ------------------
  107|      0|        {
  108|      0|            throw errnoException(
  109|      0|                std::format("Failed to read from file {}", path));
  110|      0|        }
  111|       |
  112|  3.08k|        if (read_data == kDescriptorMagic)
  ------------------
  |  Branch (112:13): [True: 1.92k, False: 1.15k]
  ------------------
  113|  1.92k|        {
  114|  1.92k|            if (desc_offset)
  ------------------
  |  Branch (114:17): [True: 1.92k, False: 0]
  ------------------
  115|  1.92k|            {
  116|  1.92k|                *desc_offset = offset;
  117|  1.92k|                desc_found = true;
  118|  1.92k|                break;
  119|  1.92k|            }
  120|  1.92k|        }
  121|  3.08k|    }
  122|       |
  123|  2.81k|    return desc_found;
  124|  2.81k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl27eraseAndSendStaticWPRegionsERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEj:
  128|  1.92k|{
  129|  1.92k|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
  130|       |
  131|  1.92k|    if (*fd < 0)
  ------------------
  |  Branch (131:9): [True: 0, False: 1.92k]
  ------------------
  132|      0|    {
  133|      0|        (void)fd.release();
  134|      0|        throw errnoException(std::format("Failed to open file {}", path));
  135|      0|    }
  136|       |
  137|  1.92k|    struct image_descriptor descriptor;
  138|       |
  139|  1.92k|    if (sys->lseek(*fd, desc_offset, SEEK_SET) < 0)
  ------------------
  |  Branch (139:9): [True: 0, False: 1.92k]
  ------------------
  140|      0|    {
  141|      0|        throw errnoException(std::format("Error seeking on file", path));
  142|      0|    }
  143|  1.92k|    auto actualReadSize = sys->read(*fd, &descriptor, sizeof(descriptor));
  144|       |
  145|  1.92k|    if (actualReadSize < 0)
  ------------------
  |  Branch (145:9): [True: 0, False: 1.92k]
  ------------------
  146|      0|    {
  147|      0|        throw errnoException(std::format("Failed to read from file {}", path));
  148|      0|    }
  149|       |
  150|  1.92k|    if (descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
  ------------------
  |  |   70|  3.85k|#define DESCRIPTOR_MAGIC 0x5f435344474d495f // "_IMGDSC_"
  ------------------
  |  Branch (150:9): [True: 0, False: 1.92k]
  ------------------
  151|  1.92k|        descriptor.descriptor_offset != desc_offset ||
  ------------------
  |  Branch (151:9): [True: 159, False: 1.76k]
  ------------------
  152|  1.76k|        descriptor.region_count == 0)
  ------------------
  |  Branch (152:9): [True: 90, False: 1.67k]
  ------------------
  153|    249|    {
  154|    249|        throw errnoException(
  155|    249|            std::format("Invalid descriptor at offset {}", path));
  156|    249|    }
  157|       |
  158|  1.67k|    std::vector<struct image_region> image_regions(descriptor.region_count);
  159|       |
  160|  1.67k|    actualReadSize =
  161|  1.67k|        sys->read(*fd, image_regions.data(),
  162|  1.67k|                  sizeof(struct image_region) * descriptor.region_count);
  163|  1.67k|    if (actualReadSize < 0)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.67k]
  ------------------
  164|      0|    {
  165|      0|        throw errnoException(std::format("Failed to read from file {}", path));
  166|      0|    }
  167|       |
  168|       |    // Erase all the static and Write Protected regions of the payload
  169|   113k|    for (uint32_t i = 0; i < descriptor.region_count; i++)
  ------------------
  |  Branch (169:26): [True: 112k, False: 1.28k]
  ------------------
  170|   112k|    {
  171|   112k|        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
  ------------------
  |  |   55|   112k|#define IMAGE_REGION_STATIC                     (1 << 0)
  ------------------
  |  Branch (171:13): [True: 2.29k, False: 110k]
  ------------------
  172|   110k|            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
  ------------------
  |  |   57|   110k|#define IMAGE_REGION_WRITE_PROTECTED            (1 << 2)
  ------------------
  |  Branch (172:13): [True: 636, False: 109k]
  ------------------
  173|  2.93k|        {
  174|  2.93k|            if (image_regions[i].region_size == 0 ||
  ------------------
  |  Branch (174:17): [True: 77, False: 2.85k]
  ------------------
  175|  2.85k|                (image_regions[i].region_size % kSectorSizeBytes) != 0)
  ------------------
  |  Branch (175:17): [True: 317, False: 2.53k]
  ------------------
  176|    394|            {
  177|    394|                throw errnoException(std::format("invalid staging area size"));
  178|    394|            }
  179|  2.53k|            uint32_t regionOffset = image_regions[i].region_offset;
  180|  2.53k|            uint32_t toEraseSize = image_regions[i].region_size;
  181|  24.9M|            while (toEraseSize >= kEraseChunkSizeBytes)
  ------------------
  |  Branch (181:20): [True: 24.9M, False: 2.53k]
  ------------------
  182|  24.9M|            {
  183|  24.9M|                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset,
  ------------------
  |  |  188|  24.9M|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
  184|  24.9M|                            kEraseChunkSizeBytes);
  185|  24.9M|                regionOffset += kEraseChunkSizeBytes;
  186|  24.9M|                toEraseSize -= kEraseChunkSizeBytes;
  187|  24.9M|            }
  188|  2.53k|            if (toEraseSize > 0)
  ------------------
  |  Branch (188:17): [True: 1.88k, False: 652]
  ------------------
  189|  1.88k|            {
  190|  1.88k|                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset, toEraseSize);
  ------------------
  |  |  188|  1.88k|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
  191|  1.88k|            }
  192|  2.53k|        }
  193|   112k|    }
  194|       |
  195|       |    // Read and send static and WP sections of the payload
  196|  29.8k|    for (uint32_t i = 0; i < descriptor.region_count; i++)
  ------------------
  |  Branch (196:26): [True: 29.4k, False: 330]
  ------------------
  197|  29.4k|    {
  198|  29.4k|        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
  ------------------
  |  |   55|  29.4k|#define IMAGE_REGION_STATIC                     (1 << 0)
  ------------------
  |  Branch (198:13): [True: 1.36k, False: 28.1k]
  ------------------
  199|  28.1k|            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
  ------------------
  |  |   57|  28.1k|#define IMAGE_REGION_WRITE_PROTECTED            (1 << 2)
  ------------------
  |  Branch (199:13): [True: 308, False: 27.8k]
  ------------------
  200|  1.66k|        {
  201|  1.66k|            uint32_t offset = image_regions[i].region_offset;
  202|  1.66k|            auto regionSize = image_regions[i].region_size;
  203|  1.66k|            size_t readSize = 0;
  204|  1.66k|            std::vector<uint8_t> readBuffer(max_packet_size);
  205|       |
  206|  1.66k|            if (sys->lseek(*fd, offset, SEEK_SET) != offset)
  ------------------
  |  Branch (206:17): [True: 531, False: 1.13k]
  ------------------
  207|    531|            {
  208|    531|                throw errnoException(
  209|    531|                    std::format("Failed to read file size {}", path));
  210|    531|            }
  211|  1.13k|            do
  212|  15.6k|            {
  213|  15.6k|                if (regionSize <= max_packet_size)
  ------------------
  |  Branch (213:21): [True: 766, False: 14.8k]
  ------------------
  214|    766|                {
  215|    766|                    readSize = regionSize;
  216|    766|                }
  217|  14.8k|                else
  218|  14.8k|                {
  219|  14.8k|                    readSize = max_packet_size;
  220|  14.8k|                }
  221|       |
  222|  15.6k|                if (!sys->read(*fd, readBuffer.data(), readSize))
  ------------------
  |  Branch (222:21): [True: 421, False: 15.1k]
  ------------------
  223|    421|                {
  224|    421|                    throw errnoException(
  225|    421|                        std::format("Failed to read from file {}", path));
  226|    421|                }
  227|       |
  228|       |                // Decided not to use initializer list to create the span here
  229|       |                // as actualReadSize is ssize_t and we'd need to static_cast
  230|  15.1k|                trimAndSend(std::span<uint8_t>(readBuffer.data(), readSize),
  231|  15.1k|                            offset);
  232|  15.1k|                offset += readSize;
  233|  15.1k|                regionSize -= readSize;
  234|       |
  235|  15.1k|            } while (regionSize); // actualReadSize will be 0 when EOF is
  ------------------
  |  Branch (235:22): [True: 14.4k, False: 716]
  ------------------
  236|       |                                  // reached, exit loop
  237|  1.13k|        }
  238|  29.4k|    }
  239|  1.28k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl20eraseAndSendStaticWPERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  242|  2.81k|{
  243|  2.81k|    uint32_t desc_offset = 0;
  244|       |
  245|  2.81k|    if (!findDescriptor(path, &desc_offset))
  ------------------
  |  Branch (245:9): [True: 891, False: 1.92k]
  ------------------
  246|    891|    {
  247|    891|        throw errnoException(std::format("No valid descriptor found"));
  248|    891|    }
  249|       |
  250|  1.92k|    eraseAndSendStaticWPRegions(path, desc_offset);
  251|  1.92k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl4readEjNSt3__14spanIhLm18446744073709551615EEE:
  254|  1.62k|{
  255|  1.62k|    std::vector<uint8_t> buf;
  256|  1.62k|    auto rsp = sendCommand(buf, PAYLOAD_UPDATE_READ, offset, data.size());
  ------------------
  |  |  186|  1.62k|#define PAYLOAD_UPDATE_READ 6
  ------------------
  257|  1.62k|    if (rsp.size() != data.size())
  ------------------
  |  Branch (257:9): [True: 1.38k, False: 243]
  ------------------
  258|  1.38k|    {
  259|  1.38k|        stdplus::print(
  260|  1.38k|            stderr,
  261|  1.38k|            "Payload command received a short response from Hoth `{} < {}`\n",
  262|  1.38k|            rsp.size(), data.size());
  263|  1.38k|        throw ResponseFailure();
  264|  1.38k|    }
  265|    243|    memcpy(data.data(), rsp.data(), data.size());
  266|    243|}
_ZNK6google4hoth8internal17PayloadUpdateImpl6verifyEv:
  269|    525|{
  270|    525|    payload_update_packet request = {};
  271|    525|    request.type = PAYLOAD_UPDATE_VERIFY_DESCRIPTOR;
  ------------------
  |  |  191|    525|#define PAYLOAD_UPDATE_VERIFY_DESCRIPTOR 11
  ------------------
  272|    525|    auto buf = hostCmd->sendCommand(
  273|    525|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|    525|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|    525|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  274|    525|        &request, sizeof(request));
  275|    525|    std::span<uint8_t> rsp = buf;
  276|    525|    auto& hdr = stdplus::raw::extractRef<RspHeader>(rsp);
  277|       |
  278|       |    // In case PAYLOAD_UPDATE_VERIFY is not supported (EC_RES_ERROR),
  279|       |    // we fall back to PAYLOAD_UPDATE_VERIFY instead.
  280|    525|    if (hdr.result == EC_RES_INVALID_PARAM || hdr.result == EC_RES_ERROR)
  ------------------
  |  Branch (280:9): [True: 0, False: 525]
  |  Branch (280:47): [True: 0, False: 525]
  ------------------
  281|      0|    {
  282|      0|        sendCommand(PAYLOAD_UPDATE_VERIFY);
  ------------------
  |  |  184|      0|#define PAYLOAD_UPDATE_VERIFY 4
  ------------------
  283|      0|        return;
  284|      0|    }
  285|    525|    if (hdr.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (285:9): [True: 0, False: 525]
  ------------------
  286|      0|    {
  287|       |        stdplus::print(stderr, "VERIFY_DESCRIPTOR error: {:#x}\n",
  288|      0|                       static_cast<uint8_t>(hdr.result));
  289|      0|        throw ResponseFailure();
  290|      0|    }
  291|    525|}
_ZNK6google4hoth8internal17PayloadUpdateImpl9getStatusEv:
  294|    733|{
  295|    733|    std::vector<uint8_t> buf;
  296|    733|    std::span<const uint8_t> output =
  297|    733|        sendCommand(buf, PAYLOAD_UPDATE_GET_STATUS);
  ------------------
  |  |  187|    733|#define PAYLOAD_UPDATE_GET_STATUS 7
  ------------------
  298|       |
  299|    733|    return stdplus::raw::copyFrom<payload_update_status>(output);
  300|    733|}
_ZNK6google4hoth8internal17PayloadUpdateImpl8activateENS1_4SideENS1_11PersistenceE:
  303|    506|{
  304|    506|    ActivateRequest request;
  305|    506|    request.header.offset = 0;
  306|    506|    request.header.len = sizeof(request.activate);
  307|    506|    request.header.type = PAYLOAD_UPDATE_ACTIVATE;
  ------------------
  |  |  185|    506|#define PAYLOAD_UPDATE_ACTIVATE 5
  ------------------
  308|    506|    request.activate.half = static_cast<uint8_t>(side);
  309|    506|    request.activate.make_persistent = static_cast<uint8_t>(persistence);
  310|       |
  311|    506|    sendCommand(
  312|    506|        {reinterpret_cast<const uint8_t*>(&request), sizeof(ActivateRequest)});
  313|    506|}
_ZNK6google4hoth8internal17PayloadUpdateImpl7confirmE29payload_update_confirm_optionjm:
  318|    707|{
  319|    707|    ConfirmRequest request;
  320|    707|    request.header.offset = 0;
  321|    707|    request.header.len = sizeof(request.confirm);
  322|    707|    request.header.type = PAYLOAD_UPDATE_CONFIRM;
  ------------------
  |  |  190|    707|#define PAYLOAD_UPDATE_CONFIRM 10
  ------------------
  323|    707|    request.confirm.option = option;
  324|    707|    request.confirm.timeout_value = boost::endian::native_to_little(timeout);
  325|    707|    request.confirm.confirmation_cookie =
  326|    707|        boost::endian::native_to_little(confirmation_cookie);
  327|       |
  328|    707|    std::vector<uint8_t> buf = hostCmd->sendCommand(
  329|    707|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|    707|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|    707|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  330|    707|        &request, sizeof(request));
  331|       |    // Extract the response header out when returning the span
  332|    707|    std::span<const uint8_t> output = buf;
  333|    707|    auto rsp = stdplus::raw::extract<RspHeader>(output);
  334|    707|    if (rsp.result == HOTH_PAYLOAD_UPDATE_CONFIRM_NO_PENDING_PAYLOAD)
  ------------------
  |  Branch (334:9): [True: 0, False: 707]
  ------------------
  335|      0|    {
  336|      0|        return std::nullopt;
  337|      0|    }
  338|       |
  339|    707|    if (rsp.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (339:9): [True: 0, False: 707]
  ------------------
  340|      0|    {
  341|      0|        stdplus::print(
  342|      0|            stderr,
  343|      0|            "Payload confirm command received a bad response from Hoth {:#x}\n",
  344|      0|            static_cast<uint8_t>(rsp.result));
  345|      0|        throw ResponseFailure();
  346|      0|    }
  347|       |
  348|    707|    return stdplus::raw::copyFrom<payload_update_confirm_response>(output);
  349|    707|}
_ZNK6google4hoth8internal17PayloadUpdateImpl4sendERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  382|    900|{
  383|    900|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
  384|       |
  385|    900|    if (*fd < 0)
  ------------------
  |  Branch (385:9): [True: 0, False: 900]
  ------------------
  386|      0|    {
  387|      0|        (void)fd.release();
  388|      0|        throw errnoException(std::format("Failed to open file {}", path));
  389|      0|    }
  390|       |
  391|    900|    std::array<uint8_t, max_packet_size> readBuffer;
  392|    900|    uint32_t offset = 0;
  393|    900|    ssize_t actualReadSize = 0;
  394|       |    // Read and send payload until we reach EOF of the given file
  395|    900|    do
  396|  8.03k|    {
  397|  8.03k|        actualReadSize = sys->read(*fd, readBuffer.data(), max_packet_size);
  398|       |
  399|  8.03k|        if (actualReadSize < 0)
  ------------------
  |  Branch (399:13): [True: 0, False: 8.03k]
  ------------------
  400|      0|        {
  401|      0|            throw errnoException(
  402|      0|                std::format("Failed to read from file {}", path));
  403|      0|        }
  404|  8.03k|        if (actualReadSize > 0)
  ------------------
  |  Branch (404:13): [True: 7.13k, False: 900]
  ------------------
  405|  7.13k|        {
  406|       |            // Decided not to use initializer list to create the span here as
  407|       |            // actualReadSize is ssize_t and we'd need to static_cast
  408|  7.13k|            trimAndSend(std::span<uint8_t>(readBuffer.data(), actualReadSize),
  409|  7.13k|                        offset);
  410|  7.13k|            offset += actualReadSize;
  411|  7.13k|        }
  412|       |        // actualReadSize will be 0 when EOF is reached, exit loop
  413|  8.03k|    } while (actualReadSize);
  ------------------
  |  Branch (413:14): [True: 7.13k, False: 900]
  ------------------
  414|    900|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11trimAndSendENSt3__14spanIKhLm18446744073709551615EEEj:
  425|  22.3k|{
  426|       |    // Allocate the payload buffer at "buffer".
  427|       |    // "request" will point to the payload_update_packet section of the buffer
  428|       |    // "request_payload" will point to the beginning of the payload
  429|       |    // (after the payload_update_packet header).
  430|  22.3k|    std::array<uint8_t, sizeof(payload_update_packet) + max_packet_size> buffer;
  431|  22.3k|    payload_update_packet* request =
  432|  22.3k|        reinterpret_cast<payload_update_packet*>(buffer.data());
  433|  22.3k|    uint8_t* request_payload = &buffer[sizeof(payload_update_packet)];
  434|       |
  435|  22.3k|    const size_t dataSize = data.size();
  436|  22.3k|    if (dataSize > max_packet_size)
  ------------------
  |  Branch (436:9): [True: 0, False: 22.3k]
  ------------------
  437|      0|    {
  438|      0|        throw errnoException(
  439|      0|            "data to send cannot be bigger than max_packet_size");
  440|      0|    }
  441|  22.3k|    size_t localOffset = SizeToSkip(data);
  442|  22.3k|    if (localOffset >= dataSize)
  ------------------
  |  Branch (442:9): [True: 522, False: 21.8k]
  ------------------
  443|    522|    {
  444|       |        // No need to send any payload
  445|    522|        return;
  446|    522|    }
  447|  21.8k|    size_t max_size_to_send = std::min(dataSize - localOffset, max_packet_size);
  448|  21.8k|    size_t size_to_send =
  449|  21.8k|        SizeToSend(data.subspan(localOffset, max_size_to_send));
  450|       |
  451|       |    // Construct and send payload
  452|  21.8k|    request->offset = globalOffset + localOffset;
  453|  21.8k|    request->len = size_to_send;
  454|  21.8k|    request->type = PAYLOAD_UPDATE_CONTINUE;
  ------------------
  |  |  181|  21.8k|#define PAYLOAD_UPDATE_CONTINUE 1
  ------------------
  455|  21.8k|    memcpy(request_payload, &data[localOffset], size_to_send);
  456|  21.8k|    sendCommand({buffer.data(), sizeof(*request) + size_to_send});
  457|  21.8k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandEhjj:
  461|  24.9M|{
  462|  24.9M|    std::vector<uint8_t> buf;
  463|  24.9M|    (void)sendCommand(buf, command, offset, len);
  464|  24.9M|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandENSt3__14spanIKhLm18446744073709551615EEE:
  467|  22.3k|{
  468|  22.3k|    std::vector<uint8_t> buf;
  469|  22.3k|    (void)sendCommand(buf, request);
  470|  22.3k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandERNSt3__16vectorIhNS3_9allocatorIhEEEEhjj:
  475|  24.9M|{
  476|       |    // For most basic commands, request offset and length are zero
  477|  24.9M|    payload_update_packet request;
  478|  24.9M|    request.offset = offset;
  479|  24.9M|    request.len = len;
  480|  24.9M|    request.type = command;
  481|  24.9M|    return sendCommand(buf, {reinterpret_cast<const uint8_t*>(&request),
  482|  24.9M|                             sizeof(payload_update_packet)});
  483|  24.9M|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandERNSt3__16vectorIhNS3_9allocatorIhEEEENS3_4spanIKhLm18446744073709551615EEE:
  487|  24.9M|{
  488|  24.9M|    buf = hostCmd->sendCommand(
  489|  24.9M|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|  24.9M|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|  24.9M|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  490|  24.9M|        request.data(), request.size());
  491|       |    // Extract the response header out when returning the span
  492|  24.9M|    std::span<const uint8_t> output = buf;
  493|  24.9M|    auto rsp = stdplus::raw::extract<RspHeader>(output);
  494|  24.9M|    if (rsp.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (494:9): [True: 0, False: 24.9M]
  ------------------
  495|      0|    {
  496|      0|        stdplus::print(
  497|      0|            stderr, "Payload command received a bad response from Hoth {:#x}\n",
  498|      0|            static_cast<uint8_t>(rsp.result));
  499|      0|        throw ResponseFailure();
  500|      0|    }
  501|       |
  502|  24.9M|    return output;
  503|  24.9M|}
payload_update.cpp:_ZN6google4hoth8internal12_GLOBAL__N_110SizeToSkipENSt3__14spanIKhLm18446744073709551615EEE:
  355|  22.3k|{
  356|  22.3k|    size_t i;
  357|   440k|    for (i = 0; i < data.size(); i++)
  ------------------
  |  Branch (357:17): [True: 439k, False: 522]
  ------------------
  358|   439k|    {
  359|   439k|        if (data[i] != 0xff)
  ------------------
  |  Branch (359:13): [True: 21.8k, False: 418k]
  ------------------
  360|  21.8k|        {
  361|  21.8k|            break;
  362|  21.8k|        }
  363|   439k|    }
  364|  22.3k|    return i;
  365|  22.3k|}
payload_update.cpp:_ZN6google4hoth8internal12_GLOBAL__N_110SizeToSendENSt3__14spanIKhLm18446744073709551615EEE:
  368|  21.8k|{
  369|  21.8k|    size_t i;
  370|   226k|    for (i = data.size(); i > 0; i--)
  ------------------
  |  Branch (370:27): [True: 226k, False: 0]
  ------------------
  371|   226k|    {
  372|   226k|        if (data[i - 1] != 0xff)
  ------------------
  |  Branch (372:13): [True: 21.8k, False: 204k]
  ------------------
  373|  21.8k|        {
  374|  21.8k|            break;
  375|  21.8k|        }
  376|   226k|    }
  377|  21.8k|    return i;
  378|  21.8k|}

_ZN6google4hoth8internal17PayloadUpdateImpl7closeFdEOiRPKNS1_3SysE:
  107|  5.64k|    {
  108|  5.64k|        if (sys)
  ------------------
  |  Branch (108:13): [True: 5.64k, False: 0]
  ------------------
  109|  5.64k|        {
  110|  5.64k|            sys->close(fd);
  111|  5.64k|        }
  112|  5.64k|    }
_ZN6google4hoth8internal17PayloadUpdateImplC2EPNS1_11HostCommandEPKNS1_3SysE:
   73|  1.01k|        hostCmd(hostCmd), sys(sys)
   74|  1.01k|    {}

_ZN6google4hoth8internal14errnoExceptionERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
   49|  2.48k|{
   50|       |    return std::system_error(errno, std::generic_category(), message);
   51|  2.48k|}

LLVMFuzzerTestOneInput:
  117|  1.01k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  118|  1.01k|    if (size < 2) return 0;
  ------------------
  |  Branch (118:9): [True: 1, False: 1.01k]
  ------------------
  119|       |
  120|  1.01k|    FuzzedDataProvider provider(data, size);
  121|       |
  122|       |    // Allocate up to 80% of fuzzer data to represent the firmware file contents
  123|  1.01k|    size_t file_data_len = provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes() * 8 / 10);
  124|  1.01k|    std::vector<uint8_t> file_data = provider.ConsumeBytes<uint8_t>(file_data_len);
  125|       |
  126|  1.01k|    FuzzerSys fuzzer_sys(file_data.data(), file_data.size());
  127|  1.01k|    FuzzerHostCommand fuzzer_host_cmd;
  128|  1.01k|    google::hoth::internal::PayloadUpdateImpl payload_update(&fuzzer_host_cmd, &fuzzer_sys);
  129|       |
  130|  1.01k|    size_t action_count = 0;
  131|  11.6k|    while (provider.remaining_bytes() > 0 && action_count < 20) {
  ------------------
  |  Branch (131:12): [True: 10.9k, False: 695]
  |  Branch (131:46): [True: 10.6k, False: 319]
  ------------------
  132|  10.6k|        action_count++;
  133|  10.6k|        uint8_t action = provider.ConsumeIntegralInRange<uint8_t>(0, 8);
  134|  10.6k|        try {
  135|  10.6k|            switch (action) {
  ------------------
  |  Branch (135:21): [True: 10.6k, False: 0]
  ------------------
  136|  2.14k|                case 0: {
  ------------------
  |  Branch (136:17): [True: 2.14k, False: 8.53k]
  ------------------
  137|  2.14k|                    payload_update.initiate();
  138|  2.14k|                    break;
  139|      0|                }
  140|    723|                case 1: {
  ------------------
  |  Branch (140:17): [True: 723, False: 9.95k]
  ------------------
  141|    723|                    uint32_t offset = provider.ConsumeIntegral<uint32_t>();
  142|    723|                    uint32_t size = provider.ConsumeIntegral<uint32_t>();
  143|    723|                    payload_update.erase(offset, size);
  144|    723|                    break;
  145|      0|                }
  146|  2.81k|                case 2: {
  ------------------
  |  Branch (146:17): [True: 2.81k, False: 7.86k]
  ------------------
  147|  2.81k|                    payload_update.eraseAndSendStaticWP("/tmp/fuzz_file");
  148|  2.81k|                    break;
  149|      0|                }
  150|  1.62k|                case 3: {
  ------------------
  |  Branch (150:17): [True: 1.62k, False: 9.05k]
  ------------------
  151|  1.62k|                    uint32_t offset = provider.ConsumeIntegral<uint32_t>();
  152|  1.62k|                    uint32_t read_len = provider.ConsumeIntegralInRange<uint32_t>(0, 1024);
  153|  1.62k|                    std::vector<uint8_t> read_buf(read_len);
  154|  1.62k|                    payload_update.read(offset, read_buf);
  155|  1.62k|                    break;
  156|      0|                }
  157|    525|                case 4: {
  ------------------
  |  Branch (157:17): [True: 525, False: 10.1k]
  ------------------
  158|    525|                    payload_update.verify();
  159|    525|                    break;
  160|      0|                }
  161|    733|                case 5: {
  ------------------
  |  Branch (161:17): [True: 733, False: 9.94k]
  ------------------
  162|    733|                    payload_update.getStatus();
  163|    733|                    break;
  164|      0|                }
  165|    506|                case 6: {
  ------------------
  |  Branch (165:17): [True: 506, False: 10.1k]
  ------------------
  166|    506|                    auto side = provider.PickValueInArray({google::hoth::internal::Side::A, google::hoth::internal::Side::B});
  167|    506|                    auto persistence = provider.PickValueInArray({google::hoth::internal::Persistence::kNonPersistent, google::hoth::internal::Persistence::kPersistent});
  168|    506|                    payload_update.activate(side, persistence);
  169|    506|                    break;
  170|      0|                }
  171|    900|                case 7: {
  ------------------
  |  Branch (171:17): [True: 900, False: 9.78k]
  ------------------
  172|    900|                    payload_update.send("/tmp/fuzz_file");
  173|    900|                    break;
  174|      0|                }
  175|    707|                case 8: {
  ------------------
  |  Branch (175:17): [True: 707, False: 9.97k]
  ------------------
  176|    707|                    auto option = provider.PickValueInArray({
  177|    707|                        payload_update_confirm_option::Enable,
  178|    707|                        payload_update_confirm_option::Enable_with_timeout,
  179|    707|                        payload_update_confirm_option::Disable,
  180|    707|                        payload_update_confirm_option::Confirm,
  181|    707|                        payload_update_confirm_option::Get_timeout_values
  182|    707|                    });
  183|    707|                    uint32_t timeout = provider.ConsumeIntegral<uint32_t>();
  184|    707|                    uint64_t cookie = provider.ConsumeIntegral<uint64_t>();
  185|    707|                    payload_update.confirm(option, timeout, cookie);
  186|    707|                    break;
  187|      0|                }
  188|  10.6k|            }
  189|  10.6k|        } catch (...) {
  190|       |            // Catch expected exceptions (e.g. from mock filesystem or D-Bus response failures)
  191|  5.30k|        }
  192|  10.6k|    }
  193|       |
  194|  1.01k|    return 0;
  195|  1.01k|}
_ZN9FuzzerSysC2EPKhm:
   37|  1.01k|    FuzzerSys(const uint8_t* data, size_t size) : data_(data), size_(size), offset_(0) {}
_ZNK9FuzzerSys4openEPKci:
   39|  5.64k|    int open(const char* pathname, int flags) const override {
   40|  5.64k|        return 42; // dummy fd
   41|  5.64k|    }
_ZNK9FuzzerSys5closeEi:
   43|  5.64k|    int close(int fd) const override {
   44|  5.64k|        return 0;
   45|  5.64k|    }
_ZNK9FuzzerSys5lseekEili:
   47|  9.48k|    off_t lseek(int fd, off_t offset, int whence) const override {
   48|  9.48k|        if (whence == SEEK_SET) {
  ------------------
  |  Branch (48:13): [True: 6.67k, False: 2.81k]
  ------------------
   49|  6.67k|            if (offset < 0 || static_cast<size_t>(offset) > size_) return -1;
  ------------------
  |  Branch (49:17): [True: 0, False: 6.67k]
  |  Branch (49:31): [True: 531, False: 6.14k]
  ------------------
   50|  6.14k|            offset_ = offset;
   51|  6.14k|        } else if (whence == SEEK_END) {
  ------------------
  |  Branch (51:20): [True: 2.81k, False: 0]
  ------------------
   52|  2.81k|            offset_ = size_;
   53|  2.81k|        } else if (whence == SEEK_CUR) {
  ------------------
  |  Branch (53:20): [True: 0, False: 0]
  ------------------
   54|      0|            if (static_cast<ssize_t>(offset_) + offset < 0 || static_cast<size_t>(offset_ + offset) > size_) return -1;
  ------------------
  |  Branch (54:17): [True: 0, False: 0]
  |  Branch (54:63): [True: 0, False: 0]
  ------------------
   55|      0|            offset_ += offset;
   56|      0|        }
   57|  8.95k|        return offset_;
   58|  9.48k|    }
_ZNK9FuzzerSys4readEiPvm:
   60|  30.3k|    ssize_t read(int fd, void* buf, size_t count) const override {
   61|  30.3k|        if (offset_ >= size_) return 0;
  ------------------
  |  Branch (61:13): [True: 1.41k, False: 28.9k]
  ------------------
   62|  28.9k|        size_t to_read = std::min(count, size_ - offset_);
   63|  28.9k|        std::memcpy(buf, data_ + offset_, to_read);
   64|  28.9k|        offset_ += to_read;
   65|  28.9k|        return to_read;
   66|  30.3k|    }
_ZN17FuzzerHostCommand11sendCommandEthPKvm:
   91|  24.9M|    std::vector<uint8_t> sendCommand(uint16_t command, uint8_t commandVersion, const void* request, size_t requestSize) override {
   92|       |        // Return a dummy response with EC_RES_SUCCESS
   93|  24.9M|        std::vector<uint8_t> rsp(sizeof(google::hoth::internal::RspHeader), 0);
   94|  24.9M|        auto* hdr = reinterpret_cast<google::hoth::internal::RspHeader*>(rsp.data());
   95|  24.9M|        hdr->result = google::hoth::internal::EC_RES_SUCCESS;
   96|  24.9M|        return rsp;
   97|  24.9M|    }

_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEEC2IJRKS6_EEESB_DpOT_:
   60|  5.64k|            as(std::forward<Vs>(vs)...), maybeT(std::move(maybeV))
   61|  5.64k|        {}
_ZNKR7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEEdeEv:
  110|  45.4k|        {
  111|  45.4k|            return *maybeT;
  112|  45.4k|        }
_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEED2Ev:
   92|  5.64k|        {
   93|  5.64k|            reset();
   94|  5.64k|        }
_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEE5resetEv:
  176|  5.64k|        {
  177|  5.64k|            reset(std::nullopt);
  178|  5.64k|        }
_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEE5resetEONSt3__18optionalIiEE:
  160|  5.64k|        {
  161|  5.64k|            maybeDrop(std::index_sequence_for<As...>());
  162|  5.64k|            maybeT = std::move(maybeV);
  163|  5.64k|        }
_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7HandleFINS7_7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEEE9maybeDropIJLm0EEEEvNSt3__116integer_sequenceImJXspT_EEEE:
  228|  5.64k|        {
  229|  5.64k|            if (maybeT)
  ------------------
  |  Branch (229:17): [True: 5.64k, False: 0]
  ------------------
  230|  5.64k|            {
  231|  5.64k|                Drop()(std::move(*maybeT), std::get<Indices>(as)...);
  232|  5.64k|            }
  233|  5.64k|        }
_ZN7stdplus7ManagedIiJPKN6google4hoth8internal3SysEEE7DropperIXadL_ZNS3_17PayloadUpdateImpl7closeFdEOiRS6_EEEclESA_SB_:
  240|  5.64k|        {
  241|  5.64k|            drop(std::move(t), as...);
  242|  5.64k|        }

_ZN7stdplus5printIJmmEEEvP8_IO_FILENSt3__119basic_format_stringIcJDpNS3_13type_identityIT_E4typeEEEEDpOS6_:
   31|  1.38k|{
   32|  1.38k|    Printer<false>::print(stream, fmt, std::forward<Args>(args)...);
   33|  1.38k|}
_ZN7stdplus7PrinterILb0EE5printIJmmEEEvP8_IO_FILENSt3__119basic_format_stringIcJDpNS5_13type_identityIT_E4typeEEEEDpOS8_:
   17|  1.38k|    {
   18|  1.38k|        stdplus::StrBuf buf;
   19|  1.38k|        std::format_to(std::back_inserter(buf), fmt,
   20|  1.38k|                       std::forward<Args>(args)...);
   21|       |        if constexpr (ln)
   22|       |        {
   23|       |            buf.push_back('\n');
   24|       |        }
   25|  1.38k|        prints(stream, buf);
   26|  1.38k|    }

_ZN7stdplus3raw10extractRefIN6google4hoth8internal9RspHeaderENS0_9UnAlignedETkNS_17TriviallyCopyableEhS5_EERT2_RNSt3__14spanIT1_Lm18446744073709551615EEE:
  170|    525|{
  171|    525|    Tp& ret = refFrom<Tp, A>(data);
  172|    525|    static_assert(sizeof(Tp) % sizeof(IntT) == 0);
  173|    525|    data = data.subspan(sizeof(Tp) / sizeof(IntT));
  174|    525|    return ret; // NOLINT(clang-analyzer-cplusplus.InnerPointer)
  175|    525|}
_ZN7stdplus3raw7refFromITkNS_17TriviallyCopyableEN6google4hoth8internal9RspHeaderENS0_9UnAlignedETkNS0_6detail15ContainsTrivialERNSt3__14spanIhLm18446744073709551615EEES5_EERT2_OT1_:
  115|    525|    {                                                                          \
  116|    525|        static_assert(std::is_same_v<A, Aligned> ||                            \
  117|    525|                      sizeof(*std::data(c)) % alignof(Tp) == 0);               \
  118|    525|        const size_t bytes = std::size(c) * sizeof(*std::data(c));             \
  119|    525|        if (bytes comp sizeof(Tp))                                             \
  ------------------
  |  Branch (119:13): [True: 0, False: 525]
  ------------------
  120|    525|        {                                                                      \
  121|      0|            throw exception::Incomplete(                                       \
  122|      0|                std::format(#func ": {} < {}", bytes, sizeof(Tp)));            \
  123|      0|        }                                                                      \
  124|    525|        return *reinterpret_cast<Tp*>(std::data(c));                           \
  125|    525|    }
_ZN7stdplus3raw8copyFromITkNS_17TriviallyCopyableE21payload_update_statusTkNS0_6detail15ContainsTrivialENSt3__14spanIKhLm18446744073709551615EEEEET_RKT0_:
   81|    733|    {                                                                          \
   82|    733|        T ret;                                                                 \
   83|    733|        const size_t bytes = std::size(c) * sizeof(*std::data(c));             \
   84|    733|        if (bytes comp sizeof(ret))                                            \
  ------------------
  |  Branch (84:13): [True: 733, False: 0]
  ------------------
   85|    733|        {                                                                      \
   86|    733|            throw exception::Incomplete(                                       \
   87|    733|                std::format(#func ": {} < {}", bytes, sizeof(ret)));           \
   88|    733|        }                                                                      \
   89|    733|        const auto c_bytes = reinterpret_cast<const std::byte*>(std::data(c)); \
   90|      0|        const auto ret_bytes = reinterpret_cast<std::byte*>(&ret);             \
   91|      0|        std::copy(c_bytes, c_bytes + sizeof(ret), ret_bytes);                  \
   92|      0|        return ret;                                                            \
   93|    733|    }
_ZN7stdplus3raw7extractIN6google4hoth8internal9RspHeaderETkNS_17TriviallyCopyableEKhEET_RNSt3__14spanIT0_Lm18446744073709551615EEE:
  146|  24.9M|{
  147|  24.9M|    T ret = copyFrom<T>(data);
  148|  24.9M|    static_assert(sizeof(T) % sizeof(IntT) == 0);
  149|  24.9M|    data = data.subspan(sizeof(T) / sizeof(IntT));
  150|  24.9M|    return ret;
  151|  24.9M|}
_ZN7stdplus3raw8copyFromITkNS_17TriviallyCopyableEN6google4hoth8internal9RspHeaderETkNS0_6detail15ContainsTrivialENSt3__14spanIKhLm18446744073709551615EEEEET_RKT0_:
   81|  24.9M|    {                                                                          \
   82|  24.9M|        T ret;                                                                 \
   83|  24.9M|        const size_t bytes = std::size(c) * sizeof(*std::data(c));             \
   84|  24.9M|        if (bytes comp sizeof(ret))                                            \
  ------------------
  |  Branch (84:13): [True: 0, False: 24.9M]
  ------------------
   85|  24.9M|        {                                                                      \
   86|      0|            throw exception::Incomplete(                                       \
   87|      0|                std::format(#func ": {} < {}", bytes, sizeof(ret)));           \
   88|      0|        }                                                                      \
   89|  24.9M|        const auto c_bytes = reinterpret_cast<const std::byte*>(std::data(c)); \
   90|  24.9M|        const auto ret_bytes = reinterpret_cast<std::byte*>(&ret);             \
   91|  24.9M|        std::copy(c_bytes, c_bytes + sizeof(ret), ret_bytes);                  \
   92|  24.9M|        return ret;                                                            \
   93|  24.9M|    }
_ZN7stdplus3raw8copyFromITkNS_17TriviallyCopyableE31payload_update_confirm_responseTkNS0_6detail15ContainsTrivialENSt3__14spanIKhLm18446744073709551615EEEEET_RKT0_:
   81|    707|    {                                                                          \
   82|    707|        T ret;                                                                 \
   83|    707|        const size_t bytes = std::size(c) * sizeof(*std::data(c));             \
   84|    707|        if (bytes comp sizeof(ret))                                            \
  ------------------
  |  Branch (84:13): [True: 707, False: 0]
  ------------------
   85|    707|        {                                                                      \
   86|    707|            throw exception::Incomplete(                                       \
   87|    707|                std::format(#func ": {} < {}", bytes, sizeof(ret)));           \
   88|    707|        }                                                                      \
   89|    707|        const auto c_bytes = reinterpret_cast<const std::byte*>(std::data(c)); \
   90|      0|        const auto ret_bytes = reinterpret_cast<std::byte*>(&ret);             \
   91|      0|        std::copy(c_bytes, c_bytes + sizeof(ret), ret_bytes);                  \
   92|      0|        return ret;                                                            \
   93|    707|    }

_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE6inlLenEh:
  100|  86.5k|    {
  101|  86.5k|        store.inl.len = len;
  102|  86.5k|    }
_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE8zeroInitEv:
  118|  1.38k|    {
  119|  1.38k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (119:13): [Folded, False: 1.38k]
  ------------------
  120|      0|        {
  121|      0|            store.dyn.ptr = allocate(buf_len);
  122|      0|            store.dyn.cap = buf_len;
  123|      0|            dynLen(0);
  124|      0|        }
  125|  1.38k|        else
  126|  1.38k|        {
  127|  1.38k|            inlLen(0);
  128|  1.38k|        }
  129|  1.38k|    }
_ZNK7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE5isDynEv:
   76|  89.3k|    {
   77|  89.3k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (77:13): [Folded, False: 89.3k]
  ------------------
   78|      0|        {
   79|      0|            return true;
   80|      0|        }
   81|  89.3k|        return store.inl.len & inl_mask;
   82|  89.3k|    }
_ZNK7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE6inlLenEv:
   95|  86.5k|    {
   96|  86.5k|        return store.inl.len;
   97|  86.5k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE6appendEm:
  298|  85.1k|    {
  299|  85.1k|        if (!as.isDyn())
  ------------------
  |  Branch (299:13): [True: 85.1k, False: 0]
  ------------------
  300|  85.1k|        {
  301|  85.1k|            const std::size_t oldlen = as.inlLen();
  302|  85.1k|            const std::size_t newlen = oldlen + amt;
  303|  85.1k|            if (newlen <= as.buf_len)
  ------------------
  |  Branch (303:17): [True: 85.1k, False: 0]
  ------------------
  304|  85.1k|            {
  305|  85.1k|                as.inlLen(newlen);
  306|  85.1k|                return as.store.inl.ptr + oldlen;
  307|  85.1k|            }
  308|      0|            const std::size_t newcap = newlen + (newlen >> 1);
  309|      0|            const auto ptr = as.allocate(newcap);
  310|      0|            std::copy(as.store.inl.ptr, as.store.inl.ptr + oldlen, ptr);
  311|       |
  312|      0|            as.store.dyn.ptr = ptr;
  313|      0|            as.store.dyn.cap = newcap;
  314|      0|            as.dynLen(newlen);
  315|      0|            return ptr + oldlen;
  316|  85.1k|        }
  317|      0|        const std::size_t oldlen = as.dynLen();
  318|      0|        const std::size_t newlen = oldlen + amt;
  319|      0|        if (newlen > as.store.dyn.cap)
  ------------------
  |  Branch (319:13): [True: 0, False: 0]
  ------------------
  320|      0|        {
  321|      0|            const std::size_t newcap = newlen + (newlen >> 1);
  322|      0|            const auto ptr = as.allocate(newcap);
  323|      0|            std::copy(as.store.dyn.ptr, as.store.dyn.ptr + oldlen, ptr);
  324|      0|            as.deallocate(as.store.dyn.ptr, as.store.dyn.cap);
  325|       |
  326|      0|            as.store.dyn.ptr = ptr;
  327|      0|            as.store.dyn.cap = newcap;
  328|      0|        }
  329|      0|        as.dynLen(newlen);
  330|      0|        return as.store.dyn.ptr + oldlen;
  331|  85.1k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE9push_backEc:
  339|  85.1k|    {
  340|  85.1k|        *append(1) = c;
  341|  85.1k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE4dataEv:
  373|  1.38k|    {
  374|  1.38k|        return as.isDyn() ? as.store.dyn.ptr : as.store.inl.ptr;
  ------------------
  |  Branch (374:16): [True: 0, False: 1.38k]
  ------------------
  375|  1.38k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE5beginEv:
  383|  1.38k|    {
  384|  1.38k|        return data();
  385|  1.38k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE4sizeEv:
  288|  1.38k|    {
  289|  1.38k|        return as.isDyn() ? as.dynLen() : as.inlLen();
  ------------------
  |  Branch (289:16): [True: 0, False: 1.38k]
  ------------------
  290|  1.38k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEEcvNS1_17basic_string_viewIcNS1_11char_traitsIcEEEEEv:
  293|  1.38k|    {
  294|  1.38k|        return std::basic_string_view<CharT>(begin(), size());
  295|  1.38k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEEC2Ev:
  235|  1.38k|    constexpr BasicStrBuf() noexcept : as({}) {}
_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEEC2EOS4_:
  131|  1.38k|    constexpr StrBufAS(Allocator&& a) noexcept : Allocator(std::move(a))
  132|  1.38k|    {
  133|  1.38k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (133:13): [Folded, False: 1.38k]
  ------------------
  134|      0|        {
  135|      0|            std::construct_at(&store.dyn);
  136|      0|        }
  137|  1.38k|        zeroInit();
  138|  1.38k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEED2Ev:
  280|  1.38k|    {
  281|  1.38k|        if (as.isDyn())
  ------------------
  |  Branch (281:13): [True: 0, False: 1.38k]
  ------------------
  282|      0|        {
  283|      0|            as.deallocate(as.store.dyn.ptr, as.store.dyn.cap);
  284|      0|        }
  285|  1.38k|    }

_ZN7stdplus9exception10IncompleteC2ERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
   30|  1.44k|    std::system_error(std::make_error_code(std::errc::illegal_byte_sequence),
   31|  1.44k|                      what)
   32|  1.44k|{}

_ZN7stdplus6printsEP8_IO_FILENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEE:
    9|  1.38k|{
   10|  1.38k|    int r = std::fwrite(data.data(), sizeof(char), data.size(), stream);
   11|  1.38k|    if (r < 0)
  ------------------
  |  Branch (11:9): [True: 0, False: 1.38k]
  ------------------
   12|      0|    {
   13|       |        throw std::system_error(errno, std::generic_category());
   14|      0|    }
   15|  1.38k|}

