示例#1
0
文件: loader.c 项目: gregsimon/ftk
static int
yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
{
    yaml_event_t event;
    yaml_node_t node;
    struct {
        yaml_node_item_t *start;
        yaml_node_item_t *end;
        yaml_node_item_t *top;
    } items = { NULL, NULL, NULL };
    int index, item_index;
    yaml_char_t *tag = first_event->data.sequence_start.tag;

    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    if (!tag || strcmp((char *)tag, "!") == 0) {
        yaml_free(tag);
        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
        if (!tag) goto error;
    }

    if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;

    SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
            first_event->data.sequence_start.style,
            first_event->start_mark, first_event->end_mark);

    if (!PUSH(parser, parser->document->nodes, node)) goto error;

    index = (int)(parser->document->nodes.top - parser->document->nodes.start);

    if (!yaml_parser_register_anchor(parser, index,
                first_event->data.sequence_start.anchor)) return 0;

    if (!yaml_parser_parse(parser, &event)) return 0;

    while (event.type != YAML_SEQUENCE_END_EVENT) {
        if (!STACK_LIMIT(parser,
                    parser->document->nodes.start[index-1].data.sequence.items,
                    INT_MAX-1)) return 0;
        item_index = yaml_parser_load_node(parser, &event);
        if (!item_index) return 0;
        if (!PUSH(parser,
                    parser->document->nodes.start[index-1].data.sequence.items,
                    item_index)) return 0;
        if (!yaml_parser_parse(parser, &event)) return 0;
    }

    parser->document->nodes.start[index-1].end_mark = event.end_mark;

    return index;

error:
    yaml_free(tag);
    yaml_free(first_event->data.sequence_start.anchor);
    return 0;
}
示例#2
0
文件: loader.c 项目: gregsimon/ftk
static int
yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
{
    yaml_node_t node;
    int index;
    yaml_char_t *tag = first_event->data.scalar.tag;

    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    if (!tag || strcmp((char *)tag, "!") == 0) {
        yaml_free(tag);
        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
        if (!tag) goto error;
    }

    SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
            first_event->data.scalar.length, first_event->data.scalar.style,
            first_event->start_mark, first_event->end_mark);

    if (!PUSH(parser, parser->document->nodes, node)) goto error;

    index = (int)(parser->document->nodes.top - parser->document->nodes.start);

    if (!yaml_parser_register_anchor(parser, index,
                first_event->data.scalar.anchor)) return 0;

    return index;

error:
    yaml_free(tag);
    yaml_free(first_event->data.scalar.anchor);
    yaml_free(first_event->data.scalar.value);
    return 0;
}
示例#3
0
文件: loader.c 项目: gregsimon/ftk
static int
yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
{
    yaml_event_t event;
    yaml_node_t node;
    struct {
        yaml_node_pair_t *start;
        yaml_node_pair_t *end;
        yaml_node_pair_t *top;
    } pairs = { NULL, NULL, NULL };
    int index;
    yaml_node_pair_t pair;
    yaml_char_t *tag = first_event->data.mapping_start.tag;

    if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;

    if (!tag || strcmp((char *)tag, "!") == 0) {
        yaml_free(tag);
        tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
        if (!tag) goto error;
    }

    if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;

    MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
            first_event->data.mapping_start.style,
            first_event->start_mark, first_event->end_mark);

    if (!PUSH(parser, parser->document->nodes, node)) goto error;

    index = (int)(parser->document->nodes.top - parser->document->nodes.start);

    if (!yaml_parser_register_anchor(parser, index,
                first_event->data.mapping_start.anchor)) return 0;

    if (!yaml_parser_parse(parser, &event)) return 0;

    while (event.type != YAML_MAPPING_END_EVENT) {
        if (!STACK_LIMIT(parser,
                    parser->document->nodes.start[index-1].data.mapping.pairs,
                    INT_MAX-1)) return 0;
        pair.key = yaml_parser_load_node(parser, &event);
        if (!pair.key) return 0;
        if (!yaml_parser_parse(parser, &event)) return 0;
        pair.value = yaml_parser_load_node(parser, &event);
        if (!pair.value) return 0;
        if (!PUSH(parser,
                    parser->document->nodes.start[index-1].data.mapping.pairs,
                    pair)) return 0;
        if (!yaml_parser_parse(parser, &event)) return 0;
    }

    parser->document->nodes.start[index-1].end_mark = event.end_mark;

    return index;

