Skip to content

IterDataAt

Description

Pointer to the element at absolute index idx in the iterator’s backing region. Unlike IterPos, this is index-addressed (no dependency on pos / direction) and is well-defined at idx == length (returns the one-past-end pointer, the standard C idiom for a half-open upper bound). Use when you need to address a remembered position – e.g. the cursor saved before a parse attempt – without going through the cursor.

Usage example (Cross-references)

Usage examples (Cross-references)
        // 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;
        if (IterRemainingLength(cur) < out->std_opcode_lengths_count)
            return false;
        out->standard_opcode_lengths = IterDataAt(cur, IterIndex(cur));
        // Must-precondition: the `IterRemainingLength < count` guard above
        // proves the cursor has at least `count` bytes left in the buffer.
        // proves the cursor has at least `count` bytes left in the buffer.
        IterMustMove(cur, (i64)out->std_opcode_lengths_count);
        out->strings_start = IterDataAt(cur, IterIndex(cur));
        return true;
    }
    // start of the line number program body.
    static bool skip_line_program_tables(BufIter *cur) {
        while (IterIndex(cur) < IterLength(cur) && *IterDataAt(cur, IterIndex(cur)) != 0) {
            if (!BufReadZstr(cur))
                return false;
            IterMustNext(cur); // empty terminator
    
        while (IterIndex(cur) < IterLength(cur) && *IterDataAt(cur, IterIndex(cur)) != 0) {
            if (!BufReadZstr(cur))
                return false;
    static bool collect_cu_strings(BufIter cur, Str *pool, CuStrings *cs) {
        // include_directories
        while (IterIndex(&cur) < IterLength(&cur) && *IterDataAt(&cur, IterIndex(&cur)) != 0) {
            Zstr dir = BufReadZstr(&cur);
            if (!dir)
    
        // file_names
        while (IterIndex(&cur) < IterLength(&cur) && *IterDataAt(&cur, IterIndex(&cur)) != 0) {
            Zstr name = BufReadZstr(&cur);
            if (!name)
        lnp_reset(&st, hdr->default_is_stmt);
    
        while (IterDataAt(&cur, IterIndex(&cur)) < prog_end) {
            u8 op = 0;
            if (!BufReadU8(&cur, &op))
                if (!BufReadULeb128(&cur, &length))
                    return false;
                if (length == 0 || (u64)(prog_end - IterDataAt(&cur, IterIndex(&cur))) < length)
                    return false;
                const u8 *body_end = IterDataAt(&cur, IterIndex(&cur)) + length;
                if (length == 0 || (u64)(prog_end - IterDataAt(&cur, IterIndex(&cur))) < length)
                    return false;
                const u8 *body_end = IterDataAt(&cur, IterIndex(&cur)) + length;
                u8        sub_op   = 0;
                if (!BufReadU8(&cur, &sub_op))
                    case DW_LNE_SET_ADDRESS :
                        // operand size = remaining body bytes; on x86-64 always 8.
                        if (body_end - IterDataAt(&cur, IterIndex(&cur)) == 8) {
                            if (!BufReadU64LE(&cur, &st.address))
                                return false;
                            if (!BufReadU64LE(&cur, &st.address))
                                return false;
                        } else if (body_end - IterDataAt(&cur, IterIndex(&cur)) == 4) {
                            u32 a32 = 0;
                            if (!BufReadU32LE(&cur, &a32))
                // above proved `length <= prog_end - here`, and switch arms
                // only consume bytes within the body. Jump to body_end.
                IterMustMove(&cur, (i64)((size)(body_end - IterDataAt(&cur, 0)) - IterIndex(&cur)));
            } else if (op < hdr->opcode_base) {
                // Standard opcode
        bool ok = true;
        while (IterRemainingLength(&section_cur) > 0) {
            const u8 *unit_start  = IterDataAt(&section_cur, IterIndex(&section_cur));
            u32       unit_length = 0;
            BufIter   peek        = section_cur;
            // String/program iters cover the bytes from `hdr.strings_start`
            // up to the end of this CU.
            size    strings_start_pos = (size)(hdr.strings_start - IterDataAt(&section_cur, 0));
            BufIter str_cur           = BufIterFromMemory(IterDataAt(&section_cur, 0), unit_end_pos);
            // strings_start_pos lies within `[0, unit_end_pos]` by construction
            // up to the end of this CU.
            size    strings_start_pos = (size)(hdr.strings_start - IterDataAt(&section_cur, 0));
            BufIter str_cur           = BufIterFromMemory(IterDataAt(&section_cur, 0), unit_end_pos);
            // strings_start_pos lies within `[0, unit_end_pos]` by construction
            // -- `hdr.strings_start` was assigned from inside this section's
    
            // Skip past the tables to find the program body start.
            BufIter prog_anchor = BufIterFromMemory(IterDataAt(&section_cur, 0), unit_end_pos);
            // Must-precondition: same bounds proof as `str_cur` above --
            // `strings_start_pos` is inside `[0, unit_end_pos]` by header
            // info_cur position up to unit_end_pos).
            BufIter die_cur =
                BufIterFromMemory(IterDataAt(&info_cur, IterIndex(&info_cur)), unit_end_pos - IterIndex(&info_cur));
            if (!walk_cu_dies(die_cur, &abbrevs, addr_size, str_bytes, str_size, &out->string_pool, &pending)) {
                abbrev_table_deinit(&abbrevs);
                    continue;
                }
                Zstr name = (Zstr)IterDataAt(&body, IterIndex(&body));
    
                (void)flags; // permissive: we don't filter by FUNCTION bit;
        }
    
        out->initial_instructions      = IterDataAt(body, IterIndex(body));
        out->initial_instructions_size = IterRemainingLength(body);
        return true;
        u64 pc_begin = 0;
        {
            u64 here = eh_byte_vaddr(section_data, section_addr, IterDataAt(body, IterIndex(body)));
            if (!decode_eh_ptr(body, cie->fde_pointer_encoding, here, &pc_begin))
                return false;
        u64 pc_range  = 0;
        {
            u64 here = eh_byte_vaddr(section_data, section_addr, IterDataAt(body, IterIndex(body)));
            if (!decode_eh_ptr(body, range_enc, here, &pc_range))
                return false;
        }
    
        out->instructions      = IterDataAt(body, IterIndex(body));
        out->instructions_size = IterRemainingLength(body);
        return true;
        BufIter section_cur = BufIterFromMemory(section_data, eh->size);
        while (IterRemainingLength(&section_cur) > 0) {
            const u8 *rec_start = IterDataAt(&section_cur, IterIndex(&section_cur));
            u32       length32  = 0;
            if (!BufReadU32LE(&section_cur, &length32))
                // Body iter starts just after the id field (since parse_cie
                // doesn't re-read id) and spans the remainder of the record.
                BufIter body = BufIterFromMemory(IterDataAt(&section_cur, IterIndex(&section_cur)), length32 - 4);
                if (parse_cie(&body, cie_offset, &cie)) {
                    if (!VecPushBackR(&out->cies, cie)) {
                u64      cie_offset = id_field_off - (u64)id;
                DwarfFde fde;
                BufIter  body = BufIterFromMemory(IterDataAt(&section_cur, IterIndex(&section_cur)), length32 - 4);
                if (parse_fde(&body, rec_start, cie_offset, out, section_data, eh->addr, &fde)) {
                    if (!VecPushBackR(&out->fdes, fde)) {
        u64       label_idx = 0;
        while (cur < IterLength(it)) {
            u8 b = *IterDataAt(it, cur);
            if (b == 0) {
                ++cur;
                    return false;
                }
                u16 ptr = (u16)(((b & 0x3Fu) << 8) | *IterDataAt(it, cur + 1));
                if (!jumped) {
                    // First jump: linear cursor advances past the 2-byte
            }
            for (u64 i = 0; i < label_len; ++i) {
                StrPushBackR(out_name, (char)*IterDataAt(it, cur + 1 + i));
            }
            name_len += label_len;
    
        // Stash raw rdata.
        if (!BufPushBytes(&rec->rdata, IterDataAt(it, rdata_start), rdlength)) {
            return false;
        }
                }
                for (u64 i = 0; i < 4; ++i) {
                    rec->ipv4[i] = *IterDataAt(it, rdata_start + i);
                }
                break;
                }
                for (u64 i = 0; i < 16; ++i) {
                    rec->ipv6[i] = *IterDataAt(it, rdata_start + i);
                }
                break;
        ctx->num_sections = num_sec;
        ctx->opt_hdr_size = size_opt;
        *out_opt_offset   = (u64)(IterDataAt(&c, IterIndex(&c)) - BufData(&ctx->out->data));
        return true;
    }
            // 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))
                continue;
            // Verify the trailing path is NUL-terminated inside the record.
            const u8 *path_start = IterDataAt(&cv_cur, IterIndex(&cv_cur));
            const u8 *region_end = IterDataAt(&cv_cur, IterLength(&cv_cur));
            bool      terminated = false;
            // Verify the trailing path is NUL-terminated inside the record.
            const u8 *path_start = IterDataAt(&cv_cur, IterIndex(&cv_cur));
            const u8 *region_end = IterDataAt(&cv_cur, IterLength(&cv_cur));
            bool      terminated = false;
            for (const u8 *p = path_start; p < region_end; ++p) {
    /// TAGS: StrIter, Position, Alias
    ///
    #define StrIterDataAt(mi, idx) IterDataAt((mi), (idx))
    
    // ---------------------------------------------------------------------------
Last updated on