Пример #1
0
//! get parameter 
var* sci_bin2int::get(int param)
{
 var* p_var_ivec = new var_ivec;	// create var_ivec;	
 ivec &iv = (dynamic_cast<var_ivec *>(p_var_ivec))->v; // alias to vector	

 var* p_var_bvec = new var_bvec;	// create var_bvec;	
 bvec &bv = (dynamic_cast<var_bvec *>(p_var_bvec))->v; // alias to vector	

	switch (param)
	{
    case SCI_SIZE:
    case SCI_SYMBOL_SIZE:
  		iv.set_length(1);
		iv[0] = get_symbol_size();
		return(p_var_ivec);

	case SCI_MSB_FLAG:
		bv.set_length(1);
		bv[0] = get_msb_flag();
		return (p_var_bvec);

	case SCI_OUTPUT:
		iv.set_length(1);
		iv[0] = get_output();					
		return(p_var_ivec);
	default:
		throw sci_exception ("sci_bin2int::get - unknown param");			
	}	     
};
Пример #2
0
static void read_field(Context * ctx, const Symbol * sym, ContextAddress base, ContextAddress * value) {
    LocationInfo * loc_info = NULL;
    LocationExpressionState * state = NULL;
    uint64_t args[1];
    void * buf = NULL;
    size_t size = 0;
    size_t i;

    args[0] = base;
    if (get_location_info(sym, &loc_info) < 0) exception(errno);
    if (loc_info->args_cnt != 1) str_exception(ERR_OTHER, "Wrong object kind");
    state = evaluate_location_expression(ctx, NULL,
                                         loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, 1);
    if (state->pieces_cnt > 0) {
        read_location_pieces(state->ctx, state->stack_frame,
                             state->pieces, state->pieces_cnt, loc_info->big_endian, &buf, &size);
    }
    else {
        ContextAddress sym_size = 0;
        if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid location expression");
        if (get_symbol_size(sym, &sym_size) < 0) exception(errno);
        size = (size_t)sym_size;
        buf = tmp_alloc(size);
        if (context_read_mem(state->ctx, (ContextAddress)state->stk[0], buf, size) < 0) exception(errno);
    }
    *value = 0;
    for (i = 0; i < size && i < sizeof(ContextAddress); i++) {
        *value = *value << 8;
        *value |= ((uint8_t *)buf)[loc_info->big_endian ? i : size - i - 1];
    }
}
Пример #3
0
//! get parameter 
var* sci_bert::get(int param)
{
 var* p_var_ivec = new var_ivec;	// create var_ivec;	
 ivec &iv = (dynamic_cast<var_ivec *>(p_var_ivec))->v; // alias to vector	

 var* p_var_bvec = new var_bvec;	// create var_vec;	
 bvec &bv = (dynamic_cast<var_bvec *>(p_var_bvec))->v; // alias to bvect	

	switch (param)
	{
	case SCI_SIZE:
    case SCI_LENGTH:
		iv.set_length(1);
  		iv[0] = get_length();
		return(p_var_ivec);
	
	case SCI_STATE:
		bv = get_state();
		return(p_var_bvec);
	
	case SCI_SYMBOL_SIZE:
		iv.set_length(1);
 		iv[0] = get_symbol_size();
		return(p_var_ivec);
	
	case SCI_THRESHOLD:
 		iv = get_threshold();
		return(p_var_ivec);
	
	case SCI_BER_CNT:		
		iv = get_ber_cnt();
		return(p_var_ivec);
	
	case SCI_BIT_CNT:		
		iv = get_bit_cnt();
		return(p_var_ivec);
	
	case SCI_METRICS:
		iv.set_length(1);
		iv[0] = get_metrics();
		return(p_var_ivec);
	
	case SCI_FSM:		
		iv.set_length(1);
		iv[0] = get_fsm();
		return(p_var_ivec);
	
	case SCI_OUTPUT:
		iv.set_length(1);
		iv[0] = get_output();
		return(p_var_ivec);

	default:
		throw sci_exception ("sci_bert::get - unknown param", param);			
	}	     
};
Пример #4
0
int get_symbol_size(const Symbol * sym, ContextAddress * size) {
    uint64_t res = 0;
    DWORD tag = 0;

    assert(sym->magic == SYMBOL_MAGIC);
    if (sym->base) {
        if (sym->length > 0) {
            if (get_symbol_size(sym->base, size)) return -1;
            *size *= sym->length;
        }
        else {
            *size = sizeof(void *);
        }
        return 0;
    }
    if (sym->info) {
        *size = sym->info->size;
        return 0;
    }
    if (sym->module == 0) {
        errno = set_errno(ERR_OTHER, "Debug info not available");
        return -1;
    }
    if (sym->sym_class == SYM_CLASS_REFERENCE || sym->sym_class == SYM_CLASS_FUNCTION) {
        SYMBOL_INFO * info = NULL;
        if (get_sym_info(sym, sym->index, &info) < 0) return -1;
        res = info->Size;
    }
    else {
        Symbol type = *sym;
        if (get_type_tag(&type, &tag)) return -1;
        if (get_type_info(&type, TI_GET_LENGTH, &res) < 0) return -1;
    }

    *size = (ContextAddress)res;
    return 0;
}
Пример #5
0
int get_symbol_name(const Symbol * sym, char ** name) {
    WCHAR * ptr = NULL;

    assert(sym->magic == SYMBOL_MAGIC);
    if (sym->base) {
        *name = NULL;
        return 0;
    }
    if (sym->info) {
        *name = sym->info->name;
        return 0;
    }
    *name = NULL;
    if (get_type_info(sym, TI_GET_SYMNAME, &ptr) < 0) ptr = NULL;
    if (ptr != NULL && wcscmp(ptr, L"<unnamed-tag>") == 0) ptr = NULL;
    if (ptr != NULL) {
        int len = 0;
        int err = 0;
        if (tmp_buf == NULL) {
            tmp_buf_size = 256;
            tmp_buf = (char *)loc_alloc(tmp_buf_size);
        }
        for (;;) {
            len = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, tmp_buf, tmp_buf_size - 1, NULL, NULL);
            if (len != 0) break;
            err = GetLastError();
            if (err != ERROR_INSUFFICIENT_BUFFER) {
                set_win32_errno(err);
                return -1;
            }
            tmp_buf_size *= 2;
            tmp_buf = (char *)loc_realloc(tmp_buf, tmp_buf_size);
        }
        HeapFree(GetProcessHeap(), 0, ptr);
        tmp_buf[len] = 0;
        *name = tmp_buf;
    }
    else {
        DWORD tag = 0;
        Symbol type = *sym;
        if (get_type_tag(&type, &tag)) return -1;
        if (tag == SymTagBaseType) {
            ContextAddress size = 0;
            int type_class = 0;
            unsigned char sign = 0;
            unsigned char real = 0;
            const TypeInfo * p = basic_type_info;
            if (get_symbol_size(&type, &size)) return -1;
            if (get_symbol_type_class(&type, &type_class)) return -1;
            if (type_class == TYPE_CLASS_INTEGER) sign = 1;
            else if (type_class == TYPE_CLASS_REAL) real = sign = 1;
            while (p->name != NULL) {
                if (p->size == size && p->sign == sign && p->real == real) {
                    *name = p->name;
                    break;
                }
                p++;
            }
        }
    }
    return 0;
}
Пример #6
0
static void command_get_context(char * token, Channel * c) {
    int err = 0;
    char id[256];
    Symbol sym;

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    if (id2symbol(id, &sym) < 0) err = errno;

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);
    write_errno(&c->out, err);

    if (err == 0) {
        char * name = NULL;
        int type_class = TYPE_CLASS_UNKNOWN;
        Symbol type;
        size_t size = 0;
        void * value = NULL;
        unsigned long length = 0;
        unsigned long offset = 0;
        ContextAddress address = 0;
        int frame = STACK_NO_FRAME; /* TODO: symbol frame */

        write_stream(&c->out, '{');

        json_write_string(&c->out, "ID");
        write_stream(&c->out, ':');
        json_write_string(&c->out, id);
        write_stream(&c->out, ',');

        json_write_string(&c->out, "ExeID");
        write_stream(&c->out, ':');
        json_write_string(&c->out, container_id(sym.ctx));
        write_stream(&c->out, ',');

        if (get_symbol_name(&sym, &name) == 0 && name != NULL) {
            json_write_string(&c->out, "Name");
            write_stream(&c->out, ':');
            json_write_string(&c->out, name);
            write_stream(&c->out, ',');
            loc_free(name);
        }

        if (get_symbol_type_class(&sym, &type_class) == 0 && type_class != TYPE_CLASS_UNKNOWN) {
            json_write_string(&c->out, "TypeClass");
            write_stream(&c->out, ':');
            json_write_long(&c->out, type_class);
            write_stream(&c->out, ',');
        }

        if (get_symbol_type(&sym, &type) == 0) {
            json_write_string(&c->out, "TypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(&type));
            write_stream(&c->out, ',');
        }

        if (get_symbol_base_type(&sym, &type) == 0) {
            json_write_string(&c->out, "BaseTypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(&type));
            write_stream(&c->out, ',');
        }

        if (get_symbol_index_type(&sym, &type) == 0) {
            json_write_string(&c->out, "IndexTypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(&type));
            write_stream(&c->out, ',');
        }

        if (get_symbol_size(&sym, frame, &size) == 0) {
            json_write_string(&c->out, "Size");
            write_stream(&c->out, ':');
            json_write_long(&c->out, size);
            write_stream(&c->out, ',');
        }

        if (get_symbol_length(&sym, frame, &length) == 0) {
            json_write_string(&c->out, "Length");
            write_stream(&c->out, ':');
            json_write_long(&c->out, length);
            write_stream(&c->out, ',');
        }

        if (sym.sym_class == SYM_CLASS_REFERENCE) {
            if (get_symbol_offset(&sym, &offset) == 0) {
                json_write_string(&c->out, "Offset");
                write_stream(&c->out, ':');
                json_write_long(&c->out, offset);
                write_stream(&c->out, ',');
            }

            if (get_symbol_address(&sym, frame, &address) == 0) {
                json_write_string(&c->out, "Address");
                write_stream(&c->out, ':');
                json_write_long(&c->out, address);
                write_stream(&c->out, ',');
            }
        }

        if (sym.sym_class == SYM_CLASS_VALUE && get_symbol_value(&sym, &value, &size) == 0) {
            json_write_string(&c->out, "Value");
            write_stream(&c->out, ':');
            json_write_binary(&c->out, value, size);
            write_stream(&c->out, ',');
        }

        json_write_string(&c->out, "Class");
        write_stream(&c->out, ':');
        json_write_long(&c->out, sym.sym_class);

        write_stream(&c->out, '}');
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }

    write_stream(&c->out, MARKER_EOM);
}
Пример #7
0
static void command_get_context_cache_client(void * x) {
    CommandGetContextArgs * args = (CommandGetContextArgs *)x;
    Channel * c = cache_channel();
    int err = 0;
    Symbol * sym = NULL;
    char * owner = NULL;
    char * name = NULL;
    int update_policy = 0;
    int sym_class = SYM_CLASS_UNKNOWN;
    int type_class = TYPE_CLASS_UNKNOWN;
    Symbol * type = NULL;
    Symbol * base = NULL;
    Symbol * index = NULL;
    Symbol * container = NULL;
    int has_size = 0;
    int has_length = 0;
    int has_lower_bound = 0;
    int has_offset = 0;
    int has_address = 0;
    int has_frame = 0;
    int big_endian = 0;
    ContextAddress size = 0;
    ContextAddress length = 0;
    int64_t lower_bound = 0;
    ContextAddress offset = 0;
    ContextAddress address = 0;
    RegisterDefinition * reg = NULL;
    SYM_FLAGS flags = 0;
    void * value = NULL;
    size_t value_size = 0;
    Context * ctx = NULL;
    int frame = STACK_NO_FRAME;
    SymbolProperties props;

    memset(&props, 0, sizeof(props));

    if (id2symbol(args->id, &sym) < 0) err = errno;

    if (err == 0) {
        get_symbol_class(sym, &sym_class);
        get_symbol_update_policy(sym, &owner, &update_policy);
        get_symbol_name(sym, &name);
        get_symbol_type_class(sym, &type_class);
        get_symbol_type(sym, &type);
        get_symbol_base_type(sym, &base);
        get_symbol_index_type(sym, &index);
        get_symbol_container(sym, &container);
        has_frame = get_symbol_frame(sym, &ctx, &frame) == 0;
        has_size = get_symbol_size(sym, &size) == 0;
        if (type_class == TYPE_CLASS_ARRAY) {
            has_length = get_symbol_length(sym, &length) == 0;
            if (has_length) has_lower_bound = get_symbol_lower_bound(sym, &lower_bound) == 0;
        }
        if (sym_class == SYM_CLASS_REFERENCE || sym_class == SYM_CLASS_FUNCTION ||
                sym_class == SYM_CLASS_VALUE || sym_class == SYM_CLASS_TYPE ||
                sym_class == SYM_CLASS_VARIANT_PART) {
            LocationInfo * loc_info = NULL;
            if (has_frame && get_location_info(sym, &loc_info) == 0) {
                LocationExpressionState * state = NULL;
                if (loc_info->args_cnt == 0) {
                    /* Absolute location */
                    state = evaluate_location(ctx, frame, loc_info);
                    if (state != NULL) {
                        if (state->stk_pos == 1) {
                            address = (ContextAddress)state->stk[0];
                            has_address = 1;
                        }
                        if (state->pieces_cnt == 1 && state->pieces->reg != NULL &&
                                state->pieces->reg->size == state->pieces->size) {
                            reg = state->pieces->reg;
                        }
                        if (state->pieces_cnt > 0) {
                            Trap trap;
                            if (set_trap(&trap)) {
                                read_location_pieces(state->ctx, state->stack_frame,
                                    state->pieces, state->pieces_cnt, loc_info->big_endian, &value, &value_size);
                                big_endian = loc_info->big_endian;
                                clear_trap(&trap);
                            }
                        }
                    }
                }
                else if (loc_info->args_cnt == 1) {
                    /* Relative location */
                    state = evaluate_location(ctx, frame, loc_info);
                    if (state != NULL && state->stk_pos == 1) {
                        offset = (ContextAddress)state->stk[0];
                        has_offset = 1;
                    }
                }
            }
        }
        get_symbol_flags(sym, &flags);
        get_symbol_props(sym, &props);
    }

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, err);

    if (err == 0) {

        write_stream(&c->out, '{');

        json_write_string(&c->out, "ID");
        write_stream(&c->out, ':');
        json_write_string(&c->out, args->id);
        write_stream(&c->out, ',');

        if (owner != NULL) {
            json_write_string(&c->out, "OwnerID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, owner);
            write_stream(&c->out, ',');

            json_write_string(&c->out, "UpdatePolicy");
            write_stream(&c->out, ':');
            json_write_long(&c->out, update_policy);
            write_stream(&c->out, ',');
        }

        if (name != NULL) {
            json_write_string(&c->out, "Name");
            write_stream(&c->out, ':');
            json_write_string(&c->out, name);
            write_stream(&c->out, ',');
        }

        if (type_class != TYPE_CLASS_UNKNOWN) {
            json_write_string(&c->out, "TypeClass");
            write_stream(&c->out, ':');
            json_write_long(&c->out, type_class);
            write_stream(&c->out, ',');
        }

        if (type != NULL) {
            json_write_string(&c->out, "TypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(type));
            write_stream(&c->out, ',');
        }

        if (base != NULL) {
            json_write_string(&c->out, "BaseTypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(base));
            write_stream(&c->out, ',');
        }

        if (index != NULL) {
            json_write_string(&c->out, "IndexTypeID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(index));
            write_stream(&c->out, ',');
        }

        if (container != NULL) {
            json_write_string(&c->out, "ContainerID");
            write_stream(&c->out, ':');
            json_write_string(&c->out, symbol2id(container));
            write_stream(&c->out, ',');
        }

        if (has_size) {
            json_write_string(&c->out, "Size");
            write_stream(&c->out, ':');
            json_write_uint64(&c->out, size);
            write_stream(&c->out, ',');
        }

        if (has_length) {
            json_write_string(&c->out, "Length");
            write_stream(&c->out, ':');
            json_write_uint64(&c->out, length);
            write_stream(&c->out, ',');

            if (has_lower_bound) {
                json_write_string(&c->out, "LowerBound");
                write_stream(&c->out, ':');
                json_write_int64(&c->out, lower_bound);
                write_stream(&c->out, ',');

                json_write_string(&c->out, "UpperBound");
                write_stream(&c->out, ':');
                json_write_int64(&c->out, lower_bound + (int64_t)length - 1);
                write_stream(&c->out, ',');
            }
        }

        if (has_offset) {
            json_write_string(&c->out, "Offset");
            write_stream(&c->out, ':');
            json_write_uint64(&c->out, offset);
            write_stream(&c->out, ',');
        }

        if (has_address) {
            json_write_string(&c->out, "Address");
            write_stream(&c->out, ':');
            json_write_uint64(&c->out, address);
            write_stream(&c->out, ',');
        }

        if (reg != NULL && has_frame) {
            json_write_string(&c->out, "Register");
            write_stream(&c->out, ':');
            json_write_string(&c->out, register2id(ctx, frame, reg));
            write_stream(&c->out, ',');
        }

        if (flags) {
            json_write_string(&c->out, "Flags");
            write_stream(&c->out, ':');
            json_write_long(&c->out, flags);
            write_stream(&c->out, ',');
        }

        if (props.binary_scale != 0) {
            json_write_string(&c->out, "BinaryScale");
            write_stream(&c->out, ':');
            json_write_long(&c->out, props.binary_scale);
            write_stream(&c->out, ',');
        }

        if (props.decimal_scale != 0) {
            json_write_string(&c->out, "DecimalScale");
            write_stream(&c->out, ':');
            json_write_long(&c->out, props.decimal_scale);
            write_stream(&c->out, ',');
        }

        if (props.bit_stride != 0) {
            json_write_string(&c->out, "BitStride");
            write_stream(&c->out, ':');
            json_write_ulong(&c->out, props.bit_stride);
            write_stream(&c->out, ',');
        }

        if (props.local_entry_offset != 0) {
            json_write_string(&c->out, "LocalEntryOffset");
            write_stream(&c->out, ':');
            json_write_ulong(&c->out, props.local_entry_offset);
            write_stream(&c->out, ',');
        }

        if (value != NULL) {
            json_write_string(&c->out, "Value");
            write_stream(&c->out, ':');
            json_write_binary(&c->out, value, value_size);
            write_stream(&c->out, ',');

            if (big_endian) {
                json_write_string(&c->out, "BigEndian");
                write_stream(&c->out, ':');
                json_write_boolean(&c->out, 1);
                write_stream(&c->out, ',');
            }
        }

        if (has_frame && frame != STACK_NO_FRAME) {
            json_write_string(&c->out, "Frame");
            write_stream(&c->out, ':');
            json_write_long(&c->out, frame);
            write_stream(&c->out, ',');
        }

        json_write_string(&c->out, "Class");
        write_stream(&c->out, ':');
        json_write_long(&c->out, sym_class);

        write_stream(&c->out, '}');
        write_stream(&c->out, 0);
    }
    else {
        write_stringz(&c->out, "null");
    }

    write_stream(&c->out, MARKER_EOM);
}
Пример #8
0
static void disassemble_cache_client(void * x) {
    DisassembleCmdArgs * args = (DisassembleCmdArgs *)x;

    int error = 0;
    Context * ctx = NULL;
    uint8_t * mem_buf = NULL;
    ContextAddress buf_addr = 0;
    ContextAddress buf_size = 0;
    size_t mem_size = 0;
    ByteArrayOutputStream buf;
    OutputStream * buf_out = create_byte_array_output_stream(&buf);
    Channel * c = cache_channel();
    char * data = NULL;
    size_t size = 0;
    ContextISA isa;

    memset(&isa, 0, sizeof(isa));

    ctx = id2ctx(args->id);
    if (ctx == NULL) error = ERR_INV_CONTEXT;
    else if (ctx->exited) error = ERR_ALREADY_EXITED;

    if (!error) check_all_stopped(ctx);

    if (!error) {
        ContextAddress sym_addr = 0;
        ContextAddress sym_size = 0;
        int sym_addr_ok = 0;
        int sym_size_ok = 0;
#if SERVICE_Symbols
        {
            Symbol * sym = NULL;
            if (find_symbol_by_addr(ctx, STACK_NO_FRAME, args->addr, &sym) == 0) {
                if (get_symbol_address(sym, &sym_addr) == 0) sym_addr_ok = 1;
                if (get_symbol_size(sym, &sym_size) == 0) sym_size_ok = 1;
            }
            if (sym_addr_ok && sym_addr <= args->addr) {
                if (args->addr - sym_addr >= 0x1000) {
                    sym_addr_ok = 0;
                    sym_size_ok = 0;
                }
                else if (sym_size_ok && sym_addr + sym_size > args->addr + args->size) {
                    sym_size = args->addr + args->size - sym_addr;
                }
            }
        }
#endif
#if SERVICE_LineNumbers
        if (!sym_addr_ok || !sym_size_ok) {
            CodeArea * area = NULL;
            address_to_line(ctx, args->addr, args->addr + 1, address_to_line_cb, &area);
            if (area != NULL) {
                sym_addr = area->start_address;
                sym_size = area->end_address - area->start_address;
                sym_addr_ok = 1;
                sym_size_ok = 1;
            }
        }
#endif
        if (sym_addr_ok && sym_size_ok && sym_addr <= args->addr && sym_addr + sym_size > args->addr) {
            buf_addr = sym_addr;
            buf_size = sym_size;
            mem_size = (size_t)sym_size;
        }
        else if (sym_addr_ok && sym_addr < args->addr) {
            if (get_isa(ctx, sym_addr, &isa) < 0) {
                error = errno;
            }
            else {
                buf_addr = sym_addr;
                buf_size = args->addr + args->size - sym_addr;
                if (isa.max_instruction_size > 0) {
                    mem_size = (size_t)(buf_size + isa.max_instruction_size);
                }
                else {
                    mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
                }
            }
        }
        else {
            /* Use default address alignment */
            if (get_isa(ctx, args->addr, &isa) < 0) {
                error = errno;
            }
            else {
                if (isa.alignment > 0) {
                    buf_addr = args->addr & ~(ContextAddress)(isa.alignment - 1);
                }
                else {
                    buf_addr = args->addr & ~(ContextAddress)(DEFAULT_ALIGMENT - 1);
                }
                buf_size = args->addr + args->size - buf_addr;
                if (isa.max_instruction_size > 0) {
                    mem_size = (size_t)(buf_size + isa.max_instruction_size);
                }
                else {
                    mem_size = (size_t)(buf_size + MAX_INSTRUCTION_SIZE);
                }
            }
        }

        if (!error) {
            mem_buf = (uint8_t *)tmp_alloc(mem_size);
            if (context_read_mem(ctx, buf_addr, mem_buf, mem_size) < 0) error = errno;
            if (error) {
#if ENABLE_ExtendedMemoryErrorReports
                MemoryErrorInfo info;
                if (context_get_mem_error_info(&info) == 0 && info.size_valid > 0) {
                    mem_size = info.size_valid;
                    error = 0;
                }
#endif
            }
        }
    }

    if (!error && disassemble_block(
            ctx, buf_out, mem_buf, buf_addr, buf_size,
            mem_size, &isa, args) < 0) error = errno;

    if (get_error_code(error) == ERR_CACHE_MISS) {
        loc_free(buf.mem);
        buf.mem = NULL;
        buf.max = 0;
        buf.pos = 0;
    }

    cache_exit();

    get_byte_array_output_stream_data(&buf, &data, &size);

    if (!is_channel_closed(c)) {
        OutputStream * out = &c->out;
        write_stringz(out, "R");
        write_stringz(out, args->token);
        write_errno(out, error);
        if (size > 0) {
            write_block_stream(out, data, size);
        }
        else {
            write_string(out, "null");
        }
        write_stream(out, 0);
        write_stream(out, MARKER_EOM);
    }

    loc_free(data);
}