error:
    yaml_free(tag);
    yaml_free(first_event->data.mapping_start.anchor);
    return 0;
}
/* Unwind to previous to frame.  Returns 0 if successful, negative
 * number in case of an error. */
int 
unwind(struct unwind_frame_info *frame, int is_ehframe)
{
#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
	const u32 *fde = NULL, *cie = NULL;
	const u8 *ptr = NULL, *end = NULL;
	unsigned long startLoc = 0, endLoc = 0, cfa;
	unsigned i;
	signed ptrType = -1;
	uleb128_t retAddrReg = 0;
//	struct unwind_table *table;
	void *unwind_table;
	struct local_unwind_table *table;
	struct unwind_state state;
	u64 reg_ptr = 0;


	if (UNW_PC(frame) == 0)
		return -EINVAL;

	if ((table = find_table(UNW_PC(frame)))) {
//		unsigned long tableSize = unwind_table_size;
		unsigned long tableSize = table->size;

		unwind_table = table->address;

		for (fde = unwind_table;
		     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
		     tableSize -= sizeof(*fde) + *fde,
		     fde += 1 + *fde / sizeof(*fde)) {
			if (!*fde || (*fde & (sizeof(*fde) - 1)))
				break;
			if (is_ehframe && !fde[1])
				continue; /* this is a CIE */
			else if (fde[1] == 0xffffffff)
				continue; /* this is a CIE */
			if ((fde[1] & (sizeof(*fde) - 1))
			    || fde[1] > (unsigned long)(fde + 1)
			                - (unsigned long)unwind_table)
				continue; /* this is not a valid FDE */
			if (is_ehframe)
				cie = fde + 1 - fde[1] / sizeof(*fde);
			else
				cie = unwind_table + fde[1];
			if (*cie <= sizeof(*cie) + 4
			    || *cie >= fde[1] - sizeof(*fde)
			    || (*cie & (sizeof(*cie) - 1))
			    || (cie[1] != 0xffffffff && cie[1])
			    || (ptrType = fde_pointer_type(cie)) < 0) {
				cie = NULL; /* this is not a (valid) CIE */
				continue;
			}
			ptr = (const u8 *)(fde + 2);
			startLoc = read_pointer(&ptr,
			                        (const u8 *)(fde + 1) + *fde,
			                        ptrType);
			endLoc = startLoc
			         + read_pointer(&ptr,
			                        (const u8 *)(fde + 1) + *fde,
			                        ptrType & DW_EH_PE_indirect
			                        ? ptrType
			                        : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
			if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
				break;
			cie = NULL;
		}
	}
	if (cie != NULL) {
		memset(&state, 0, sizeof(state));
		state.cieEnd = ptr; /* keep here temporarily */
		ptr = (const u8 *)(cie + 2);
		end = (const u8 *)(cie + 1) + *cie;
		if ((state.version = *ptr) != 1)
			cie = NULL; /* unsupported version */
		else if (*++ptr) {
			/* check if augmentation size is first (and thus present) */
			if (*ptr == 'z') {
				/* check for ignorable (or already handled)
				 * nul-terminated augmentation string */
				while (++ptr < end && *ptr)
					if (strchr("LPR", *ptr) == NULL)
						break;
			}
			if (ptr >= end || *ptr)
				cie = NULL;
		}
		++ptr;
	}
	if (cie != NULL) {
		/* get code aligment factor */
		state.codeAlign = get_uleb128(&ptr, end);
		/* get data aligment factor */
		state.dataAlign = get_sleb128(&ptr, end);
		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
			cie = NULL;
		else {
			retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
			/* skip augmentation */
			if (((const char *)(cie + 2))[1] == 'z')
				ptr += get_uleb128(&ptr, end);
			if (ptr > end
			   || retAddrReg >= ARRAY_SIZE(reg_info)
			   || REG_INVALID(retAddrReg)
			   || reg_info[retAddrReg].width != sizeof(unsigned long))
				cie = NULL;
		}
	}
	if (cie != NULL) {
		state.cieStart = ptr;
		ptr = state.cieEnd;
		state.cieEnd = end;
		end = (const u8 *)(fde + 1) + *fde;
		/* skip augmentation */
		if (((const char *)(cie + 2))[1] == 'z') {
			uleb128_t augSize = get_uleb128(&ptr, end);

			if ((ptr += augSize) > end)
				fde = NULL;
		}
	}
	if (cie == NULL || fde == NULL)
		return -ENXIO;

	state.org = startLoc;
	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
	/* process instructions */
	if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
	   || state.loc > endLoc
	   || state.regs[retAddrReg].where == Nowhere
	   || state.cfa.reg >= ARRAY_SIZE(reg_info)
	   || reg_info[state.cfa.reg].width != sizeof(unsigned long)
	   || state.cfa.offs % sizeof(unsigned long)) {
		return -EIO;
		}
	/* update frame */
	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
	startLoc = min((unsigned long)UNW_SP(frame), cfa);
	endLoc = max((unsigned long)UNW_SP(frame), cfa);
	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
		startLoc = min(STACK_LIMIT(cfa), cfa);
		endLoc = max(STACK_LIMIT(cfa), cfa);
	}
