예제 #1
0
파일: glue.c 프로젝트: ruedagato/arqui
/*
 * Emit the section preamble, absolute location (if any) and
 * symbol name(s) for intialized data.
 */
static int
emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
{
    char *segname;
    static int in_code = 0;
    static int sectionNr = 0;

    if (sym) {
        // code or data space?
        if (IS_CODE(getSpec(sym->type))) {
            segname = "code";
            in_code = 1;
        } else {
            segname = "idata";
            in_code  = 0;
        }
        dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
        if (SPEC_ABSA(getSpec(sym->type))) {
            // specify address for absolute symbols
            dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
        } // if
        dbuf_printf(oBuf, "\n%s\n", sym->rname);

        addSet(&emitted, sym->rname);
    }
    return (in_code);
}
예제 #2
0
/*
 * Set guest ES, DS, FS, or GS, based on register name and new tss.
 */
static
int set_guest_seg(guest_cpu_handle_t gcpu, seg_reg_t *gdtr, seg_reg_t *ldtr,
		  tss32_t *tss, mon_ia32_segment_registers_t name)
{
	desc_t desc;
	seg_reg_t seg;
	seg_reg_t *dtr;
	uint32_t cpl;
	int r;

	mon_memset(&seg, 0, sizeof(seg));

	if (name == IA32_SEG_ES) {
		seg.selector = (uint16_t)tss->es;
	} else if (name == IA32_SEG_DS) {
		seg.selector = (uint16_t)tss->ds;
	} else if (name == IA32_SEG_FS) {
		seg.selector = (uint16_t)tss->fs;
	} else if (name == IA32_SEG_GS) {
		seg.selector = (uint16_t)tss->gs;
	} else {
		return -1;
	}

	cpl = SELECTOR_RPL(tss->cs);

	dtr = SELECTOR_GDT(seg.selector) ? gdtr : ldtr;

	if (SELECTOR_IDX(seg.selector) == 0) {
		seg.selector = 0;
		seg.ar.bits.null_bit = 1;
		goto set_seg_reg;
	}

	r = copy_from_gva(gcpu,
		(uint64_t)(dtr->base + SELECTOR_IDX(seg.selector)),
		sizeof(desc), (uint64_t)(&desc)
		);

	if (r != 0) {
		force_ring3_ss(gcpu);
		gcpu_inject_ts(gcpu, seg.selector);
		return -1;
	}

	parse_desc(&desc, &seg);

	if ((seg.ar.bits.s_bit == 0) || /* must be non-sys desc */
	    (IS_CODE(seg.ar.bits.type) && !IS_CODE_R(seg.ar.bits.type))) {
		force_ring3_ss(gcpu);
		gcpu_inject_ts(gcpu, seg.selector);
		return -1;
	}

	if (seg.ar.bits.p_bit != 1) {
		/* Must be present. */
		force_ring3_ss(gcpu);
		gcpu_inject_np(gcpu, seg.selector);
		return -1;
	}

	/* If g_bit is set, the unit is 4 KB. */
	if (seg.ar.bits.g_bit == 1) {
		seg.limit = (seg.limit << 12) | 0xfff;
	}

	/* Priv checks. */
	if (IS_CODE(seg.ar.bits.type) && !IS_CODE_CONFORM(seg.ar.bits.type)) {
		uint32_t rpl = (uint32_t)SELECTOR_RPL(seg.selector);

		if ((seg.ar.bits.dpl < cpl) || (seg.ar.bits.dpl < rpl)) {
			force_ring3_ss(gcpu);
			gcpu_inject_ts(gcpu, seg.selector);
			return -1;
		}
	}

set_seg_reg:

	gcpu_set_segment_reg(gcpu, name, seg.selector, seg.base,
		seg.limit, seg.ar.value);

	return 0;
}
예제 #3
0
/*
 * Set guest CS according to new tss.
 */
