_ZNK6google4hoth8internal17PayloadUpdateImpl8initiateEv:
   56|  2.22k|{
   57|  2.22k|    sendCommand(PAYLOAD_UPDATE_INITIATE);
  ------------------
  |  |  180|  2.22k|#define PAYLOAD_UPDATE_INITIATE 0
  ------------------
   58|  2.22k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl5eraseEjj:
   61|    787|{
   62|    787|    sendCommand(PAYLOAD_UPDATE_ERASE, offset, size);
  ------------------
  |  |  188|    787|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
   63|    787|}
_ZNK6google4hoth8internal17PayloadUpdateImpl14findDescriptorERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPj:
   67|  2.69k|{
   68|  2.69k|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
   69|       |
   70|  2.69k|    if (*fd < 0)
  ------------------
  |  Branch (70:9): [True: 0, False: 2.69k]
  ------------------
   71|      0|    {
   72|      0|        (void)fd.release();
   73|      0|        throw errnoException(std::format("Failed to open file {}", path));
   74|      0|    }
   75|       |
   76|  2.69k|    auto seekRet = sys->lseek(*fd, 0, SEEK_END);
   77|  2.69k|    size_t fsize = seekRet;
   78|       |
   79|  2.69k|    if (seekRet < 0)
  ------------------
  |  Branch (79:9): [True: 0, False: 2.69k]
  ------------------
   80|      0|    {
   81|      0|        throw errnoException(std::format("Error seeking on file", path));
   82|      0|    }
   83|       |
   84|  2.69k|    uint64_t read_data = 0;
   85|  2.69k|    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.69k|    ssize_t offset = static_cast<ssize_t>(
   90|  2.69k|        (fsize / kImageDescriptorAlignment) * kImageDescriptorAlignment);
   91|  2.69k|    if (offset + sizeof(kDescriptorMagic) > fsize)
  ------------------
  |  Branch (91:9): [True: 447, False: 2.24k]
  ------------------
   92|    447|    {
   93|    447|        offset -= kImageDescriptorAlignment;
   94|    447|    }
   95|       |
   96|  3.74k|    for (; offset >= 0; offset -= kImageDescriptorAlignment)
  ------------------
  |  Branch (96:12): [True: 2.87k, False: 865]
  ------------------
   97|  2.87k|    {
   98|  2.87k|        auto seek = sys->lseek(*fd, offset, SEEK_SET);
   99|  2.87k|        if (seek < 0)
  ------------------
  |  Branch (99:13): [True: 0, False: 2.87k]
  ------------------
  100|      0|        {
  101|      0|            throw errnoException(std::format("Error seeking on file", path));
  102|      0|        }
  103|       |
  104|  2.87k|        auto actualReadSize = sys->read(*fd, &read_data, sizeof(read_data));
  105|       |
  106|  2.87k|        if (actualReadSize < 0)
  ------------------
  |  Branch (106:13): [True: 0, False: 2.87k]
  ------------------
  107|      0|        {
  108|      0|            throw errnoException(
  109|      0|                std::format("Failed to read from file {}", path));
  110|      0|        }
  111|       |
  112|  2.87k|        if (read_data == kDescriptorMagic)
  ------------------
  |  Branch (112:13): [True: 1.83k, False: 1.04k]
  ------------------
  113|  1.83k|        {
  114|  1.83k|            if (desc_offset)
  ------------------
  |  Branch (114:17): [True: 1.83k, False: 0]
  ------------------
  115|  1.83k|            {
  116|  1.83k|                *desc_offset = offset;
  117|  1.83k|                desc_found = true;
  118|  1.83k|                break;
  119|  1.83k|            }
  120|  1.83k|        }
  121|  2.87k|    }
  122|       |
  123|  2.69k|    return desc_found;
  124|  2.69k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl27eraseAndSendStaticWPRegionsERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEj:
  128|  1.83k|{
  129|  1.83k|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
  130|       |
  131|  1.83k|    if (*fd < 0)
  ------------------
  |  Branch (131:9): [True: 0, False: 1.83k]
  ------------------
  132|      0|    {
  133|      0|        (void)fd.release();
  134|      0|        throw errnoException(std::format("Failed to open file {}", path));
  135|      0|    }
  136|       |
  137|  1.83k|    struct image_descriptor descriptor;
  138|       |
  139|  1.83k|    if (sys->lseek(*fd, desc_offset, SEEK_SET) < 0)
  ------------------
  |  Branch (139:9): [True: 0, False: 1.83k]
  ------------------
  140|      0|    {
  141|      0|        throw errnoException(std::format("Error seeking on file", path));
  142|      0|    }
  143|  1.83k|    auto actualReadSize = sys->read(*fd, &descriptor, sizeof(descriptor));
  144|       |
  145|  1.83k|    if (actualReadSize < 0)
  ------------------
  |  Branch (145:9): [True: 0, False: 1.83k]
  ------------------
  146|      0|    {
  147|      0|        throw errnoException(std::format("Failed to read from file {}", path));
  148|      0|    }
  149|       |
  150|  1.83k|    if (descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
  ------------------
  |  |   70|  3.66k|#define DESCRIPTOR_MAGIC 0x5f435344474d495f // "_IMGDSC_"
  ------------------
  |  Branch (150:9): [True: 0, False: 1.83k]
  ------------------
  151|  1.83k|        descriptor.descriptor_offset != desc_offset ||
  ------------------
  |  Branch (151:9): [True: 183, False: 1.64k]
  ------------------
  152|  1.64k|        descriptor.region_count == 0)
  ------------------
  |  Branch (152:9): [True: 98, False: 1.55k]
  ------------------
  153|    281|    {
  154|    281|        throw errnoException(
  155|    281|            std::format("Invalid descriptor at offset {}", path));
  156|    281|    }
  157|       |
  158|  1.55k|    std::vector<struct image_region> image_regions(descriptor.region_count);
  159|       |
  160|  1.55k|    actualReadSize =
  161|  1.55k|        sys->read(*fd, image_regions.data(),
  162|  1.55k|                  sizeof(struct image_region) * descriptor.region_count);
  163|  1.55k|    if (actualReadSize < 0)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.55k]
  ------------------
  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|   112k|    for (uint32_t i = 0; i < descriptor.region_count; i++)
  ------------------
  |  Branch (169:26): [True: 111k, False: 1.23k]
  ------------------
  170|   111k|    {
  171|   111k|        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
  ------------------
  |  |   55|   111k|#define IMAGE_REGION_STATIC                     (1 << 0)
  ------------------
  |  Branch (171:13): [True: 2.27k, False: 109k]
  ------------------
  172|   109k|            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
  ------------------
  |  |   57|   109k|#define IMAGE_REGION_WRITE_PROTECTED            (1 << 2)
  ------------------
  |  Branch (172:13): [True: 793, False: 108k]
  ------------------
  173|  3.06k|        {
  174|  3.06k|            if (image_regions[i].region_size == 0 ||
  ------------------
  |  Branch (174:17): [True: 47, False: 3.01k]
  ------------------
  175|  3.01k|                (image_regions[i].region_size % kSectorSizeBytes) != 0)
  ------------------
  |  Branch (175:17): [True: 267, False: 2.75k]
  ------------------
  176|    314|            {
  177|    314|                throw errnoException(std::format("invalid staging area size"));
  178|    314|            }
  179|  2.75k|            uint32_t regionOffset = image_regions[i].region_offset;
  180|  2.75k|            uint32_t toEraseSize = image_regions[i].region_size;
  181|  25.7M|            while (toEraseSize >= kEraseChunkSizeBytes)
  ------------------
  |  Branch (181:20): [True: 25.6M, False: 2.75k]
  ------------------
  182|  25.6M|            {
  183|  25.6M|                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset,
  ------------------
  |  |  188|  25.6M|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
  184|  25.6M|                            kEraseChunkSizeBytes);
  185|  25.6M|                regionOffset += kEraseChunkSizeBytes;
  186|  25.6M|                toEraseSize -= kEraseChunkSizeBytes;
  187|  25.6M|            }
  188|  2.75k|            if (toEraseSize > 0)
  ------------------
  |  Branch (188:17): [True: 1.96k, False: 791]
  ------------------
  189|  1.96k|            {
  190|  1.96k|                sendCommand(PAYLOAD_UPDATE_ERASE, regionOffset, toEraseSize);
  ------------------
  |  |  188|  1.96k|#define PAYLOAD_UPDATE_ERASE 8
  ------------------
  191|  1.96k|            }
  192|  2.75k|        }
  193|   111k|    }
  194|       |
  195|       |    // Read and send static and WP sections of the payload
  196|  22.9k|    for (uint32_t i = 0; i < descriptor.region_count; i++)
  ------------------
  |  Branch (196:26): [True: 22.6k, False: 264]
  ------------------
  197|  22.6k|    {
  198|  22.6k|        if ((image_regions[i].region_attributes & IMAGE_REGION_STATIC) ||
  ------------------
  |  |   55|  22.6k|#define IMAGE_REGION_STATIC                     (1 << 0)
  ------------------
  |  Branch (198:13): [True: 1.29k, False: 21.3k]
  ------------------
  199|  21.3k|            (image_regions[i].region_attributes & IMAGE_REGION_WRITE_PROTECTED))
  ------------------
  |  |   57|  21.3k|#define IMAGE_REGION_WRITE_PROTECTED            (1 << 2)
  ------------------
  |  Branch (199:13): [True: 468, False: 20.8k]
  ------------------
  200|  1.76k|        {
  201|  1.76k|            uint32_t offset = image_regions[i].region_offset;
  202|  1.76k|            auto regionSize = image_regions[i].region_size;
  203|  1.76k|            size_t readSize = 0;
  204|  1.76k|            std::vector<uint8_t> readBuffer(max_packet_size);
  205|       |
  206|  1.76k|            if (sys->lseek(*fd, offset, SEEK_SET) != offset)
  ------------------
  |  Branch (206:17): [True: 466, False: 1.29k]
  ------------------
  207|    466|            {
  208|    466|                throw errnoException(
  209|    466|                    std::format("Failed to read file size {}", path));
  210|    466|            }
  211|  1.29k|            do
  212|  13.6k|            {
  213|  13.6k|                if (regionSize <= max_packet_size)
  ------------------
  |  Branch (213:21): [True: 867, False: 12.7k]
  ------------------
  214|    867|                {
  215|    867|                    readSize = regionSize;
  216|    867|                }
  217|  12.7k|                else
  218|  12.7k|                {
  219|  12.7k|                    readSize = max_packet_size;
  220|  12.7k|                }
  221|       |
  222|  13.6k|                if (!sys->read(*fd, readBuffer.data(), readSize))
  ------------------
  |  Branch (222:21): [True: 506, False: 13.1k]
  ------------------
  223|    506|                {
  224|    506|                    throw errnoException(
  225|    506|                        std::format("Failed to read from file {}", path));
  226|    506|                }
  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|  13.1k|                trimAndSend(std::span<uint8_t>(readBuffer.data(), readSize),
  231|  13.1k|                            offset);
  232|  13.1k|                offset += readSize;
  233|  13.1k|                regionSize -= readSize;
  234|       |
  235|  13.1k|            } while (regionSize); // actualReadSize will be 0 when EOF is
  ------------------
  |  Branch (235:22): [True: 12.3k, False: 792]
  ------------------
  236|       |                                  // reached, exit loop
  237|  1.29k|        }
  238|  22.6k|    }
  239|  1.23k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl20eraseAndSendStaticWPERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  242|  2.69k|{
  243|  2.69k|    uint32_t desc_offset = 0;
  244|       |
  245|  2.69k|    if (!findDescriptor(path, &desc_offset))
  ------------------
  |  Branch (245:9): [True: 865, False: 1.83k]
  ------------------
  246|    865|    {
  247|    865|        throw errnoException(std::format("No valid descriptor found"));
  248|    865|    }
  249|       |
  250|  1.83k|    eraseAndSendStaticWPRegions(path, desc_offset);
  251|  1.83k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl4readEjNSt3__14spanIhLm18446744073709551615EEE:
  254|  1.69k|{
  255|  1.69k|    std::vector<uint8_t> buf;
  256|  1.69k|    auto rsp = sendCommand(buf, PAYLOAD_UPDATE_READ, offset, data.size());
  ------------------
  |  |  186|  1.69k|#define PAYLOAD_UPDATE_READ 6
  ------------------
  257|  1.69k|    if (rsp.size() != data.size())
  ------------------
  |  Branch (257:9): [True: 1.40k, False: 289]
  ------------------
  258|  1.40k|    {
  259|  1.40k|        stdplus::print(
  260|  1.40k|            stderr,
  261|  1.40k|            "Payload command received a short response from Hoth `{} < {}`\n",
  262|  1.40k|            rsp.size(), data.size());
  263|  1.40k|        throw ResponseFailure();
  264|  1.40k|    }
  265|    289|    memcpy(data.data(), rsp.data(), data.size());
  266|    289|}
_ZNK6google4hoth8internal17PayloadUpdateImpl6verifyEv:
  269|    558|{
  270|    558|    payload_update_packet request = {};
  271|    558|    request.type = PAYLOAD_UPDATE_VERIFY_DESCRIPTOR;
  ------------------
  |  |  191|    558|#define PAYLOAD_UPDATE_VERIFY_DESCRIPTOR 11
  ------------------
  272|    558|    auto buf = hostCmd->sendCommand(
  273|    558|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|    558|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|    558|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  274|    558|        &request, sizeof(request));
  275|    558|    std::span<uint8_t> rsp = buf;
  276|    558|    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|    558|    if (hdr.result == EC_RES_INVALID_PARAM || hdr.result == EC_RES_ERROR)
  ------------------
  |  Branch (280:9): [True: 0, False: 558]
  |  Branch (280:47): [True: 0, False: 558]
  ------------------
  281|      0|    {
  282|      0|        sendCommand(PAYLOAD_UPDATE_VERIFY);
  ------------------
  |  |  184|      0|#define PAYLOAD_UPDATE_VERIFY 4
  ------------------
  283|      0|        return;
  284|      0|    }
  285|    558|    if (hdr.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (285:9): [True: 0, False: 558]
  ------------------
  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|    558|}
_ZNK6google4hoth8internal17PayloadUpdateImpl9getStatusEv:
  294|    752|{
  295|    752|    std::vector<uint8_t> buf;
  296|    752|    std::span<const uint8_t> output =
  297|    752|        sendCommand(buf, PAYLOAD_UPDATE_GET_STATUS);
  ------------------
  |  |  187|    752|#define PAYLOAD_UPDATE_GET_STATUS 7
  ------------------
  298|       |
  299|    752|    return stdplus::raw::copyFrom<payload_update_status>(output);
  300|    752|}
_ZNK6google4hoth8internal17PayloadUpdateImpl8activateENS1_4SideENS1_11PersistenceE:
  303|    501|{
  304|    501|    ActivateRequest request;
  305|    501|    request.header.offset = 0;
  306|    501|    request.header.len = sizeof(request.activate);
  307|    501|    request.header.type = PAYLOAD_UPDATE_ACTIVATE;
  ------------------
  |  |  185|    501|#define PAYLOAD_UPDATE_ACTIVATE 5
  ------------------
  308|    501|    request.activate.half = static_cast<uint8_t>(side);
  309|    501|    request.activate.make_persistent = static_cast<uint8_t>(persistence);
  310|       |
  311|    501|    sendCommand(
  312|    501|        {reinterpret_cast<const uint8_t*>(&request), sizeof(ActivateRequest)});
  313|    501|}
_ZNK6google4hoth8internal17PayloadUpdateImpl7confirmE29payload_update_confirm_optionjm:
  318|    722|{
  319|    722|    ConfirmRequest request;
  320|    722|    request.header.offset = 0;
  321|    722|    request.header.len = sizeof(request.confirm);
  322|    722|    request.header.type = PAYLOAD_UPDATE_CONFIRM;
  ------------------
  |  |  190|    722|#define PAYLOAD_UPDATE_CONFIRM 10
  ------------------
  323|    722|    request.confirm.option = option;
  324|    722|    request.confirm.timeout_value = boost::endian::native_to_little(timeout);
  325|    722|    request.confirm.confirmation_cookie =
  326|    722|        boost::endian::native_to_little(confirmation_cookie);
  327|       |
  328|    722|    std::vector<uint8_t> buf = hostCmd->sendCommand(
  329|    722|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|    722|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|    722|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  330|    722|        &request, sizeof(request));
  331|       |    // Extract the response header out when returning the span
  332|    722|    std::span<const uint8_t> output = buf;
  333|    722|    auto rsp = stdplus::raw::extract<RspHeader>(output);
  334|    722|    if (rsp.result == HOTH_PAYLOAD_UPDATE_CONFIRM_NO_PENDING_PAYLOAD)
  ------------------
  |  Branch (334:9): [True: 0, False: 722]
  ------------------
  335|      0|    {
  336|      0|        return std::nullopt;
  337|      0|    }
  338|       |
  339|    722|    if (rsp.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (339:9): [True: 0, False: 722]
  ------------------
  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|    722|    return stdplus::raw::copyFrom<payload_update_confirm_response>(output);
  349|    722|}
_ZNK6google4hoth8internal17PayloadUpdateImpl4sendERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  382|    870|{
  383|    870|    Fd fd(sys->open(path.c_str(), O_RDONLY), sys);
  384|       |
  385|    870|    if (*fd < 0)
  ------------------
  |  Branch (385:9): [True: 0, False: 870]
  ------------------
  386|      0|    {
  387|      0|        (void)fd.release();
  388|      0|        throw errnoException(std::format("Failed to open file {}", path));
  389|      0|    }
  390|       |
  391|    870|    std::array<uint8_t, max_packet_size> readBuffer;
  392|    870|    uint32_t offset = 0;
  393|    870|    ssize_t actualReadSize = 0;
  394|       |    // Read and send payload until we reach EOF of the given file
  395|    870|    do
  396|  7.17k|    {
  397|  7.17k|        actualReadSize = sys->read(*fd, readBuffer.data(), max_packet_size);
  398|       |
  399|  7.17k|        if (actualReadSize < 0)
  ------------------
  |  Branch (399:13): [True: 0, False: 7.17k]
  ------------------
  400|      0|        {
  401|      0|            throw errnoException(
  402|      0|                std::format("Failed to read from file {}", path));
  403|      0|        }
  404|  7.17k|        if (actualReadSize > 0)
  ------------------
  |  Branch (404:13): [True: 6.30k, False: 870]
  ------------------
  405|  6.30k|        {
  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|  6.30k|            trimAndSend(std::span<uint8_t>(readBuffer.data(), actualReadSize),
  409|  6.30k|                        offset);
  410|  6.30k|            offset += actualReadSize;
  411|  6.30k|        }
  412|       |        // actualReadSize will be 0 when EOF is reached, exit loop
  413|  7.17k|    } while (actualReadSize);
  ------------------
  |  Branch (413:14): [True: 6.30k, False: 870]
  ------------------
  414|    870|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11trimAndSendENSt3__14spanIKhLm18446744073709551615EEEj:
  425|  19.4k|{
  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|  19.4k|    std::array<uint8_t, sizeof(payload_update_packet) + max_packet_size> buffer;
  431|  19.4k|    payload_update_packet* request =
  432|  19.4k|        reinterpret_cast<payload_update_packet*>(buffer.data());
  433|  19.4k|    uint8_t* request_payload = &buffer[sizeof(payload_update_packet)];
  434|       |
  435|  19.4k|    const size_t dataSize = data.size();
  436|  19.4k|    if (dataSize > max_packet_size)
  ------------------
  |  Branch (436:9): [True: 0, False: 19.4k]
  ------------------
  437|      0|    {
  438|      0|        throw errnoException(
  439|      0|            "data to send cannot be bigger than max_packet_size");
  440|      0|    }
  441|  19.4k|    size_t localOffset = SizeToSkip(data);
  442|  19.4k|    if (localOffset >= dataSize)
  ------------------
  |  Branch (442:9): [True: 492, False: 18.9k]
  ------------------
  443|    492|    {
  444|       |        // No need to send any payload
  445|    492|        return;
  446|    492|    }
  447|  18.9k|    size_t max_size_to_send = std::min(dataSize - localOffset, max_packet_size);
  448|  18.9k|    size_t size_to_send =
  449|  18.9k|        SizeToSend(data.subspan(localOffset, max_size_to_send));
  450|       |
  451|       |    // Construct and send payload
  452|  18.9k|    request->offset = globalOffset + localOffset;
  453|  18.9k|    request->len = size_to_send;
  454|  18.9k|    request->type = PAYLOAD_UPDATE_CONTINUE;
  ------------------
  |  |  181|  18.9k|#define PAYLOAD_UPDATE_CONTINUE 1
  ------------------
  455|  18.9k|    memcpy(request_payload, &data[localOffset], size_to_send);
  456|  18.9k|    sendCommand({buffer.data(), sizeof(*request) + size_to_send});
  457|  18.9k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandEhjj:
  461|  25.7M|{
  462|  25.7M|    std::vector<uint8_t> buf;
  463|  25.7M|    (void)sendCommand(buf, command, offset, len);
  464|  25.7M|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandENSt3__14spanIKhLm18446744073709551615EEE:
  467|  19.4k|{
  468|  19.4k|    std::vector<uint8_t> buf;
  469|  19.4k|    (void)sendCommand(buf, request);
  470|  19.4k|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandERNSt3__16vectorIhNS3_9allocatorIhEEEEhjj:
  475|  25.7M|{
  476|       |    // For most basic commands, request offset and length are zero
  477|  25.7M|    payload_update_packet request;
  478|  25.7M|    request.offset = offset;
  479|  25.7M|    request.len = len;
  480|  25.7M|    request.type = command;
  481|  25.7M|    return sendCommand(buf, {reinterpret_cast<const uint8_t*>(&request),
  482|  25.7M|                             sizeof(payload_update_packet)});
  483|  25.7M|}
_ZNK6google4hoth8internal17PayloadUpdateImpl11sendCommandERNSt3__16vectorIhNS3_9allocatorIhEEEENS3_4spanIKhLm18446744073709551615EEE:
  487|  25.7M|{
  488|  25.7M|    buf = hostCmd->sendCommand(
  489|  25.7M|        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |   58|  25.7M|#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00
  ------------------
                      EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PAYLOAD_UPDATE, 0,
  ------------------
  |  |  146|  25.7M|#define EC_PRV_CMD_HOTH_PAYLOAD_UPDATE 0x0005
  ------------------
  490|  25.7M|        request.data(), request.size());
  491|       |    // Extract the response header out when returning the span
  492|  25.7M|    std::span<const uint8_t> output = buf;
  493|  25.7M|    auto rsp = stdplus::raw::extract<RspHeader>(output);
  494|  25.7M|    if (rsp.result != EC_RES_SUCCESS)
  ------------------
  |  Branch (494:9): [True: 0, False: 25.7M]
  ------------------
  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|  25.7M|    return output;
  503|  25.7M|}
payload_update.cpp:_ZN6google4hoth8internal12_GLOBAL__N_110SizeToSkipENSt3__14spanIKhLm18446744073709551615EEE:
  355|  19.4k|{
  356|  19.4k|    size_t i;
  357|   533k|    for (i = 0; i < data.size(); i++)
  ------------------
  |  Branch (357:17): [True: 533k, False: 492]
  ------------------
  358|   533k|    {
  359|   533k|        if (data[i] != 0xff)
  ------------------
  |  Branch (359:13): [True: 18.9k, False: 514k]
  ------------------
  360|  18.9k|        {
  361|  18.9k|            break;
  362|  18.9k|        }
  363|   533k|    }
  364|  19.4k|    return i;
  365|  19.4k|}
payload_update.cpp:_ZN6google4hoth8internal12_GLOBAL__N_110SizeToSendENSt3__14spanIKhLm18446744073709551615EEE:
  368|  18.9k|{
  369|  18.9k|    size_t i;
  370|   242k|    for (i = data.size(); i > 0; i--)
  ------------------
  |  Branch (370:27): [True: 242k, False: 0]
  ------------------
  371|   242k|    {
  372|   242k|        if (data[i - 1] != 0xff)
  ------------------
  |  Branch (372:13): [True: 18.9k, False: 223k]
  ------------------
  373|  18.9k|        {
  374|  18.9k|            break;
  375|  18.9k|        }
  376|   242k|    }
  377|  18.9k|    return i;
  378|  18.9k|}

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

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

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.8k|    while (provider.remaining_bytes() > 0 && action_count < 20) {
  ------------------
  |  Branch (131:12): [True: 11.1k, False: 692]
  |  Branch (131:46): [True: 10.8k, False: 325]
  ------------------
  132|  10.8k|        action_count++;
  133|  10.8k|        uint8_t action = provider.ConsumeIntegralInRange<uint8_t>(0, 8);
  134|  10.8k|        try {
  135|  10.8k|            switch (action) {
  ------------------
  |  Branch (135:21): [True: 10.8k, False: 0]
  ------------------
  136|  2.22k|                case 0: {
  ------------------
  |  Branch (136:17): [True: 2.22k, False: 8.58k]
  ------------------
  137|  2.22k|                    payload_update.initiate();
  138|  2.22k|                    break;
  139|      0|                }
  140|    787|                case 1: {
  ------------------
  |  Branch (140:17): [True: 787, False: 10.0k]
  ------------------
  141|    787|                    uint32_t offset = provider.ConsumeIntegral<uint32_t>();
  142|    787|                    uint32_t size = provider.ConsumeIntegral<uint32_t>();
  143|    787|                    payload_update.erase(offset, size);
  144|    787|                    break;
  145|      0|                }
  146|  2.69k|                case 2: {
  ------------------
  |  Branch (146:17): [True: 2.69k, False: 8.11k]
  ------------------
  147|  2.69k|                    payload_update.eraseAndSendStaticWP("/tmp/fuzz_file");
  148|  2.69k|                    break;
  149|      0|                }
  150|  1.69k|                case 3: {
  ------------------
  |  Branch (150:17): [True: 1.69k, False: 9.11k]
  ------------------
  151|  1.69k|                    uint32_t offset = provider.ConsumeIntegral<uint32_t>();
  152|  1.69k|                    uint32_t read_len = provider.ConsumeIntegralInRange<uint32_t>(0, 1024);
  153|  1.69k|                    std::vector<uint8_t> read_buf(read_len);
  154|  1.69k|                    payload_update.read(offset, read_buf);
  155|  1.69k|                    break;
  156|      0|                }
  157|    558|                case 4: {
  ------------------
  |  Branch (157:17): [True: 558, False: 10.2k]
  ------------------
  158|    558|                    payload_update.verify();
  159|    558|                    break;
  160|      0|                }
  161|    752|                case 5: {
  ------------------
  |  Branch (161:17): [True: 752, False: 10.0k]
  ------------------
  162|    752|                    payload_update.getStatus();
  163|    752|                    break;
  164|      0|                }
  165|    501|                case 6: {
  ------------------
  |  Branch (165:17): [True: 501, False: 10.3k]
  ------------------
  166|    501|                    auto side = provider.PickValueInArray({google::hoth::internal::Side::A, google::hoth::internal::Side::B});
  167|    501|                    auto persistence = provider.PickValueInArray({google::hoth::internal::Persistence::kNonPersistent, google::hoth::internal::Persistence::kPersistent});
  168|    501|                    payload_update.activate(side, persistence);
  169|    501|                    break;
  170|      0|                }
  171|    870|                case 7: {
  ------------------
  |  Branch (171:17): [True: 870, False: 9.94k]
  ------------------
  172|    870|                    payload_update.send("/tmp/fuzz_file");
  173|    870|                    break;
  174|      0|                }
  175|    722|                case 8: {
  ------------------
  |  Branch (175:17): [True: 722, False: 10.0k]
  ------------------
  176|    722|                    auto option = provider.PickValueInArray({
  177|    722|                        payload_update_confirm_option::Enable,
  178|    722|                        payload_update_confirm_option::Enable_with_timeout,
  179|    722|                        payload_update_confirm_option::Disable,
  180|    722|                        payload_update_confirm_option::Confirm,
  181|    722|                        payload_update_confirm_option::Get_timeout_values
  182|    722|                    });
  183|    722|                    uint32_t timeout = provider.ConsumeIntegral<uint32_t>();
  184|    722|                    uint64_t cookie = provider.ConsumeIntegral<uint64_t>();
  185|    722|                    payload_update.confirm(option, timeout, cookie);
  186|    722|                    break;
  187|      0|                }
  188|  10.8k|            }
  189|  10.8k|        } catch (...) {
  190|       |            // Catch expected exceptions (e.g. from mock filesystem or D-Bus response failures)
  191|  5.31k|        }
  192|  10.8k|    }
  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.39k|    int open(const char* pathname, int flags) const override {
   40|  5.39k|        return 42; // dummy fd
   41|  5.39k|    }
_ZNK9FuzzerSys5closeEi:
   43|  5.39k|    int close(int fd) const override {
   44|  5.39k|        return 0;
   45|  5.39k|    }
_ZNK9FuzzerSys5lseekEili:
   47|  9.16k|    off_t lseek(int fd, off_t offset, int whence) const override {
   48|  9.16k|        if (whence == SEEK_SET) {
  ------------------
  |  Branch (48:13): [True: 6.47k, False: 2.69k]
  ------------------
   49|  6.47k|            if (offset < 0 || static_cast<size_t>(offset) > size_) return -1;
  ------------------
  |  Branch (49:17): [True: 0, False: 6.47k]
  |  Branch (49:31): [True: 466, False: 6.00k]
  ------------------
   50|  6.00k|            offset_ = offset;
   51|  6.00k|        } else if (whence == SEEK_END) {
  ------------------
  |  Branch (51:20): [True: 2.69k, False: 0]
  ------------------
   52|  2.69k|            offset_ = size_;
   53|  2.69k|        } 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.70k|        return offset_;
   58|  9.16k|    }
_ZNK9FuzzerSys4readEiPvm:
   60|  27.0k|    ssize_t read(int fd, void* buf, size_t count) const override {
   61|  27.0k|        if (offset_ >= size_) return 0;
  ------------------
  |  Branch (61:13): [True: 1.44k, False: 25.6k]
  ------------------
   62|  25.6k|        size_t to_read = std::min(count, size_ - offset_);
   63|  25.6k|        std::memcpy(buf, data_ + offset_, to_read);
   64|  25.6k|        offset_ += to_read;
   65|  25.6k|        return to_read;
   66|  27.0k|    }
_ZN17FuzzerHostCommand11sendCommandEthPKvm:
   91|  25.7M|    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|  25.7M|        std::vector<uint8_t> rsp(sizeof(google::hoth::internal::RspHeader), 0);
   94|  25.7M|        auto* hdr = reinterpret_cast<google::hoth::internal::RspHeader*>(rsp.data());
   95|  25.7M|        hdr->result = google::hoth::internal::EC_RES_SUCCESS;
   96|  25.7M|        return rsp;
   97|  25.7M|    }

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

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

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

_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE6inlLenEh:
  100|  88.0k|    {
  101|  88.0k|        store.inl.len = len;
  102|  88.0k|    }
_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE8zeroInitEv:
  118|  1.40k|    {
  119|  1.40k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (119:13): [Folded, False: 1.40k]
  ------------------
  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.40k|        else
  126|  1.40k|        {
  127|  1.40k|            inlLen(0);
  128|  1.40k|        }
  129|  1.40k|    }
_ZNK7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE5isDynEv:
   76|  90.8k|    {
   77|  90.8k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (77:13): [Folded, False: 90.8k]
  ------------------
   78|      0|        {
   79|      0|            return true;
   80|      0|        }
   81|  90.8k|        return store.inl.len & inl_mask;
   82|  90.8k|    }
_ZNK7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEE6inlLenEv:
   95|  88.0k|    {
   96|  88.0k|        return store.inl.len;
   97|  88.0k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE6appendEm:
  298|  86.6k|    {
  299|  86.6k|        if (!as.isDyn())
  ------------------
  |  Branch (299:13): [True: 86.6k, False: 0]
  ------------------
  300|  86.6k|        {
  301|  86.6k|            const std::size_t oldlen = as.inlLen();
  302|  86.6k|            const std::size_t newlen = oldlen + amt;
  303|  86.6k|            if (newlen <= as.buf_len)
  ------------------
  |  Branch (303:17): [True: 86.6k, False: 0]
  ------------------
  304|  86.6k|            {
  305|  86.6k|                as.inlLen(newlen);
  306|  86.6k|                return as.store.inl.ptr + oldlen;
  307|  86.6k|            }
  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|  86.6k|        }
  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|  86.6k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE9push_backEc:
  339|  86.6k|    {
  340|  86.6k|        *append(1) = c;
  341|  86.6k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE4dataEv:
  373|  1.40k|    {
  374|  1.40k|        return as.isDyn() ? as.store.dyn.ptr : as.store.inl.ptr;
  ------------------
  |  Branch (374:16): [True: 0, False: 1.40k]
  ------------------
  375|  1.40k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE5beginEv:
  383|  1.40k|    {
  384|  1.40k|        return data();
  385|  1.40k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEE4sizeEv:
  288|  1.40k|    {
  289|  1.40k|        return as.isDyn() ? as.dynLen() : as.inlLen();
  ------------------
  |  Branch (289:16): [True: 0, False: 1.40k]
  ------------------
  290|  1.40k|    }
_ZNK7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEEcvNS1_17basic_string_viewIcNS1_11char_traitsIcEEEEEv:
  293|  1.40k|    {
  294|  1.40k|        return std::basic_string_view<CharT>(begin(), size());
  295|  1.40k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEEC2Ev:
  235|  1.40k|    constexpr BasicStrBuf() noexcept : as({}) {}
_ZN7stdplus6detail8StrBufASIcLm128ENSt3__19allocatorIcEEEC2EOS4_:
  131|  1.40k|    constexpr StrBufAS(Allocator&& a) noexcept : Allocator(std::move(a))
  132|  1.40k|    {
  133|  1.40k|        if (std::is_constant_evaluated())
  ------------------
  |  Branch (133:13): [Folded, False: 1.40k]
  ------------------
  134|      0|        {
  135|      0|            std::construct_at(&store.dyn);
  136|      0|        }
  137|  1.40k|        zeroInit();
  138|  1.40k|    }
_ZN7stdplus11BasicStrBufIcLm128ENSt3__19allocatorIcEEED2Ev:
  280|  1.40k|    {
  281|  1.40k|        if (as.isDyn())
  ------------------
  |  Branch (281:13): [True: 0, False: 1.40k]
  ------------------
  282|      0|        {
  283|      0|            as.deallocate(as.store.dyn.ptr, as.store.dyn.cap);
  284|      0|        }
  285|  1.40k|    }

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

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