#ifndef CONFIG_64BIT
# define CASES CASE(8); CASE(16); CASE(32)
#else
# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
#endif
	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
		if (REG_INVALID(i)) {
			if (state.regs[i].where == Nowhere)
				continue;
			return -EIO;
		}
		switch(state.regs[i].where) {
		default:
			break;
		case Register:
			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
			   || REG_INVALID(state.regs[i].value)
			   || reg_info[i].width > reg_info[state.regs[i].value].width){
				return -EIO;
	}
			switch(reg_info[state.regs[i].value].width) {
#define CASE(n) \
			case sizeof(u##n): \
				state.regs[i].value = FRAME_REG(state.regs[i].value, \
				                                const u##n); \
				break
			CASES;
#undef CASE
			default:
				return -EIO;
			}
			break;
		}
	}
	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
		if (REG_INVALID(i))
			continue;
		switch(state.regs[i].where) {
		case Nowhere:
			if (reg_info[i].width != sizeof(UNW_SP(frame))
			   || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
			      != &UNW_SP(frame))
				continue;
			UNW_SP(frame) = cfa;
			break;
		case Register:
			switch(reg_info[i].width) {
#define CASE(n) case sizeof(u##n): \
				FRAME_REG(i, u##n) = state.regs[i].value; \
				break
			CASES;
#undef CASE
			default:
				return -EIO;
			}
			break;
		case Value:
			if (reg_info[i].width != sizeof(unsigned long)){
				return -EIO;}
			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
			                                    * state.dataAlign;
			break;
		case Memory: {
				unsigned long addr = cfa + state.regs[i].value
				                           * state.dataAlign;
				if ((state.regs[i].value * state.dataAlign)
				    % sizeof(unsigned long)
				    || addr < startLoc
				    || addr + sizeof(unsigned long) < addr
				    || addr + sizeof(unsigned long) > endLoc){
					return -EIO;}
				switch(reg_info[i].width) {
#define CASE(n)     case sizeof(u##n): \
					readmem(addr, KVADDR, &reg_ptr,sizeof(u##n), "register", RETURN_ON_ERROR|QUIET); \
					FRAME_REG(i, u##n) = (u##n)reg_ptr;\
					break
				CASES;
#undef CASE
				default:
					return -EIO;
				}
			}
			break;
		}
	}
	return 0;
#undef CASES
#undef FRAME_REG
}