static
int set_guest_cs(guest_cpu_handle_t gcpu, seg_reg_t *gdtr,
		 seg_reg_t *ldtr, tss32_t *tss)
{
	desc_t desc;
	seg_reg_t cs;
	seg_reg_t *dtr;
	uint32_t cpl;
	int r;

	mon_memset(&cs, 0, sizeof(cs));
	cs.selector = (uint16_t)tss->cs;
	cpl = SELECTOR_RPL(tss->cs);

	if (SELECTOR_IDX(cs.selector) == 0) {
		/* must not be null */
		gcpu_inject_ts(gcpu, cs.selector);
		return -1;
	}

	dtr = SELECTOR_GDT(cs.selector) ? gdtr : ldtr;

	r = copy_from_gva(gcpu,
		(uint64_t)(dtr->base + SELECTOR_IDX(cs.selector)),
		sizeof(desc),
		(uint64_t)(&desc));

	if (r != 0) {
		gcpu_inject_ts(gcpu, cs.selector);
		return -1;
	}

	parse_desc(&desc, &cs);

	if (cs.ar.bits.p_bit != 1) {
		/* must be present */
		gcpu_inject_np(gcpu, cs.selector);
		return -1;
	}

	if ((cs.ar.bits.s_bit == 0) ||          /* must be non-sys desc */
	    !IS_CODE(cs.ar.bits.type)) {        /* must be code */
		gcpu_inject_ts(gcpu, cs.selector);
		return -1;
	}

	/* Priv checks */
	if (IS_CODE_CONFORM(cs.ar.bits.type)) {
		if (cs.ar.bits.dpl > cpl) {
			gcpu_inject_ts(gcpu, cs.selector);
			return -1;
		}
	} else {
		if (cs.ar.bits.dpl != cpl) {
			gcpu_inject_ts(gcpu, cs.selector);
			return -1;
		}
	}

	/* If g_bit is set, the unit is 4 KB. */
	if (cs.ar.bits.g_bit == 1) {
		cs.limit = (cs.limit << 12) | 0xfff;
	}

	if (!IS_ASSESSED(cs.ar.bits.type)) {
		SET_ASSESSED(cs.ar.bits.type);
		SET_ASSESSED(desc.bits.type);

		r = copy_to_gva(gcpu,
			(uint64_t)(dtr->base + (cs.selector & 0xfff8)),
			sizeof(desc),
			(uint64_t)(&desc));

		if (r != 0) {
			gcpu_inject_ts(gcpu, cs.selector);
			return -1;
		}
	}

	cs.ar.bits.null_bit = 0;

	gcpu_set_segment_reg(gcpu, IA32_SEG_CS, cs.selector, cs.base,
		cs.limit, cs.ar.value);

	if (tss->eip > cs.limit) {
		gcpu_inject_ts(gcpu, cs.selector);
		return -1;
	}

	return 0;
}
예제 #4
0
/*
 * Set guest SS according to new tss.
 */
