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;
        }
    
        MemCopy(new_str, src, len);
        new_str[len] = '\0';
        return new_str;
                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);
        }
                }
                char *data = StrBegin(&flagbuf);
                MemCopy(data, tok, n);
                data[n] = '\0';
                StrResize(&flagbuf, (size)n);
        }
        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;
            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;
            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;
            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
    
        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(
        }
    
        MemCopy(dst, src, item_size);
        return true;
    }
            }
        } 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;
        }
                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 * vec_aligned_size(vec, item_size));
        } else {
            if (vec->copy_deinit) {
    
        if (removed_data) {
            MemCopy(removed_data, vec_ptr_at(vec, start, item_size), count * vec_aligned_size(vec, item_size));
        } else {
            if (vec->copy_deinit) {
        }
    
        MemCopy(out->data, cstr, len);
        out->data[len] = 0;
        out->length    = len;
            }
        } 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);
        }
                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;
            }
            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;
                }
        // 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
            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);
            // 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);
            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);
        }
            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);
    
        // DBI stream
        wr_u32(&sym[8], func_rva - 0x1000);
        wr_u16(&sym[12], 1);
        MemCopy(&sym[14], func_name, name_len + 1);
    
        // SectionHdr stream: one IMAGE_SECTION_HEADER with VA=0x1000.
        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], 0x1000);
        // Test very long strings
        char long_number[100];
        MemCopy(long_number, "12345678901234567890123456789012345678901234567890", 51);
    
        Str  long_str   = StrInitFromZstr(long_number, &alloc);
        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));
    }
            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;
            }
    
        // --- 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(&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;
        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);
    }
Last updated on