Beispiel #1
0
void test_clist(void)
{
    /* CU_ASSERT(NULL == ex_path_normalize(NULL)); */
    int i = 0;
    int test_cnt = 10000;
    clist *list = clist_new();

    CU_ASSERT(0 == clist_len(list));
    for(i = 0; i < test_cnt; ++i) {
        clist_append(list, cobj_int_new(i));
    }

    CU_ASSERT(test_cnt == clist_len(list));
    CU_ASSERT(false == clist_is_empty(list));
    CU_ASSERT(0 == cobj_int_val(clist_at_obj(list, 0)));
    CU_ASSERT(1 == cobj_int_val(clist_at_obj(list, 1)));
    CU_ASSERT(test_cnt - 1 == cobj_int_val(clist_at_obj(list, test_cnt - 1)));

    for(i = 0; i < test_cnt; ++i) {
        void *obj = clist_pop_front(list);
        CU_ASSERT(i == cobj_int_val(obj));
        cobj_free(obj);
    }
    CU_ASSERT(0 == clist_len(list));
    CU_ASSERT(true == clist_is_empty(list));

    for(i = 0; i < test_cnt; ++i) {
        clist_append(list, cobj_int_new(i));
    }
    clist_clear(list);
    CU_ASSERT(0 == clist_len(list));
    for(i = 0; i < test_cnt; ++i) {
        clist_append(list, cobj_int_new(i));
    }

    clist_node *node = NULL;
    void *obj = NULL;
    i = 0;
    clist_foreach_val(list, node, obj) {
        CU_ASSERT(i == cobj_int_val(obj));
        ++i;
    }
Beispiel #2
0
int main(int argc, char *argv[])
{
	struct clist comp_units;
	clist_init(&comp_units);
	char *outfile = "out.rpx";
	_Bool final_link = 0;

	// usage: rpl [-x] [-o <outfile>] <infiles...>
	int opt;
	while((opt = getopt(argc, argv, "o:x")) != -1) {
		switch(opt) {
		case 'o': 
			outfile = optarg;
			break;
		case 'x':
			// this option enables the assumption that this will be the final
			// link operation and absolute jump targets can now be resolved.
			final_link = 1;
			break;
		default:
			{
				printf("usage: %s -o <outfile> <infile> ...\n", argv[0]);
				return -1;
			}
			break;
		}
	}


	struct comp_unit out_u;
	comp_unit_init(&out_u);
	size_t out_text_cap = 0;

	struct clist abs_patch_addrs;
	clist_init(&abs_patch_addrs);

	struct clist rel_patch_addrs;
	clist_init(&rel_patch_addrs);


	for(int i = optind; i < argc; i++) {
		struct comp_unit *u = comp_unit_read(argv[i]);
		if(u == NULL)
			return -1;

		// for each infile:

		// emit its code
		size_t text_start_off = out_u.text_len;

		array_append_bytes(
			&out_u.text, &out_u.text_len, &out_text_cap,
			u->text, u->text_len);

		// collate export locations
		for(struct clnode *i = clist_first(&u->exported);
		    i != clist_end(&u->exported);
		    i = clnode_next(i)) {
			struct name_addr_node *uex = (struct name_addr_node *)i;

			struct name_addr_node *ex =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)),
					uex->name, uex->addr + text_start_off);

			clist_queue(&out_u.exported, &ex->hdr);
		}

		// collate abs-dep locations
		for(struct clnode *i = clist_first(&u->abs_deps);
		    i != clist_end(&u->abs_deps);
		    i = clnode_next(i)) {
			struct name_addr_node *udep = (struct name_addr_node *)i;

			struct name_addr_node *dep =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)),
					udep->name, udep->addr + text_start_off);

			clist_queue(&abs_patch_addrs, &dep->hdr);
		}

		// collate rel-dep locations
		for(struct clnode *i = clist_first(&u->rel_deps);
		    i != clist_end(&u->rel_deps);
		    i = clnode_next(i)) {
			struct name_addr_node *udep = (struct name_addr_node *)i;

			struct name_addr_node *dep =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)),
					udep->name, udep->addr + text_start_off);

			clist_queue(&rel_patch_addrs, &dep->hdr);
		}

		// collate foreign locations
		for(struct clnode *i = clist_first(&u->foreign_deps);
		    i != clist_end(&u->foreign_deps);
		    i = clnode_next(i)) {
			struct name_addr_node *ufdep = (struct name_addr_node *)i;

			struct name_addr_node *fdep =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)),
					ufdep->name, ufdep->addr + text_start_off);

			clist_queue(&out_u.foreign_deps, &fdep->hdr);
		}
	}

	//
	// fixup deps if they can be resolved
	//

	while(! clist_is_empty(&rel_patch_addrs)) {
		struct clnode *i = clnode_remove(clist_first(&rel_patch_addrs));
		struct name_addr_node *patch_dst = (struct name_addr_node *)i;

		struct name_addr_node *patch_src =
			name_addr_node_find(&out_u.exported, patch_dst->name);

		if(! patch_src) { // external dep
			clist_queue(&out_u.rel_deps, &patch_dst->hdr);
		} else {
			jump_t jump_target = patch_src->addr;
			jump_t jump_source = patch_dst->addr;
			jump_t jump = jump_target - jump_source;
			jump = htobe32(jump);
			memcpy(out_u.text + patch_dst->addr, &jump, sizeof(jump));

			free(i);
		}
	}

	if(final_link) {
		while(! clist_is_empty(&abs_patch_addrs)) {
			struct clnode *i = clnode_remove(clist_first(&abs_patch_addrs));
			struct name_addr_node *patch_dst = (struct name_addr_node *)i;
	
			struct name_addr_node *patch_src =
				name_addr_node_find(&out_u.exported, patch_dst->name);
	
			if(! patch_src) { // external dep
				fprintf(stderr, "error: unresolved absolute link target: %s\n", 
				        patch_dst->name);
			} else {
				jump_t jump = patch_src->addr;
				jump = htobe32(jump);
				memcpy(out_u.text + patch_dst->addr, &jump, sizeof(jump));
	
				free(i);
			}
		}
	} else {
		while(! clist_is_empty(&abs_patch_addrs)) {
			struct clnode *i = clnode_remove(clist_first(&abs_patch_addrs));
			struct name_addr_node *patch_dst = (struct name_addr_node *)i;

			clist_queue(&out_u.abs_deps, &patch_dst->hdr);
		}
	}

	//
	// emit object file
	//

	comp_unit_write(&out_u, outfile);

	return 0;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
	if(argc != 3) {
		printf("usage: %s <infile> <outfile>\n", argv[0]);
		return -1;
	}
	char *infile = argv[1];
	char *outfile = argv[2];

	FILE *instream;
	if(strcmp(infile, "--") == 0)
		instream = stdin;
	else
		instream = fopen(infile, "r");
	if(! instream) {
		perror("fopen()");
		fprintf(stderr, "file %s\n", infile);
		return -1;
	}

	FILE *outstream;
	if(strcmp(outfile, "--") == 0)
		outstream = stdout;
	else
		outstream = fopen(outfile, "w");
	if(! outstream) {
		perror("fopen()");
		fprintf(stderr, "file %s\n", outfile);
		return -1;
	}

	// tokenize
	struct clist words;
	clist_init(&words);
	read_words_from_FILE(instream, &words, ';');


	struct comp_unit cu;
	size_t out_text_cap = 0;
	comp_unit_init(&cu);

	// pass 1:
	// identify and store all labels and addressess
	// identify exported labels
	// identify patch locations
	// generate code and immediates

	struct clist label_addrs;
	clist_init(&label_addrs);

	struct clist abs_patch_addrs;
	clist_init(&abs_patch_addrs);

	struct clist rel_patch_addrs;
	clist_init(&rel_patch_addrs);

	for(struct clnode *i = clist_first(&words);
	    i != clist_end(&words);
	    i = clnode_next(i)) {

		struct word_node *wn = (struct word_node *)i;
		char *directive = wn->word;
		if(*directive != '.') {
			printf("expected directive: %s\n", directive);
			return -1;
		}
		directive++;

		i = clnode_next(i);
		if(i == clist_end(&words)) {
			printf("all directives require an argument\n");
			return -1;
		}
		struct word_node *wn_arg = (struct word_node *)i;
		char *arg = wn_arg->word;
		if(*arg == '.') {
			printf("expected arg: %s\n", arg);
			return -1;
		}

		struct name_addr_node *n_a_node;
		char *endp;
		unsigned long long arg_uval;
		long long arg_sval;

		if(strcmp(directive, "label") == 0) {

			n_a_node =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);

			clist_queue(&label_addrs, &n_a_node->hdr);

		} else if(strcmp(directive, "export") == 0) {

			n_a_node=
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);

			clist_queue(&label_addrs, &n_a_node->hdr);

			n_a_node =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);

			clist_queue(&cu.exported, &n_a_node->hdr);

		} else if(strcmp(directive, "data_u1") == 0) {

			arg_uval = strtoull(arg, &endp, 0);
			if(*endp) {
				printf("parse u1 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_uval > 0xFFULL) {
				printf("parse u1 immedate too large %s\n", arg);
				return 0;
			}

			uint8_t v = arg_uval;

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, &v, sizeof(v));

		} else if(strcmp(directive, "data_u2") == 0) {

			arg_uval = strtoull(arg, &endp, 0);
			if(*endp) {
				printf("parse u2 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_uval > 0xFFFFULL) {
				printf("parse u2 immedate too large %s\n", arg);
				return 0;
			}

			uint16_t v = arg_uval;
			v = htobe16(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_u4") == 0) {

			arg_uval = strtoull(arg, &endp, 0);
			if(*endp) {
				printf("parse u4 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_uval > 0xFFFFFFFFULL) {
				printf("parse u4 immedate too large %s\n", arg);
				return 0;
			}

			uint32_t v = arg_uval;
			v = htobe32(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_u8") == 0) {

			arg_uval = strtoull(arg, &endp, 0);
			if(*endp) {
				printf("parse u8 immedate error for %s\n", arg);
				return 0;
			}

			uint64_t v = arg_uval;
			v = htobe64(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_s1") == 0) {

			arg_sval = strtoll(arg, &endp, 0);
			if(*endp) {
				printf("parse s1 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_sval > 0x7FLL || arg_sval < -0x80LL) {
				printf("parse s1 immedate out of range %s\n", arg);
				return 0;
			}

			int8_t v = arg_sval;

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_s2") == 0) {

			arg_sval = strtoll(arg, &endp, 0);
			if(*endp) {
				printf("parse s2 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_sval > 0x7FFFLL || arg_sval < -0x8000LL) {
				printf("parse s2 immedate out of range %s\n", arg);
				return 0;
			}

			int16_t v = arg_sval;
			v = htobe16(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_s4") == 0) {

			arg_sval = strtoll(arg, &endp, 0);
			if(*endp) {
				printf("parse s4 immedate error for %s\n", arg);
				return 0;
			}
			if(arg_sval > 0x7FFFFFFFLL || arg_sval < -0x80000000LL) {
				printf("parse s4 immedate out of range %s\n", arg);
				return 0;
			}

			int32_t v = arg_sval;
			v = htobe32(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "data_s8") == 0) {

			arg_sval = strtoll(arg, &endp, 0);
			if(*endp) {
				printf("parse s8 immedate error for %s\n", arg);
				return 0;
			}

			int64_t v = arg_sval;
			v = htobe64(v);

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "addr") == 0) {

			n_a_node =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);
			clist_queue(&abs_patch_addrs, &n_a_node->hdr);

			uint32_t v = 0;
			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "reladdr") == 0) {

			n_a_node =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);
			clist_queue(&rel_patch_addrs, &n_a_node->hdr);

			int32_t v = 0;
			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "foreign_id") == 0) {

			n_a_node =
				name_addr_node_init(
					malloc(sizeof(struct name_addr_node)), arg, cu.text_len);
			clist_queue(&cu.foreign_deps, &n_a_node->hdr);

			// patched up later
			uint32_t v = 0;
			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, (unsigned char*)&v, sizeof(v));

		} else if(strcmp(directive, "mnemonic") == 0) {

			uint8_t op;
			for(op = 0; op < ARRLEN(mnemonics); op++)
				if(strcasecmp(mnemonics[op], arg) == 0)
					break;

			if(op == ARRLEN(mnemonics)) {
				printf("unknown mnemonic: %s\n", arg);
				return -1;
			}

			array_append_bytes(
				&cu.text, &cu.text_len, &out_text_cap, &op, sizeof(op));

		} else {
			printf("unknown assembler directive: %s\n", directive);
			return -1;
		}

	}

	// pass 2:
	// fixup patch addresses

	while(! clist_is_empty(&rel_patch_addrs)) {
		struct clnode *i = clnode_remove(clist_first(&rel_patch_addrs));
		struct name_addr_node *patch_dst = (struct name_addr_node *)i;

		struct name_addr_node *patch_src =
			name_addr_node_find(&label_addrs, patch_dst->name);

		if(! patch_src) { // external dep
			clist_queue(&cu.rel_deps, &patch_dst->hdr);
		} else {
			jump_t jump_target = patch_src->addr;
			jump_t jump_source = patch_dst->addr;
			jump_t jump = jump_target - jump_source;
			jump = htobe32(jump);
			memcpy(cu.text + patch_dst->addr, &jump, sizeof(jump));

			free(i);
		}
	}


	while(! clist_is_empty(&abs_patch_addrs)) {
		struct clnode *i = clnode_remove(clist_first(&abs_patch_addrs));
		struct name_addr_node *patch_dst = (struct name_addr_node *)i;

		struct name_addr_node *patch_src =
			name_addr_node_find(&label_addrs, patch_dst->name);

		if(! patch_src) { // external dep
			clist_queue(&cu.abs_deps, &patch_dst->hdr);
		} else {
			jump_t jump = patch_src->addr;
			jump = htobe32(jump);
			memcpy(cu.text + patch_dst->addr, &jump, sizeof(jump));

			free(i);
		}
	}
	
	//
	// write object file
	//

	comp_unit_write(&cu, argv[2]);

	return 0;
}
Beispiel #4
0
EC_BOOL cset_is_empty(const CSET *cset)
{
    return clist_is_empty(cset);
}