static
int set_guest_ss(guest_cpu_handle_t gcpu, seg_reg_t *gdtr,
		 seg_reg_t *ldtr, tss32_t *tss)
{
	desc_t desc;
	seg_reg_t ss;
	seg_reg_t *dtr;
	uint32_t cpl;
	int r;

	mon_memset(&ss, 0, sizeof(ss));
	ss.selector = (uint16_t)tss->ss;
	cpl = SELECTOR_RPL(tss->cs);

	if (SELECTOR_IDX(ss.selector) == 0) {
		/* must not be null */
		force_ring3_ss(gcpu);
		gcpu_inject_ts(gcpu, ss.selector);
		return -1;
	}

	dtr = SELECTOR_GDT(ss.selector) ? gdtr : ldtr;

	r = copy_from_gva(gcpu,
		(uint64_t)(dtr->base + SELECTOR_IDX(ss.selector)),
		sizeof(desc),
		(uint64_t)(&desc));

	if (r != 0) {
		force_ring3_ss(gcpu);
		gcpu_inject_ts(gcpu, ss.selector);
		return -1;
	}

	parse_desc(&desc, &ss);

	if (ss.ar.bits.p_bit == 0) {
		/* must be present */
		force_ring3_ss(gcpu);
		gcpu_inject_ss(gcpu, ss.selector);
		return -1;
	}

	if ((ss.ar.bits.s_bit == 0) ||          /* must be non-sys desc */
	    IS_CODE(ss.ar.bits.type) ||         /* must not be code */
	    !IS_DATA_RW(ss.ar.bits.type) ||     /* must be data with r/w */
	    (ss.ar.bits.dpl != cpl) ||
	    ((uint32_t)SELECTOR_RPL(ss.selector) != cpl)) {
		force_ring3_ss(gcpu);
		gcpu_inject_ts(gcpu, ss.selector);
		return -1;
	}

	/* If g_bit is set, the unit is 4 KB. */
	if (ss.ar.bits.g_bit == 1) {
		ss.limit = (ss.limit << 12) | 0xfff;
	}

	if (!IS_ASSESSED(ss.ar.bits.type)) {
		SET_ASSESSED(ss.ar.bits.type);
		SET_ASSESSED(desc.bits.type);

		r = copy_to_gva(gcpu,
			(uint64_t)(dtr->base + SELECTOR_IDX(ss.selector)),
			sizeof(desc),
			(uint64_t)(&desc));

		if (r != 0) {
			force_ring3_ss(gcpu);
			gcpu_inject_ts(gcpu, ss.selector);
			return -1;
		}
	}

	gcpu_set_segment_reg(gcpu, IA32_SEG_SS, ss.selector, ss.base,
		ss.limit, ss.ar.value);

	return 0;
}
예제 #5
0
파일: glue.c 프로젝트: ruedagato/arqui
static char *
parseIvalAst (ast *node, int *inCodeSpace) {
#define LEN 4096
    char *buffer = NULL;
    char *left, *right;

    if (IS_AST_VALUE(node)) {
        value *val = AST_VALUE(node);
        symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
        if (inCodeSpace && val->type
                && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
        {
            *inCodeSpace = 1;
        }
        if (inCodeSpace && sym
                && (IS_FUNC(sym->type)
                    || IS_CODE(getSpec(sym->type))))
        {
            *inCodeSpace = 1;
        }

        DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
        if (IS_AST_LIT_VALUE(node)) {
            buffer = Safe_alloc(LEN);
            SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
        } else if (IS_AST_SYM_VALUE(node)) {
            assert ( AST_SYMBOL(node) );
            /*
            printf ("sym %s: ", AST_SYMBOL(node)->rname);
            printTypeChain(AST_SYMBOL(node)->type, stdout);
            printTypeChain(AST_SYMBOL(node)->etype, stdout);
            printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
            */
            buffer = Safe_strdup(AST_SYMBOL(node)->rname);
        } else {
            assert ( !"Invalid values type for initializers in AST." );
        }
    } else if (IS_AST_OP(node)) {
        DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
        switch (node->opval.op) {
        case CAST:
            assert (node->right);
            buffer = parseIvalAst(node->right, inCodeSpace);
            DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
            break;
        case '&':
            assert ( node->left && !node->right );
            buffer = parseIvalAst(node->left, inCodeSpace);
            DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
            break;
        case '+':
            assert (node->left && node->right );
            left = parseIvalAst(node->left, inCodeSpace);
            right = parseIvalAst(node->right, inCodeSpace);
            buffer = Safe_alloc(LEN);
            SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
            DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
            Safe_free(left);
            Safe_free(right);
            break;
        case '[':
            assert ( node->left && node->right );
            assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
            right = parseIvalAst(node->right, inCodeSpace);
            buffer = Safe_alloc(LEN);
            SNPRINTF(buffer, LEN, "(%s + %u * %s)",
                    AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
            Safe_free(right);
            DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
            break;
        default:
            assert ( !"Unhandled operation in initializer." );
            break;
        }
    } else {
        assert ( !"Invalid construct in initializer." );
    }

    return (buffer);
}