Skip to content

MemCopy

Description

Copy memory from source to destination. A zero byte count returns dst without reading either pointer.

Parameters

Name Direction Description
dst out Destination memory region.
src in Source memory region.
n in Number of bytes to copy.

Success

Returns destination pointer.

Failure

Aborts via LOG_FATAL when n > 0 and either dst or src is NULL. Behaviour is undefined when the regions overlap; use MemMove for that case.

Usage example (Cross-references)

Usage examples (Cross-references)
    
    __attribute__((used)) void *memcpy(void *dst, const void *src, freestanding_size_t n) {
        MemCopy(dst, src, (size)n);
        return dst;
    }
    }
    
    void *MemCopy(void *dst, const void *src, size n) {
        if (n == 0) {
            return dst;
                }
                char *data = StrBegin(&flagbuf);
                MemCopy(data, tok, n);
                data[n] = '\0';
                StrResize(&flagbuf, (size)n);
                ok = false;
            } else if (StrLen(&tmp)) {
                MemCopy(StrBegin(o) + offset, StrBegin(&tmp), StrLen(&tmp));
            }
        }
                StrInitStack(spec_buf, 32) {
                    char *data = StrBegin(&spec_buf);
                    MemCopy(data, start, spec_len);
                    data[spec_len] = '\0';
                    StrResize(&spec_buf, (size)spec_len);
                ok = false;
            } else if (StrLen(&tmp)) {
                MemCopy(BufData(out) + offset, StrBegin(&tmp), StrLen(&tmp));
            }
        }
        if (fmt_info->flags & FMT_FLAG_CHAR) {
            u64 bits;
            MemCopy(&bits, v, sizeof(bits));
            return write_int_as_chars(o, fmt_info->flags, bits, 8);
        }
        if (fmt_info->flags & FMT_FLAG_CHAR) {
            u32 bits;
            MemCopy(&bits, v, sizeof(bits));
            return write_int_as_chars(o, fmt_info->flags, bits, 4);
        }
        }
    
        MemCopy(new_str, src, len);
        new_str[len] = '\0';
        return new_str;
        }
    
        MemCopy(out->data, cstr, len);
        out->data[len] = 0;
        out->length    = len;
                inserted_count++;
            } else {
                MemCopy(vec_ptr_at(vec, idx + i, item_size), item_data + i * item_size, item_size);
            }
        }
                inserted_count++;
            } else {
                MemCopy(vec_ptr_at(vec, idx + i, item_size), item_data + i * item_size, item_size);
            }
        }
        // bytes live for both paths and lets the slide be a single MemMove.
        if (removed_data) {
            MemCopy(removed_data, vec_ptr_at(vec, start, item_size), count * item_size);
        } else {
            if (vec->copy_deinit) {
    
        if (removed_data) {
            MemCopy(removed_data, vec_ptr_at(vec, start, item_size), count * item_size);
        } else {
            if (vec->copy_deinit) {
            }
        } else {
            MemCopy(dst_key, key, key_size);
        }
            }
        } else {
            MemCopy(dst_val, value, value_size);
        }
        }
    
        MemCopy(map_entry_ptr(map, entry_size, insert_idx), entry, entry_size);
        map->states[insert_idx]  = MAP_SLOT_OCCUPIED;
        map->length             += 1;
        value_ptr = map_get_value_ptr(map, key, entry_size, key_offset, key_size, value_offset, hash_offset);
        if (value_ptr) {
            MemCopy(out_value, value_ptr, value_size);
        } else {
            MemCopy(out_value, default_value, value_size);
            MemCopy(out_value, value_ptr, value_size);
        } else {
            MemCopy(out_value, default_value, value_size);
        }
    
        if (map->value_copy_init) {
            MemCopy(dst_value, temp_value, value_size);
            AllocatorFree(map->allocator, temp_value);
        } else {
            AllocatorFree(map->allocator, temp_value);
        } else {
            MemCopy(dst_value, value, value_size);
        }
        }
    
        MemCopy(dst, src, item_size);
        return true;
    }
        if (k == 8u) {
            // Whole limb in bounds: one little-endian load instead of a byte loop.
            MemCopy(&v, data + off, 8u);
            v = FROM_LITTLE_ENDIAN8(v);
        } else {
            // Whole limb in bounds: one little-endian store instead of a byte loop.
            u64 le = TO_LITTLE_ENDIAN8(value);
            MemCopy(data + off, &le, 8u);
        } else {
            for (u64 j = 0; j < k; j++) {
            }
        } else {
            MemCopy(new_node->data, item_data, item_size);
        }
            GenericListNode *node = node_at_list(list, item_size, start);
            for (u64 c = 0; (c < count) && node; c++) {
                MemCopy((u8 *)removed_data + c * item_size, node->data, item_size);
    
                MemSet(node->data, 0, item_size);
        node = list->head;
        for (index = 0; node && index < item_count; index++) {
            MemCopy((u8 *)data + index * item_size, node->data, item_size);
            node = node->next;
        }
        node = list->head;
        for (index = 0; node && index < item_count; index++) {
            MemCopy(node->data, (u8 *)data + index * item_size, item_size);
            node = node->next;
        }
            u64 rem    = bv->length & 7u;
    
            MemCopy(out->data, bv->data, nbytes);
            if (rem != 0u) {
                out->data[nbytes - 1u] &= (u8)((1u << rem) - 1u);
            u64 word = 0;
    
            MemCopy(&word, bitvec->data + k, 8u);
            count += bitvec_popcount64(word);
        }
            return NULL;
        }
        MemCopy(fresh, ptr, old_padded < new_size ? old_padded : new_size);
    #if FEATURE_ALLOC_STATS
        // The user is abandoning the old `ptr` in favour of `fresh`. The
            entry.requested_size = live_rec->requested_size;
            entry.alloc_trace_n  = live_rec->alloc_trace_n;
            MemCopy(entry.alloc_trace, live_rec->alloc_trace, (size)live_rec->alloc_trace_n * sizeof(StackFrame));
            entry.free_trace_n = 0;
            if (self->config.capture_traces && self->config.trace_depth > 0) {
            return NULL;
        size copy = old_requested < new_size ? old_requested : new_size;
        MemCopy(fresh, ptr, copy);
        debug_allocator_deallocate(self, ptr);
        return fresh;
        }
        if (*arr_p) {
            MemCopy(new_table, *arr_p, (size)*len_p * sizeof(PageEntry));
            os_page_unmap(&page->base, *arr_p, *bytes_p);
        }
        }
        size copy_bytes = old_rounded < new_rounded ? old_rounded : new_rounded;
        MemCopy(fresh, ptr, copy_bytes);
        (void)page_allocator_deallocate(self, ptr);
        return fresh;
    
        if (slab->slabs && old_cap) {
            MemCopy(new_slabs, slab->slabs, (size)old_cap * sizeof(void *));
            MemCopy(new_bitmaps, slab->bitmaps, (size)old_cap * (size)slab->bitmap_words_per_slab * sizeof(u64));
            os_page_unmap(&slab->base, slab->slabs, os_page_round_up((size)old_cap * sizeof(void *)));
        if (slab->slabs && old_cap) {
            MemCopy(new_slabs, slab->slabs, (size)old_cap * sizeof(void *));
            MemCopy(new_bitmaps, slab->bitmaps, (size)old_cap * (size)slab->bitmap_words_per_slab * sizeof(u64));
            os_page_unmap(&slab->base, slab->slabs, os_page_round_up((size)old_cap * sizeof(void *)));
            os_page_unmap(
            return false;
        if (*arr && len) {
            MemCopy(fresh, *arr, (size)len * sizeof(HeapPageXL));
        }
        if (*arr) {
            return false;
        if (heap->recycle && heap->recycle_len) {
            MemCopy(fresh, heap->recycle, (size)heap->recycle_len * sizeof(void *));
        }
        if (heap->recycle) {
                return NULL;
            size copy_bytes = cur < new_size ? cur : new_size;
            MemCopy(fresh, ptr, copy_bytes);
            (void)heap_allocator_deallocate(self, ptr);
            return fresh;
            }
            char *data = StrBegin(&search_path);
            MemCopy(data, path, path_len);
            data[path_len]     = '\\';
            data[path_len + 1] = '*';
        StrInitStack(buf, 4096) {
            char *data = StrBegin(&buf);
            MemCopy(data, path, n);
            data[n] = 0;
            StrResize(&buf, n);
        sa->sin_family         = AF_INET;
        sa->sin_port           = FROM_BIG_ENDIAN2(port);
        MemCopy(&sa->sin_addr.s_addr, ip, 4);
        a.length = (u32)sizeof(struct sockaddr_in);
        a.family = SOCKET_FAMILY_INET;
        sa->sin6_family         = AF_INET6;
        sa->sin6_port           = FROM_BIG_ENDIAN2(port);
        MemCopy(sa->sin6_addr.s6_addr, ip, 16);
        a.length = (u32)sizeof(struct sockaddr_in6);
        a.family = SOCKET_FAMILY_INET6;
                ascii_lower((u8 *)StrBegin(&e.name), StrLen(&e.name));
                if (got_v4) {
                    MemCopy(e.ip, v4, 4);
                    e.is_ipv6 = false;
                } else {
                    e.is_ipv6 = false;
                } else {
                    MemCopy(e.ip, v6, 16);
                    e.is_ipv6 = true;
                }
                return false;
            }
            MemCopy(host_out, spec + 1, host_len);
            host_out[host_len] = '\0';
            *port_out          = close + 2;
            return false;
        }
        MemCopy(host_out, spec, host_len);
        host_out[host_len] = '\0';
        *port_out          = colon + 1;
            len = (u32)SOCKET_ADDR_MAX_SIZE;
        }
        MemCopy(out->raw, sa, (size)len);
        out->length = len;
        out->family = af_to_socket_family((i32)sa->sa_family);
                sa->sin_family = AF_INET;
                sa->sin_port   = FROM_BIG_ENDIAN2(port);
                MemCopy(&sa->sin_addr.s_addr, v4, 4);
                out->length = (u32)sizeof(struct sockaddr_in);
                out->family = SOCKET_FAMILY_INET;
                // Windows' IN6_ADDR defines `#define s6_addr u.Byte`, so this
                // works the same on both platforms.
                MemCopy(sa->sin6_addr.s6_addr, v6, 16);
                out->length = (u32)sizeof(struct sockaddr_in6);
                out->family = SOCKET_FAMILY_INET6;
            // 8-byte name: bytes, not a numeric, so copy + advance manually.
            // IterRemainingLength >= 40 bound above proves 8 bytes are live.
            MemCopy(s.name, IterDataAt(&c, IterIndex(&c)), 8);
            s.name[8] = '\0';
            IterMustMove(&c, 8);
                continue;
            // Same proof: 16 bytes are live.
            MemCopy(cv->guid, IterDataAt(&cv_cur, IterIndex(&cv_cur)), 16);
            IterMustMove(&cv_cur, 16);
            if (!BufReadU32LE(&cv_cur, &cv->age))
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return PeOpenFromMemory(out, &copy);
            if (chunk > remaining)
                chunk = remaining;
            MemCopy(dest, src + inoff, chunk);
            dest      += chunk;
            offset    += chunk;
                want = num_dir_bytes - done;
            }
            MemCopy(self->stream_dir + done, src, want);
        }
        return true;
                break;
            }
            MemCopy(self->info.guid, VecBegin(&buf) + 12, 16);
            ok = true;
        }
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return PdbOpenFromMemory(out, &copy);
                return false;
            }
            MemCopy(StrEnd(&out->raw), bytes, len);
            StrResize(&out->raw, len);
        }
        // plus the 16-byte segname plus the body.
        IterMustMove(cmd, 8); // skip cmd(4) + cmdsize(4) prefix
        MemCopy(seg.name, IterDataAt(cmd, IterIndex(cmd)), 16);
        seg.name[16] = '\0';
        IterMustMove(cmd, 16);
            MachoSection sec;
            MemSet(&sec, 0, sizeof(sec));
            MemCopy(sec.section, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
            sec.section[16] = '\0';
            IterMustMove(&sec_it, 16);
            sec.section[16] = '\0';
            IterMustMove(&sec_it, 16);
            MemCopy(sec.segment, IterDataAt(&sec_it, IterIndex(&sec_it)), 16);
            sec.segment[16] = '\0';
            IterMustMove(&sec_it, 16);
        // proves the 8-byte prefix plus the 16-byte UUID payload fit.
        IterMustMove(cmd, 8); // skip cmd + cmdsize prefix
        MemCopy(ctx->out->uuid, IterDataAt(cmd, IterIndex(cmd)), 16);
        ctx->out->has_uuid = true;
        return true;
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return MachoOpenFromMemory(out, &copy);
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        // Hand `&copy` to the L-form -- it consumes the local and zeros
        Buf  in = BufInit(alloc_base);
        bool ok = BufResize(&in, 5);
        MemCopy(BufData(&in), "12345", 5);
    
        i64 wrote = FileWriteAndClose(&path, &in);
        ok = ok && (n > 0);
        if (ok)
            MemCopy(snapshot, rec->alloc_trace, (size)n * sizeof(StackFrame));
    
        AllocatorFree(adbg, p);
            if (!dst->name)
                return false;
            MemCopy(dst->name, src->name, name_len + 1);
        } else {
            dst->name = NULL;
                return false;
            }
            MemCopy(dst->values, src->values, src->num_values * sizeof(int));
        } else {
            dst->values = NULL;
            item.name     = (char *)fixture_malloc(name_len + 1);
            if (item.name) {
                MemCopy(item.name, name, name_len);
                item.name[name_len] = '\0';
            }
            item.values = (int *)fixture_malloc(num_values * sizeof(int));
            if (item.values) {
                MemCopy(item.values, values, num_values * sizeof(int));
                item.num_values = num_values;
            }
        WriteFmt("Testing fast-insert preserves displaced tail (aligned_size)\n");
    
        ElemVec vec = VecInit(&alloc); // no copy hooks: plain MemCopy path
    
        Elem orig[4];
        WriteFmt("Testing fast-insert displacement move stays in bounds (over-copy)\n");
    
        ElemVec vec = VecInit(&alloc); // no copy hooks: plain MemCopy path
    
        // N live originals; inserting N at idx 0 makes displaced == min(N, N) == N,
        f32 v;
        u32 bits = 0x42434445u;
        MemCopy(&v, &bits, sizeof(v));
    
        StrAppendFmt(&output, "{c}", v);
        u64 bits = ((u64)'A' << 56) | ((u64)'B' << 48) | ((u64)'C' << 40) | ((u64)'D' << 32) | ((u64)'E' << 24) |
                   ((u64)'F' << 16) | ((u64)'G' << 8) | (u64)'H';
        MemCopy(&v, &bits, sizeof(v));
        StrAppendFmt(&out, "{c}", v);
        bool ok = (ZstrCompare(StrBegin(&out), "ABCDEFGH") == 0);
            StrIter *iter1       = VecPtrAt(&iters, 0);
            char     buffer1[10] = {0};
            MemCopy(buffer1, iter1->data, StrIterLength(iter1));
            result = result && (ZstrCompare(buffer1, "Hello") == 0);
            StrIter *iter2       = VecPtrAt(&iters, 1);
            char     buffer2[10] = {0};
            MemCopy(buffer2, iter2->data, StrIterLength(iter2));
            result = result && (ZstrCompare(buffer2, "World") == 0);
            StrIter *iter3       = VecPtrAt(&iters, 2);
            char     buffer3[10] = {0};
            MemCopy(buffer3, iter3->data, StrIterLength(iter3));
            result = result && (ZstrCompare(buffer3, "Test") == 0);
        }
        // Test very long strings
        char long_number[100];
        MemCopy(long_number, "12345678901234567890123456789012345678901234567890", 51);
    
        Str  long_str   = StrInitFromZstr(long_number, &alloc);
            return;
        }
        MemCopy(out, base, baselen);
        out[baselen] = '/';
        MemCopy(out + baselen + 1, name, namelen);
        MemCopy(out, base, baselen);
        out[baselen] = '/';
        MemCopy(out + baselen + 1, name, namelen);
        out[baselen + 1 + namelen] = '\0';
    }
        u8        *sec   = &pe_blob[PE_SECTION_TBL_OFF];
        const char nm[8] = {'.', 'd', 'e', 'b', 'u', 'g', 0, 0};
        MemCopy(sec, nm, 8);
        wr_u32(&sec[8], 0x200);
        wr_u32(&sec[12], PE_DEBUG_DIR_RVA);
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], kAge);
        u64 path_len = ZstrLen(pdb_path);
        wr_u32(&cv[20], kAge);
        u64 path_len = ZstrLen(pdb_path);
        MemCopy(&cv[24], pdb_path, path_len + 1);
    }
    
        // Superblock
        MemCopy(pdb_blob, kPdbMsfMagic, 32);
        wr_u32(&pdb_blob[32], PDB_BLOCK_SIZE);
        wr_u32(&pdb_blob[36], 1);
        wr_u32(&info[4], 0);
        wr_u32(&info[8], kAge);
        MemCopy(&info[12], kGuid, 16);
        if (!match_guid)
            info[12] ^= 0xFF;
        wr_u32(&sym[8], func_rva - sec_va);
        wr_u16(&sym[12], 1);
        MemCopy(&sym[14], func_name, name_len + 1);
    
        // SectionHdr stream: one IMAGE_SECTION_HEADER with VA=sec_va.
        u8      *sec      = &pdb_blob[PDB_SECHDR_PAGE * PDB_BLOCK_SIZE];
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x2000);
        wr_u32(&sec[12], sec_va);
        wr_u32(&seg[4], SEG64_HDR + SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u64(&seg[24], 0x100000000ull);
        wr_u64(&seg[32], 0x1000);
        u8        *sec          = &out[seg_off + SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        wr_u64(&sec[32], 0x100000000ull);
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        wr_u64(&sec[32], 0x100000000ull);
        wr_u64(&sec[40], 0x1000);
        wr_u32(&uc[0], 0x1B);
        wr_u32(&uc[4], UUID_SIZE);
        MemCopy(&uc[8], uuid, 16);
    
        // Symbols + strings.
            while (s[nlen])
                ++nlen;
            MemCopy(&out[str_off + cur_strx], s, nlen);
            out[str_off + cur_strx + nlen]  = '\0';
            cur_strx                       += nlen + 1;
    
        u8 bad_uuid[16];
        MemCopy(bad_uuid, kUuid, 16);
        bad_uuid[0] ^= 0xff;
        mc_wr_u32(&seg[4], MC_SEG64_HDR + MC_SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        mc_wr_u64(&seg[24], 0x100000000ull);
        mc_wr_u64(&seg[32], 0x1000);
        u8        *sec          = &out[seg_off + MC_SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        mc_wr_u64(&sec[32], 0x100000000ull);
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        mc_wr_u64(&sec[32], 0x100000000ull);
        mc_wr_u64(&sec[40], 0x1000);
        mc_wr_u32(&uc[0], 0x1B);
        mc_wr_u32(&uc[4], MC_UUID_SIZE);
        MemCopy(&uc[8], uuid, 16);
    
        u32 cur_strx = 1;
            while (s[nlen])
                ++nlen;
            MemCopy(&out[str_off + cur_strx], s, nlen);
            out[str_off + cur_strx + nlen]  = '\0';
            cur_strx                       += nlen + 1;
        MemSet(strbuf, 0, sizeof(strbuf));
        u64 name_len = ZstrLen(fn_name);
        MemCopy(&strbuf[MC_NAME_STRP], fn_name, name_len);
        strbuf[MC_NAME_STRP + name_len] = '\0';
        u64 str_n                       = MC_NAME_STRP + name_len + 1;
        mc_wr_u32(&seg[4], MC_SEG64_HDR + MC_SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        mc_wr_u64(&seg[24], 0x100000000ull);
        mc_wr_u64(&seg[32], 0x1000);
        u8        *tsec         = &out[text_seg_off + MC_SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&tsec[0], sectname, 16);
        MemCopy(&tsec[16], tname, 16);
        mc_wr_u64(&tsec[32], 0x100000000ull);
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&tsec[0], sectname, 16);
        MemCopy(&tsec[16], tname, 16);
        mc_wr_u64(&tsec[32], 0x100000000ull);
        mc_wr_u64(&tsec[40], 0x1000);
        mc_wr_u32(&uc[0], 0x1B);
        mc_wr_u32(&uc[4], MC_UUID_SIZE);
        MemCopy(&uc[8], uuid, 16);
    
        // __DWARF segment with 3 sections.
        mc_wr_u32(&dseg[4], dwarf_seg_sz);
        const char dname[16] = {'_', '_', 'D', 'W', 'A', 'R', 'F', 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&dseg[8], dname, 16);
        mc_wr_u64(&dseg[24], 0); // vmaddr
        mc_wr_u64(&dseg[32], 0); // vmsize
                ++j;
            }
            MemCopy(&s[16], dname, 16);
            mc_wr_u64(&s[32], 0);              // addr
            mc_wr_u64(&s[40], dsects[i].size); // size
    
        // DWARF payloads.
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], mc_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
        // DWARF payloads.
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], mc_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], mc_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
    
        return total;
    
        u8 bad_uuid[16];
        MemCopy(bad_uuid, mc_kUuid, 16);
        bad_uuid[0] ^= 0xff;
        bl_wr_u32(&seg[4], BL_SEG64_HDR + BL_SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        bl_wr_u64(&seg[24], 0x100000000ull);
        bl_wr_u64(&seg[32], 0x1000);
        u8        *sec          = &out[seg_off + BL_SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        bl_wr_u64(&sec[32], 0x100000000ull);
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);
        MemCopy(&sec[16], tname, 16);
        bl_wr_u64(&sec[32], 0x100000000ull);
        bl_wr_u64(&sec[40], 0x1000);
        bl_wr_u32(&uc[0], 0x1B);
        bl_wr_u32(&uc[4], BL_UUID_SIZE);
        MemCopy(&uc[8], uuid, 16);
    
        return total;
        MemSet(strbuf, 0, sizeof(strbuf));
        u64 name_len = ZstrLen(fn_name);
        MemCopy(&strbuf[BL_NAME_STRP], fn_name, name_len);
        strbuf[BL_NAME_STRP + name_len] = '\0';
        u64 str_n                       = BL_NAME_STRP + name_len + 1;
        bl_wr_u32(&seg[4], BL_SEG64_HDR + BL_SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        bl_wr_u64(&seg[24], 0x100000000ull);
        bl_wr_u64(&seg[32], 0x1000);
        u8        *tsec         = &out[text_seg_off + BL_SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&tsec[0], sectname, 16);
        MemCopy(&tsec[16], tname, 16);
        bl_wr_u64(&tsec[32], 0x100000000ull);
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&tsec[0], sectname, 16);
        MemCopy(&tsec[16], tname, 16);
        bl_wr_u64(&tsec[32], 0x100000000ull);
        bl_wr_u64(&tsec[40], 0x1000);
        bl_wr_u32(&uc[0], 0x1B);
        bl_wr_u32(&uc[4], BL_UUID_SIZE);
        MemCopy(&uc[8], uuid, 16);
    
        u8 *dseg = &out[dwarf_seg_off];
        bl_wr_u32(&dseg[4], dwarf_seg_sz);
        const char dname[16] = {'_', '_', 'D', 'W', 'A', 'R', 'F', 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&dseg[8], dname, 16);
        bl_wr_u64(&dseg[24], 0);
        bl_wr_u64(&dseg[32], 0);
                ++j;
            }
            MemCopy(&s[16], dname, 16);
            bl_wr_u64(&s[32], 0);
            bl_wr_u64(&s[40], dsects[i].size);
        }
    
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], bl_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
    
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], bl_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
        MemCopy(&out[info_off], info, info_n);
        MemCopy(&out[abbrev_off], bl_kAbbrev, abbrev_n);
        MemCopy(&out[str_off], strbuf, str_n);
    
        return total;
        u8        *sec   = &blob[SECTION_TBL_OFF];
        const char nm[8] = {'.', 'd', 'e', 'b', 'u', 'g', 0, 0};
        MemCopy(sec, nm, 8);
        wr_u32(&sec[8], SECTION_VSIZE);
        wr_u32(&sec[12], SECTION_VA);
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], 0x0000002a); // Age
        // PDB path, NUL-terminated.
        // PDB path, NUL-terminated.
        u64 path_len = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, path_len + 1);
    }
        u8        *sec   = &blob[SECTION_TBL_OFF];
        const char nm[8] = {'.', 'd', 'e', 'b', 'u', 'g', 0, 0};
        MemCopy(sec, nm, 8);
        wr_u32(&sec[8], SECTION_VSIZE);
        wr_u32(&sec[12], SECTION_VA);
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], CV_AGE);
        u64 path_len = ZstrLen(kPdbPath);
        wr_u32(&cv[20], CV_AGE);
        u64 path_len = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, path_len + 1);
    }
        u8        *sec   = &blob[OPT_HDR_OFF + OPT_HDR_SIZE_PE32];
        const char nm[8] = {'.', 'd', 'e', 'b', 'u', 'g', 0, 0};
        MemCopy(sec, nm, 8);
        wr_u32(&sec[8], SECTION_VSIZE);
        wr_u32(&sec[12], SECTION_VA);
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], CV_AGE);
        u64 path_len = ZstrLen(kPdbPath);
        wr_u32(&cv[20], CV_AGE);
        u64 path_len = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, path_len + 1);
    }
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        wr_u32(&cv[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, plen + 1);
    }
        cv[2]  = 'D';
        cv[3]  = 'S';
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        wr_u32(&cv[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, plen + 1);
    }
        for (u16 i = 0; i < n; ++i) {
            u8 *sec = &out[SECTION_TBL_OFF + (u32)i * SECTION_ENTSIZE];
            MemCopy(sec, secs[i].name, 8);
            wr_u32(&sec[8], secs[i].vsize);
            wr_u32(&sec[12], secs[i].va);
        build_pe_blob();
        u8 bad[BLOB_SIZE];
        MemCopy(bad, blob, sizeof(bad));
        bad[NT_OFF] = 'Q'; // corrupt 'P' of the NT signature
        return pe_rejects(bad, sizeof(bad));
        build_pe_blob();
        u8 bad[BLOB_SIZE];
        MemCopy(bad, blob, sizeof(bad));
        wr_u16(&bad[OPT_HDR_OFF], 0x1234); // bogus optional magic
        return pe_rejects(bad, sizeof(bad));
        build_pe_blob();
        u8 bad[BLOB_SIZE];
        MemCopy(bad, blob, sizeof(bad));
        wr_u32(&bad[DOS_E_LFANEW_OFF], (u32)sizeof(bad) + 0x1000);
        return pe_rejects(bad, sizeof(bad));
        build_pe_blob_m1();
        u8 bad[BLOB_SIZE];
        MemCopy(bad, blob, sizeof(bad));
        // Declare a SizeOfOptionalHeader larger than the bytes remaining
        // after opt_offset. opt_offset = 0x98 (152); remaining = 2048-152 =
        cv2[2]  = 'D';
        cv2[3]  = 'S';
        MemCopy(&cv2[4], kGuid, 16);
        wr_u32(&cv2[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        wr_u32(&cv2[20], CV_AGE);
        u64 plen = ZstrLen(kPdbPath);
        MemCopy(&cv2[24], kPdbPath, plen + 1);
        Pe pe;
        if (!PeOpenFromMemoryCopy(&pe, blob, sizeof(blob), ALLOCATOR_OF(&alloc))) {
        SecDesc          secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".rdata\0\0", 8);
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".rdata\0\0", 8);
        secs[1].va = 0x2000;
        SecDesc          secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".b\0\0\0\0\0\0", 8);
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".b\0\0\0\0\0\0", 8);
        secs[1].va = 0x2000;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, "ABCDEFGH", 8); // all 8 bytes used
        secs[0].va = 0x1000;
        SecDesc          secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".b\0\0\0\0\0\0", 8);
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".b\0\0\0\0\0\0", 8);
        secs[1].va = 0x2000;
        SecDesc          secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va       = 0x1000;
        secs[0].vsize    = 0x100;
        secs[0].raw_off  = 0x200;
        secs[0].raw_size = 0x100;
        MemCopy(secs[1].name, ".b\0\0\0\0\0\0", 8);
        secs[1].va       = 0x2000;
        secs[1].vsize    = 0x100;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va       = 0x1000;
        secs[0].vsize    = 0x100;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va    = 0x1000;
        secs[0].vsize = 0x100;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va      = 0x1000;
        secs[0].vsize   = 0x100;
        SecDesc          secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, "ABCDEFGH", 8); // full 8-char name, no NUL
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, "ABCDEFGH", 8); // full 8-char name, no NUL
        secs[1].va      = 0x2000;
        secs[1].raw_off = 0x321;
        SecDesc secs[2];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".rdata\0\0", 8);
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        MemCopy(secs[1].name, ".rdata\0\0", 8);
        secs[1].va = 0x2000;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        SecDesc secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".text\0\0\0", 8);
        secs[0].va = 0x1000;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
        SecDesc          secs[1];
        MemSet(secs, 0, sizeof(secs));
        MemCopy(secs[0].name, ".a\0\0\0\0\0\0", 8);
        secs[0].va = 0x1000;
    
        // --- Superblock (page 0) -------------------------------------------------
        MemCopy(blob, kMagic, 32);
        wr_u32(&blob[32], BLOCK_SIZE);
        wr_u32(&blob[36], 1);         // free_block_map_block
        wr_u32(&info[4], 0xdeadbeef);
        wr_u32(&info[8], 0x42);
        MemCopy(&info[12], kGuid, 16);
    }
    
        // --- Superblock --------------------------------------------------------
        MemCopy(fblob, kMagic, 32);
        wr_u32(&fblob[32], F_BLOCK_SIZE);
        wr_u32(&fblob[36], 1);           // free_block_map_block
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        // --- DBI stream (#3) ---------------------------------------------------
        wr_u16(&sym[12], 1);                   // Segment (1-based)
        const char name[] = "my_function";
        MemCopy(&sym[14], name, sizeof(name)); // includes NUL
    
        // --- SectionHdr stream (#5) --------------------------------------------
        //                      NumRelocs(2) + NumLineNum(2) + Characteristics(4)
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x2000);       // VirtualSize
        wr_u32(&sec[12], 0x1000);      // VirtualAddress
        wr_u32(&p[8], offset);
        wr_u16(&p[12], segment);
        MemCopy(&p[14], name, namelen);
        *sym = p + 2 + rec_len;
    }
        const u32 dir_bytes = 4 + M_NUM_STREAMS * 4 + 4 * 4;
    
        MemCopy(mblob, kMagic, 32);
        wr_u32(&mblob[32], M_BLOCK_SIZE);
        wr_u32(&mblob[36], 1);
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        u8 *dbi = &mblob[M_DBI_PAGE * M_BLOCK_SIZE];
        u8      *sec      = &mblob[M_SECHDR_PAGE * M_BLOCK_SIZE];
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x2000);  // VirtualSize
        wr_u32(&sec[12], 0x1000); // VirtualAddress
        u8 buf[256];
        MemSet(buf, 0, sizeof(buf));
        MemCopy(buf, kMagic, 32);
        wr_u32(&buf[32], 333); // bogus block size
        wr_u32(&buf[36], 1);
    
        u8 buf[16];
        MemCopy(buf, kMagic, 16); // partial magic, far short of 56-byte superblock
    
        Pdb  pdb;
    
        // --- Superblock ---------------------------------------------------------
        MemCopy(gblob, kMagic, 32);
        wr_u32(&gblob[32], D1_BLOCK_SIZE);
        wr_u32(&gblob[36], 1);            // free_block_map_block
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        // --- DBI stream (#3) ----------------------------------------------------
        wr_u16(&sym[12], 1);     // Segment (1-based)
        const char name[] = "my_function";
        MemCopy(&sym[14], name, sizeof(name));
    
        // --- SectionHdr stream (#5): one .text section -------------------------
        u8      *sec      = &gblob[D1_SECHDR_PAGE * D1_BLOCK_SIZE];
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x2000);  // VirtualSize
        wr_u32(&sec[12], 0x1000); // VirtualAddress
    
        // --- Superblock (page 0) ---------------------------------------------
        MemCopy(g_blob, kMagic, 32);
        wr_u32(&g_blob[32], bs);
        wr_u32(&g_blob[36], 1);           // free_block_map_block
    
        // --- Superblock ------------------------------------------------------
        MemCopy(g_blob, kMagic, 32);
        wr_u32(&g_blob[32], bs);
        wr_u32(&g_blob[36], 1);
        u8 buf[256];
        MemSet(buf, 0, sizeof(buf));
        MemCopy(buf, kMagic, 32);
        wr_u32(&buf[32], 256);
        wr_u32(&buf[36], 1);
        u8 buf[55]; // one short of the 56-byte superblock
        MemSet(buf, 0, sizeof(buf));
        MemCopy(buf, kMagic, 32);
        wr_u32(&buf[32], B_BS);
        MemSet(g_tblob, 0, sizeof(g_tblob));
    
        MemCopy(g_tblob, kMagic, 32);
        wr_u32(&g_tblob[32], T_BS);
        wr_u32(&g_tblob[36], 1);
    
        // Split: first 512 bytes to page 4, remaining 96 bytes to page 10.
        MemCopy(&g_tblob[T_DIR_PG0 * T_BS], dir, T_BS);
        MemCopy(&g_tblob[T_DIR_PG1 * T_BS], dir + T_BS, T_DIR_BYTES - T_BS);
        // Split: first 512 bytes to page 4, remaining 96 bytes to page 10.
        MemCopy(&g_tblob[T_DIR_PG0 * T_BS], dir, T_BS);
        MemCopy(&g_tblob[T_DIR_PG1 * T_BS], dir + T_BS, T_DIR_BYTES - T_BS);
    
        // Stream 1 content.
        };
        MemSet(g_blob, 0, sizeof(g_blob));
        MemCopy(g_blob, kMagic, 32);
        wr_u32(&g_blob[32], Z_BS);
        wr_u32(&g_blob[36], 1);
    
        MemSet(g_hblob, 0, sizeof(g_hblob));
        MemCopy(g_hblob, kMagic, 32);
        wr_u32(&g_hblob[32], H_BS);
        wr_u32(&g_hblob[36], 1);
        wr_u32(&p[8], offset);
        wr_u16(&p[12], segment);
        MemCopy(&p[14], name, namelen);
        *sym = p + 2 + rec_len;
    }
        for (i = 0; i < 8 && name8[i]; ++i)
            nm[i] = (u8)name8[i];
        MemCopy(sec, nm, 8);
        wr_u32(&sec[8], vsize);  // VirtualSize
        wr_u32(&sec[12], vaddr); // VirtualAddress
        const u32 dir_bytes = 4 + G_NUM_STREAMS * 4 + 4 * 4;
    
        MemCopy(blob, kMagic, 32);
        wr_u32(&blob[32], G_BLOCK_SIZE);
        wr_u32(&blob[36], 1);
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        u8 *dbi = &blob[G_DBI_PAGE * G_BLOCK_SIZE];
    
        // --- Superblock --------------------------------------------------------
        MemCopy(xblob, kMagic, 32);
        wr_u32(&xblob[32], X_BLOCK_SIZE);
        wr_u32(&xblob[36], 1);
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        // --- DBI stream (#3) ---------------------------------------------------
        u8      *sec      = &xblob[X_SECHDR_PAGE * X_BLOCK_SIZE];
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x4000);  // VirtualSize
        wr_u32(&sec[12], 0x1000); // VirtualAddress
        write_pub32(&p, 0x1000, 1, "second_block_function");
    
        MemCopy(&xblob[X_SYM_PAGE0 * X_BLOCK_SIZE], sym_flat, X_BLOCK_SIZE);
        MemCopy(&xblob[X_SYM_PAGE1 * X_BLOCK_SIZE], sym_flat + X_BLOCK_SIZE, X_SYM_SIZE - X_BLOCK_SIZE);
    }
    
        MemCopy(&xblob[X_SYM_PAGE0 * X_BLOCK_SIZE], sym_flat, X_BLOCK_SIZE);
        MemCopy(&xblob[X_SYM_PAGE1 * X_BLOCK_SIZE], sym_flat + X_BLOCK_SIZE, X_SYM_SIZE - X_BLOCK_SIZE);
    }
        MemSet(sblob, 0, sizeof(sblob));
    
        MemCopy(sblob, kMagic, 32);
        wr_u32(&sblob[32], S_BLOCK_SIZE);
        wr_u32(&sblob[36], 1);
        wr_u32(&info[4], 0xdeadbeef);
        wr_u32(&info[8], 0x42);
        MemCopy(&info[12], kGuid, 16);
    }
            return false;
        }
        MemCopy(BufData(&in), sblob, sizeof(sblob));
        BufResize(&in, (size)sizeof(sblob));
            wr_u32(&sp[8], pubs[i].offset);
            wr_u16(&sp[12], pubs[i].segment);
            MemCopy(&sp[14], pubs[i].name, namelen);
            sp += 2 + rec_len;
        }
        const u32 dir_bytes = 4 + N_STREAMS * 4 + 4 * 4;
    
        MemCopy(blob, kMagic, 32);
        wr_u32(&blob[32], PG_SIZE);
        wr_u32(&blob[36], 1);
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    
        // --- DBI (#3) -----------------------------------------------------
        u32 adv_dir    = dir_bytes_override ? dir_bytes_override : dir_bytes;
    
        MemCopy(g_buf, kMagic, 32);
        wr_u32(&g_buf[32], bs);
        wr_u32(&g_buf[36], 1);
        wr_u32(&info[4], 0xfeedface);
        wr_u32(&info[8], 1);
        MemCopy(&info[12], kGuid, 16);
    }
    static void put_section_at(u8 *sec, u32 va) {
        const u8 sname[8] = {'.', 't', 'e', 'x', 't', 0, 0, 0};
        MemCopy(sec, sname, 8);
        wr_u32(&sec[8], 0x2000);
        wr_u32(&sec[12], va);
        wr_u32(&dst[8], offset);
        wr_u16(&dst[12], segment);
        MemCopy(&dst[14], name, namelen);
        return 2 + rec_len;
    }
        for (u32 i = 0; i < NSEC; ++i) {
            const u8 sname[8] = {'.', 's', 0, 0, 0, 0, 0, 0};
            MemCopy(&sec[i * 40], sname, 8);
            wr_u32(&sec[i * 40 + 8], 0x2000);
            wr_u32(&sec[i * 40 + 12], 0x1000 + i * 0x4000);
        wr_u32(&seg[4], SEG64_HDR + SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);      // segname
        wr_u64(&seg[24], 0x100000000ull); // vmaddr
        wr_u64(&seg[32], 0x1000);         // vmsize
        u8        *sec          = &blob[seg_off + SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);   // sectname
        MemCopy(&sec[16], tname, 16);     // segname
        wr_u64(&sec[32], 0x100000000ull); // addr
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);   // sectname
        MemCopy(&sec[16], tname, 16);     // segname
        wr_u64(&sec[32], 0x100000000ull); // addr
        wr_u64(&sec[40], 0x100);          // size
        wr_u32(&uc[0], 0x1B);
        wr_u32(&uc[4], UUID_SIZE);
        MemCopy(&uc[8], kUuid, 16);
    
        // --- Symbol table (nlist_64 * 1) at offset 256 ------------------------
        strs[0]         = '\0';
        const char nm[] = "my_function";
        MemCopy(&strs[1], nm, sizeof(nm));
    }
        wr_u32(&seg[4], SEG64_HDR + SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u64(&seg[24], 0x100000000ull); // vmaddr
        wr_u64(&seg[32], 0x1000);         // vmsize
        u8        *sec          = &b[SEG_OFF + SEG64_HDR];
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);   // sectname
        MemCopy(&sec[16], tname, 16);     // segname
        wr_u64(&sec[32], 0x100000000ull); // addr
        const char sectname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sectname, 16);   // sectname
        MemCopy(&sec[16], tname, 16);     // segname
        wr_u64(&sec[32], 0x100000000ull); // addr
        wr_u64(&sec[40], 0x100);          // size
        wr_u32(&uc[0], LC_UUID);
        wr_u32(&uc[4], UUID_SIZE);
        MemCopy(&uc[8], kUuid, 16);
    }
        wr_u32(&seg[4], cmdsize);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u64(&seg[24], 0x100000000ull); // vmaddr
        wr_u64(&seg[32], 0x10000);        // vmsize
            u8        *sec    = &buf[HDR_SIZE + SEG64_HDR + i * SECT64_SIZE];
            const char sn[16] = {'_', '_', 's', 'e', 'c', 't', (char)('0' + (char)i), 0, 0, 0, 0, 0, 0, 0, 0, 0};
            MemCopy(&sec[0], sn, 16);                           // sectname
            MemCopy(&sec[16], tname, 16);                       // segname
            wr_u64(&sec[32], 0x100000000ull + (u64)i * 0x1000); // addr
            const char sn[16] = {'_', '_', 's', 'e', 'c', 't', (char)('0' + (char)i), 0, 0, 0, 0, 0, 0, 0, 0, 0};
            MemCopy(&sec[0], sn, 16);                           // sectname
            MemCopy(&sec[16], tname, 16);                       // segname
            wr_u64(&sec[32], 0x100000000ull + (u64)i * 0x1000); // addr
            wr_u64(&sec[40], 0x100);                            // size
        wr_u32(&seg[4], seg_size);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u64(&seg[24], 0x100000000ull); // vmaddr
        wr_u64(&seg[32], 0x10000);        // vmsize
        u8        *sec       = &g_symblob[seg_off + SEG64_HDR];
        const char sname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sname, 16);
        MemCopy(&sec[16], tname, 16);
        wr_u64(&sec[32], 0x100000000ull); // addr
        const char sname[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sec[0], sname, 16);
        MemCopy(&sec[16], tname, 16);
        wr_u64(&sec[32], 0x100000000ull); // addr
        wr_u64(&sec[40], 0x10000);        // size
        build_macho_blob();
        u8 bad[BLOB_SIZE];
        MemCopy(bad, blob, sizeof(bad));
        // The LC_SYMTAB command's symoff field lives at sym_cmd_off + 8.
        u32 sym_cmd_off = 32 + SEG64_HDR + SECT64_SIZE;
    static void build_two_symbol_blob(void) {
        build_macho_blob();
        MemCopy(two_blob, blob, sizeof(two_blob));
    
        // Bump nsyms to 2 in the LC_SYMTAB command.
        b[cfg.stroff + 0] = '\0';
        const char nm[]   = "fn_a";
        MemCopy(&b[cfg.stroff + 1], nm, sizeof(nm));
    
        Macho m;
        wr_nlist(b, cfg.symoff + 1 * NLIST64_SIZE, 7, 0x24, 2, 0x100000040ull);
        b[stroff + 0] = '\0';
        MemCopy(&b[stroff + 1], "alpha", 6); // includes NUL at stroff+6
        MemCopy(&b[stroff + 7], "beta", 5);  // includes NUL at stroff+11
        b[stroff + 0] = '\0';
        MemCopy(&b[stroff + 1], "alpha", 6); // includes NUL at stroff+6
        MemCopy(&b[stroff + 7], "beta", 5);  // includes NUL at stroff+11
    
        Macho m;
        wr_nlist(b, cfg.symoff, 1, 0x0F, /*n_sect*/ 5, 0x100000010ull);
        b[cfg.stroff] = '\0';
        MemCopy(&b[cfg.stroff + 1], "z", 2);
    
        Macho m;
        wr_nlist(b, symoff, 1, 0x0F, 1, 0x100000010ull);
        b[stroff] = '\0';
        MemCopy(&b[stroff + 1], "fit", 4);
    
        Macho m;
        wr_nlist(b, symoff, 1, 0x0F, 1, 0x100000010ull);
        b[stroff] = '\0';
        MemCopy(&b[stroff + 1], "edge", 5);
    
        Macho m;
            wr_nlist(b, symoff + i * NLIST64_SIZE, 1, 0x0F, 1, 0x100000010ull + i);
        b[stroff] = '\0';
        MemCopy(&b[stroff + 1], "sym", 4);
    
        Macho m;
        // still find a NUL and parse one symbol -> distinguishable outcome).
        b[stroff] = '\0';
        MemCopy(&b[stroff + 1], "ovr", 4);
    
        Macho m;
        wr_u32(&seg[4], SEG2_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u64(&seg[24], 0x100000000ull);
        wr_u64(&seg[32], 0x2000);
        u8        *sa       = &b[SECT_A];
        const char sa_n[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sa[0], sa_n, 16);
        MemCopy(&sa[16], tname, 16);
        wr_u64(&sa[32], 0x100000000ull);
        const char sa_n[16] = {'_', '_', 't', 'e', 'x', 't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sa[0], sa_n, 16);
        MemCopy(&sa[16], tname, 16);
        wr_u64(&sa[32], 0x100000000ull);
        wr_u64(&sa[40], 0x100);
        u8        *sb       = &b[SECT_B];
        const char sb_n[16] = {'_', '_', 'c', 's', 't', 'r', 'i', 'n', 'g', 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sb[0], sb_n, 16);
        MemCopy(&sb[16], tname, 16);
        wr_u64(&sb[32], 0x100000100ull);
        const char sb_n[16] = {'_', '_', 'c', 's', 't', 'r', 'i', 'n', 'g', 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&sb[0], sb_n, 16);
        MemCopy(&sb[16], tname, 16);
        wr_u64(&sb[32], 0x100000100ull);
        wr_u64(&sb[40], 0x80);
        wr_u32(&uc[0], LC_UUID);
        wr_u32(&uc[4], UUID_SIZE);
        MemCopy(&uc[8], kUuid, 16);
    
        Macho m;
        wr_u32(&seg[4], SEG64_HDR); // cmdsize == 72, exact minimum
        const char nm[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], nm, 16);
        wr_u64(&seg[24], 0x1000);   // vmaddr
        wr_u64(&seg[32], 0x1000);   // vmsize
        // bounding the string.
        const char nm[16] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'};
        MemCopy(&seg[8], nm, 16);
        wr_u32(&seg[64], 0); // nsects == 0
        wr_u32(&seg[4], SEG64_HDR + SECT64_SIZE);
        const char tname[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], tname, 16);
        wr_u32(&seg[64], 1); // nsects == 1
        const char sn[16] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'};
        const char gn[16] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5'};
        MemCopy(&sec[0], sn, 16);
        MemCopy(&sec[16], gn, 16);
        wr_u64(&sec[32], 0x100000000ull); // addr
        const char gn[16] = {'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5'};
        MemCopy(&sec[0], sn, 16);
        MemCopy(&sec[16], gn, 16);
        wr_u64(&sec[32], 0x100000000ull); // addr
        wr_u64(&sec[40], 0x100);          // size
        wr_u32(&seg[4], SEG64_HDR);
        const char nm[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], nm, 16);
        wr_u32(&seg[64], 0); // nsects == 0
        wr_u32(&seg[4], SEG64_HDR);
        const char nm[16] = {'_', '_', 'T', 'E', 'X', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        MemCopy(&seg[8], nm, 16);
        wr_u32(&seg[64], 0); // nsects == 0
        wr_u32(&uc[0], LC_UUID);
        wr_u32(&uc[4], UUID_SIZE);
        MemCopy(&uc[8], kUuid, 16);
    
        Macho m;
        // --- .shstrtab content ------------------------------------------------
        const char shstr[SHSTR_SIZE] = "\0.shstrtab\0.text\0.symtab\0.strtab\0";
        MemCopy(&elf_blob[SHSTR_OFF], shstr, SHSTR_SIZE);
    
        // --- .strtab content --------------------------------------------------
        // --- .strtab content --------------------------------------------------
        const char strtab[STRTAB_SZ] = "\0my_func\0";
        MemCopy(&elf_blob[STRTAB_OFF], strtab, STRTAB_SZ);
    
        // --- symbol table: [0]=null, [1]=my_func (FUNC, GLOBAL) ---------------
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[1] = 'X'; // corrupt 'E' of the ELF magic
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[4] = (u8)ELF_CLASS_32; // v1 supports ELF64 only
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        wr_u16(&bad[16 + 40], 3); // e_phnum = 3, but only 2 PT_LOADs fit before EOF
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        wr_u16(&bad[16 + 46], N_SECTIONS); // e_shstrndx = shnum (out of range)
        wr_shdr(
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[5] = (u8)ELF_DATA_MSB; // v1 supports little-endian only
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // Point e_shoff (at e_ident + 24 = offset 40) well past EOF.
        wr_u64(&bad[16 + 24], (u64)sizeof(bad) + 0x1000);
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        wr_u16(&bad[16 + 30], (u16)(N_SECTIONS + 5)); // e_shstrndx past end
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // .symtab is section index 3; its header's sh_size is at
        // SHT_OFF + 3*64 + 32. Blow it up past EOF.
        // --- .shstrtab --------------------------------------------------------
        const char shstr[DBG_SHSTR_SIZE] = "\0.shstrtab\0.note.gnu.build-id\0.gnu_debuglink\0";
        MemCopy(&dbg_blob[DBG_SHSTR_OFF], shstr, DBG_SHSTR_SIZE);
    
        // --- build-id note: namesz=4, descsz=8, type=3 (NT_GNU_BUILD_ID), -----
        note[14] = 'U';
        note[15] = '\0';
        MemCopy(&note[16], kBuildId, BUILD_ID_LEN);
    
        // --- .gnu_debuglink: "foo.debug\0" + pad + crc32 ----------------------
        u8        *dl      = &dbg_blob[DBG_DL_OFF];
        const char fname[] = "foo.debug";
        MemCopy(dl, fname, sizeof(fname)); // includes NUL
        wr_u32(&dl[DBG_DL_SIZE - 4], DEBUGLINK_CRC);
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // e_shstrndx sits at e_ident(16) + 46 = byte 62 in the header.
        wr_u16(&bad[16 + 46], (u16)N_SECTIONS); // e_shstrndx = n (one past the last valid index)
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // shstrtab is section index 1; its sh_size is at SHT_OFF + 1*64 + 32.
        // Blow it up past EOF (offset stays valid, size overruns).
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // shstrtab header: offset = file_size, size = 0.
        wr_u64(&bad[SHT_OFF + SEC_SHSTRTAB * SHDR_SIZE + 24], (u64)sizeof(bad)); // sh_offset
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // shstrtab header: offset = 0, size = file_size (exact fit).
        wr_u64(&bad[SHT_OFF + SEC_SHSTRTAB * SHDR_SIZE + 24], 0);                // sh_offset
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // .symtab is section index 3. Set its offset/size so each fits alone
        // but the sum runs past EOF: offset = file_size - 0x20, size = 0x40.
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[0] = 0x00; // corrupt 0x7f
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[1] = 'X'; // corrupt 'E'
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[2] = 'X'; // corrupt 'L'
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[3] = 'X'; // corrupt 'F'
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[4] = (u8)ELF_CLASS_32; // 32-bit not supported
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[4] = (u8)ELF_CLASS_INVALID;
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[5] = (u8)ELF_DATA_MSB; // big-endian not supported
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[5] = (u8)ELF_DATA_INVALID;
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        bad[4] = (u8)ELF_CLASS_64 + 1; // 3
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        wr_u16(&bad[OFF_E_SHENTSIZE], 0); // e_shentsize = 0, with shnum > 0
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        wr_u16(&bad[OFF_E_SHENTSIZE], 65); // e_shentsize = 65, with shnum > 0
        return elf_rejects(bad, sizeof(bad));
        build_elf_blob();
        u8 bad[ELF_FIXTURE_SIZE];
        MemCopy(bad, elf_blob, sizeof(bad));
        // .symtab is section index 3; sh_size lives at SHT_OFF + 3*64 + 32.
        // Blow it past EOF so decode_symbols fails after decode_sections has
    
        const char shstr[] = "\0.shstrtab\0.symtab\0.strtab\0.dynsym\0.dynstr\0";
        MemCopy(&sym_blob[SF_SHSTR_OFF], shstr, sizeof(shstr));
    
        const char strtab[] = "\0alpha\0beta\0local\0beta_lo\0";
    
        const char strtab[] = "\0alpha\0beta\0local\0beta_lo\0";
        MemCopy(&sym_blob[SF_STRTAB_OFF], strtab, sizeof(strtab));
    
        const char dynstr[] = "\0dyn_sym\0";
    
        const char dynstr[] = "\0dyn_sym\0";
        MemCopy(&sym_blob[SF_DYNSTR_OFF], dynstr, sizeof(dynstr));
    
        // .symtab: [0]=null, [1]=alpha(GLOBAL FUNC, sized), [2]=beta_lo(LOCAL,
    
        const char shstr[] = "\0.shstrtab\0.note.gnu.build-id\0";
        MemCopy(&bid_blob[BID_SHSTR_OFF], shstr, sizeof(shstr));
    
        if (note_payload && note_size)
    
        if (note_payload && note_size)
            MemCopy(&bid_blob[BID_NOTE_OFF], note_payload, note_size);
    
        u64 note_off = note_off_override ? note_off_override : (u64)BID_NOTE_OFF;
        u8               note[16 + sizeof(desc)];
        wr_note_hdr(note, 4, (u32)sizeof(desc), NT_GNU_BUILD_ID);
        MemCopy(&note[16], desc, sizeof(desc));
        build_bid_blob(note, (u32)sizeof(note), 0);
    
        const char shstr[] = "\0.shstrtab\0.gnu_debuglink\0";
        MemCopy(&dl_blob[DL_SHSTR_OFF], shstr, sizeof(shstr));
    
        if (payload && dl_size)
    
        if (payload && dl_size)
            MemCopy(&dl_blob[DL_DATA_OFF], payload, dl_size);
    
        u64 off = off_override ? off_override : (u64)DL_DATA_OFF;
        MemSet(payload, 0, sizeof(payload));
        const char fname[] = "abc.debug";
        MemCopy(payload, fname, sizeof(fname)); // includes NUL
        wr_u32(&payload[12], 0x0a0b0c0du);
        build_dl_blob(payload, 16, 0);
        MemSet(payload, 0, sizeof(payload));
        const char fname[] = "abc.debug";
        MemCopy(payload, fname, sizeof(fname));
        wr_u32(&payload[12], 0x0a0b0c0du);
        build_dl_blob(payload, 16, (u64)sizeof(dl_blob) + 0x1000);
    
        const char shstr[DBG_SHSTR_SIZE] = "\0.shstrtab\0.note.gnu.build-id\0.gnu_debuglink\0";
        MemCopy(&blob[DBG_SHSTR_OFF], shstr, DBG_SHSTR_SIZE);
    
        // build-id note: namesz=4, descsz=8, type=3, name "GNU\0", desc=kBuildId.
        note[14] = 'U';
        note[15] = '\0';
        MemCopy(&note[16], kBuildId, BUILD_ID_LEN);
    
        // .gnu_debuglink: "foo.debug\0" + pad + crc32.
        u8        *dl      = &blob[DBG_DL_OFF];
        const char fname[] = "foo.debug";
        MemCopy(dl, fname, sizeof(fname));
        wr_u32(&dl[DBG_DL_SIZE - 4], DEBUGLINK_CRC);
    
        // shstrtab: "\0.shstrtab\0.symtab\0"
        MemCopy(&buf[SHSTR_OFF], "\0.shstrtab\0.symtab\0", 19);
    
        u8 *sht = &buf[SHT_OFF];
        put_u16(elf + 62, 1);         // e_shstrndx
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + eh_off, eh, eh_len);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + eh_off, eh, eh_len);
    
        u8 *sh = elf + shtab_off;
        eh[11] = 0x78;                  // data_alignment_factor = sleb(-8)
        eh[12] = 16;                    // return_address_register (u8, v1)
        MemCopy(eh + 13, cie_insns, cie_n);
        u64 fde_off = 13 + cie_n;       // == 4 + cie_body
        put_u64(eh + fde_off + 8, pc_begin);
        put_u64(eh + fde_off + 16, pc_range);
        MemCopy(eh + fde_off + 24, fde_insns, fde_n);
        u64 term_off = fde_off + 24 + fde_n;
            }
            p += enc_uleb(eh + p, an);
            MemCopy(eh + p, aug, an);
            p += an;
        }
        }
        if (c->insns_n) {
            MemCopy(eh + p, c->insns, c->insns_n);
            p += c->insns_n;
        }
        }
        if (fde_n) {
            MemCopy(eh + p, fde_insns, fde_n);
            p += fde_n;
        }
        put_u16(elf + 62, 1);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + df_off, df, df_len);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + df_off, df, df_len);
    
        u8 *sh = elf + shtab_off;
        df[11] = 0x78;               // data_alignment_factor = -8
        df[12] = 16;                 // return_address_register
        MemCopy(df + 13, cie_insns, cie_n);
        u64 fde_off = 13 + cie_n;
        put_u64(df + fde_off + 8, pc_begin);
        put_u64(df + fde_off + 16, pc_range);
        MemCopy(df + fde_off + 24, fde_insns, fde_n);
        u64 term_off = fde_off + 24 + fde_n;
        w->buf[w->pos++]  = 0x78;    // data_alignment_factor = -8
        w->buf[w->pos++]  = 16;      // return_address_register
        MemCopy(w->buf + w->pos, insns, n);
        w->pos += n;
        return off;
        put_u64(w->buf + w->pos, pc_range);
        w->pos += 8;
        MemCopy(w->buf + w->pos, insns, n);
        w->pos += n;
        return off;
        put_u16(elf + 62, 1);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + df_off, df, df_len);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + df_off, df, df_len);
    
        u8 *sh = elf + shtab_off;
        // sentinel.)
        const char dname[] = "src_dir";
        MemCopy(p, dname, sizeof(dname)); // includes NUL
        p    += sizeof(dname);
        *p++  = 0x00;                     // include_directories terminator
        // file_names: one entry "source.c", dir_idx 1, mtime 0, size 0, then NUL.
        const char fname[] = "source.c";
        MemCopy(p, fname, sizeof(fname)); // includes NUL
        p    += sizeof(fname);
        *p++  = 0x01;                     // dir index (uleb) -> "src_dir"
    
        // --- section payloads ---
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + dl_off, dl, dl_len);
        // --- section payloads ---
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + dl_off, dl, dl_len);
    
        // --- section headers (3 * 64 bytes) ---
        // include_directories: one entry "src_dir", terminator NUL.
        const char dname[] = "src_dir";
        MemCopy(p, dname, sizeof(dname));
        p    += sizeof(dname);
        *p++  = 0x00; // include_directories terminator
        // file_names: entry 1 "source.c".
        const char fname1[] = "source.c";
        MemCopy(p, fname1, sizeof(fname1));
        p    += sizeof(fname1);
        *p++  = 0x01; // dir index
        // file_names: entry 2 "other.c".
        const char fname2[] = "other.c";
        MemCopy(p, fname2, sizeof(fname2));
        p    += sizeof(fname2);
        *p++  = 0x01; // dir index
        put_u32(hdr_len_field, (u32)(p - after_hdr_len));
    
        MemCopy(p, prog, prog_len);
        p += prog_len;
            *p++ = kStdOpcodeLengths[i];           // standard_opcode_lengths
        const char dname[] = "src_dir";
        MemCopy(p, dname, sizeof(dname));
        p                  += sizeof(dname);
        *p++                = 0x00; // include_directories terminator
        *p++                = 0x00; // include_directories terminator
        const char fname[]  = "source.c";
        MemCopy(p, fname, sizeof(fname));
        p    += sizeof(fname);
        *p++  = 0x01; // dir index
        put_u32(hdr_len_field, (u32)(p - after_hdr_len));
    
        MemCopy(p, prog, prog_len);
        p += prog_len;
        // include_directories: "dir_zero", "real_dir", then NUL terminator.
        const char d0[] = "dir_zero";
        MemCopy(p, d0, sizeof(d0));
        p               += sizeof(d0);
        const char d1[]  = "real_dir";
        p               += sizeof(d0);
        const char d1[]  = "real_dir";
        MemCopy(p, d1, sizeof(d1));
        p    += sizeof(d1);
        *p++  = 0x00; // include_directories terminator
        // file_names: "first.c" dir 1, "second.c" dir 2, then NUL terminator.
        const char f0[] = "first.c";
        MemCopy(p, f0, sizeof(f0));
        p               += sizeof(f0);
        *p++             = 0x01; // dir index 1 -> "dir_zero"
        *p++             = 0x00; // size
        const char f1[]  = "second.c";
        MemCopy(p, f1, sizeof(f1));
        p    += sizeof(f1);
        *p++  = 0x02; // dir index 2 -> "real_dir"
        put_u16(elf + 62, 1);         // e_shstrndx
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + dl_off, dl, dl_len);
    
        MemCopy(elf + shstr_off, shstr, shstr_len);
        MemCopy(elf + dl_off, dl, dl_len);
    
        u8 *sh = elf + shtab_off;
        // file 2's dir index 2 no longer resolves "real_dir".
        const char d0[] = "z";
        MemCopy(p, d0, sizeof(d0));
        p               += sizeof(d0);
        const char d1[]  = "real_dir";
        p               += sizeof(d0);
        const char d1[]  = "real_dir";
        MemCopy(p, d1, sizeof(d1));
        p    += sizeof(d1);
        *p++  = 0x00; // include_directories terminator
        // file_names: "first.c" dir 1, "second.c" dir 2, then NUL terminator.
        const char f0[] = "first.c";
        MemCopy(p, f0, sizeof(f0));
        p               += sizeof(f0);
        *p++             = 0x01; // dir index 1 -> "z" (pool offset 0 -> NULL dir)
        *p++             = 0x00; // size
        const char f1[]  = "second.c";
        MemCopy(p, f1, sizeof(f1));
        p    += sizeof(f1);
        *p++  = 0x02; // dir index 2 -> "real_dir"
            *p++ = std_lengths[i];
        const char dname[] = "src_dir";
        MemCopy(p, dname, sizeof(dname));
        p                  += sizeof(dname);
        *p++                = 0x00;
        *p++                = 0x00;
        const char fname[]  = "source.c";
        MemCopy(p, fname, sizeof(fname));
        p    += sizeof(fname);
        *p++  = 0x01;
        put_u32(hdr_len_field, (u32)(p - after_hdr_len));
    
        MemCopy(p, prog, prog_len);
        p += prog_len;
    
        const char d1[] = "dir_one";
        MemCopy(p, d1, sizeof(d1));
        p               += sizeof(d1);
        const char d2[]  = "dir_two";
        p               += sizeof(d1);
        const char d2[]  = "dir_two";
        MemCopy(p, d2, sizeof(d2));
        p    += sizeof(d2);
        *p++  = 0x00; // include_directories terminator
    
        const char f1[] = "first.c";
        MemCopy(p, f1, sizeof(f1));
        p               += sizeof(f1);
        *p++             = 0x01; // dir index 1 -> "dir_one"
        *p++             = 0x00; // size
        const char f2[]  = "second.c";
        MemCopy(p, f2, sizeof(f2));
        p    += sizeof(f2);
        *p++  = 0x02; // dir index 2 -> "dir_two"
        // non-zero offset, so the file-present sentinel still works).
        const char d1[] = "somedir";
        MemCopy(q, d1, sizeof(d1));
        q    += sizeof(d1);
        *q++  = 0x00; // include_directories terminator
        // file_names: "only.c" with dir index 0 (root / no directory).
        const char f1[] = "only.c";
        MemCopy(q, f1, sizeof(f1));
        q    += sizeof(f1);
        *q++  = 0x00; // dir index 0
        // first iteration has already allocated CuStrings storage.
        const char d1[] = "good_dir";
        MemCopy(q, d1, sizeof(d1));
        q               += sizeof(d1);
        const char d2[]  = "runaway_directory_with_no_terminator_byte_present";
        q               += sizeof(d1);
        const char d2[]  = "runaway_directory_with_no_terminator_byte_present";
        MemCopy(q, d2, sizeof(d2) - 1); // no trailing NUL
        q += sizeof(d2) - 1;
        put_u32(unit_len_field, (u32)(q - (unit_len_field + 4)));
Last updated on