Example #1
0
static int
_parse_long_options(struct ld *ld, struct ld_option *opts, int ac,
    int argc, char **argv, char *opt, enum ld_dash dash)
{
	char *equal;
	size_t av_len;
	int i, match;

	if ((equal = strchr(opt, '=')) != NULL) {
		av_len = equal - opt;
		equal++;
		if (*equal == '\0')
			ld_fatal(ld, "no argument after =");
	} else
		av_len = strlen(opt);

	match = 0;
	for (i = 0; opts[i].lo_long != NULL; i++) {
		if (opts[i].lo_dash != ANY_DASH && opts[i].lo_dash != dash)
			continue;
		if (strlen(opts[i].lo_long) == av_len &&
		    !strncmp(opt, opts[i].lo_long, av_len)) {
			match = 1;
			break;
		}
	}
	if (!match)
		return (-1);

	switch (opts[i].lo_arg) {
	case NO_ARG:
		if (equal != NULL) {
			ld_fatal(ld, "option %s does not accept argument",
			    opts[i].lo_long);
		}
		_process_options(ld, opts[i].lo_key, NULL);
		break;
	case REQ_ARG:
		if (equal != NULL)
			_process_options(ld, opts[i].lo_key, equal);
		else {
			if (++ac >= argc)
				ld_fatal(ld, "require arg for option %s",
				    opts[i].lo_long);
			_process_options(ld, opts[i].lo_key, argv[ac]);
		}
		break;
	case OPT_ARG:
		_process_options(ld, opts[i].lo_key, equal);
		break;
	default:
		assert(0);
		break;
	}

	return (++ac);
}
Example #2
0
static void
_process_reloc(struct ld *ld, struct ld_input_section *is,
    struct ld_reloc_entry *lre, struct ld_symbol *lsb, uint8_t *buf)
{
	struct ld_state *ls;
	struct ld_output *lo;
	uint32_t p, s, l, g, got;
	int32_t a, v;

	ls = &ld->ld_state;

	lo = ld->ld_output;
	assert(lo != NULL);

	l = lsb->lsb_plt_off;
	p = lre->lre_offset + is->is_output->os_addr + is->is_reloff;
	got = ld->ld_got->is_output->os_addr;
	s = (uint32_t) lsb->lsb_value;
	READ_32(buf + lre->lre_offset, a);

	switch (lre->lre_type) {
	case R_386_NONE:
		break;

	case R_386_32:
		v = s + a;
		WRITE_32(buf + lre->lre_offset, v);
		break;

	case R_386_PC32:
		if (lsb->lsb_plt)
			v = l + a - p;
		else
			v = s + a - p;
		WRITE_32(buf + lre->lre_offset, v);
		break;

	case R_386_PLT32:
		if (!ls->ls_ignore_next_plt) {
			v = l + a - p;
			WRITE_32(buf + lre->lre_offset, v);
		} else
			ls->ls_ignore_next_plt = 0;
		break;

	case R_386_GOT32:
		g = _got_offset(ld, lsb);
		v = g + a;
		WRITE_32(buf + lre->lre_offset, v);
		break;

	case R_386_GOTOFF:
		v = s + a - got;
		WRITE_32(buf + lre->lre_offset, v);
		break;

	case R_386_GOTPC:
		v = got + a - p;
		WRITE_32(buf + lre->lre_offset, v);
		break;

	default:
		ld_fatal(ld, "Relocation %d not supported", lre->lre_type);
		break;
	}
}
Example #3
0
static void
_process_options(struct ld *ld, int key, char *arg)
{
	struct ld_state *ls;

	assert(ld != NULL);
	ls = &ld->ld_state;

	switch (key) {
	case 'b':
		ls->ls_itgt = elftc_bfd_find_target(arg);
		if (ls->ls_itgt == NULL)
			ld_fatal(ld, "invalid BFD target `%s'", arg);
		break;
	case 'd':
		ld->ld_common_alloc = 1;
		break;
	case 'e':
		_copy_optarg(ld, &ld->ld_entry, arg);
		break;
	case 'h':
		_copy_optarg(ld, &ld->ld_soname, arg);
		break;
	case 'I':
		_copy_optarg(ld, &ld->ld_interp, arg);
		break;
	case 'l':
		ld_path_search_library(ld, arg);
		break;
	case 'L':
		ld_path_add(ld, arg);
		break;
	case 'M':
		ld->ld_print_linkmap = 1;
		break;
	case 'o':
		_copy_optarg(ld, &ld->ld_output_file, arg);
		break;
	case 'q':
		ld->ld_emit_reloc = 1;
		break;
	case 'r':
		ld->ld_reloc = 1;
		break;
	case 'T':
		ld_script_parse(arg);
		break;
	case 'u':
		ld_symbols_add_extern(ld, arg);
		break;
	case 'v':
	case 'V':
		_print_version(ld);
		break;
	case '(':
		ls->ls_group_level++;
		if (ls->ls_group_level > LD_MAX_NESTED_GROUP)
			ld_fatal(ld, "too many nested archive groups");
		break;
	case ')':
		ls->ls_group_level--;
		break;
	case KEY_AS_NEEDED:
		ls->ls_as_needed = 1;
		break;
	case KEY_DYNAMIC:
		ls->ls_static = 0;
		break;
	case KEY_EH_FRAME_HDR:
		ld->ld_ehframe_hdr = 1;
		break;
	case KEY_GC_SECTIONS:
		ld->ld_gc = 1;
		break;
	case KEY_NO_AS_NEEDED:
		ls->ls_as_needed = 0;
		break;
	case KEY_NO_DEFINE_COMMON:
		ld->ld_common_no_alloc = 1;
		break;
	case KEY_NO_GC_SECTIONS:
		ld->ld_gc = 0;
		break;
	case KEY_NO_PRINT_GC_SECTIONS:
		ld->ld_gc_print = 0;
		break;
	case KEY_NO_WHOLE_ARCHIVE:
		ls->ls_whole_archive = 0;
		break;
	case KEY_OFORMAT:
		ld_output_format(ld, arg, arg, arg);
		break;
	case KEY_PIE:
		ld->ld_exec = 0;
		ld->ld_pie = 1;
		ld->ld_dynamic_link = 1;
		break;
	case KEY_PRINT_GC_SECTIONS:
		ld->ld_gc_print = 1;
		break;
	case KEY_SHARED:
		ld->ld_exec = 0;
		ld->ld_dso = 1;
		ld->ld_dynamic_link = 1;
		break;
	case KEY_STATIC:
		ls->ls_static = 1;
		break;
	case KEY_WHOLE_ARCHIVE:
		ls->ls_whole_archive = 1;
		break;
	case KEY_FILE:
		ld_file_add(ld, arg, LFT_UNKNOWN);
		break;
	case KEY_VERSION_SCRIPT:
		ld_script_parse(arg);
		break;
	case KEY_Z_EXEC_STACK:
		ld->ld_gen_gnustack = 1;
		ld->ld_stack_exec_set = 1;
		ld->ld_stack_exec = 1;
		break;
	case KEY_Z_NO_EXEC_STACK:
		ld->ld_gen_gnustack = 1;
		ld->ld_stack_exec_set = 1;
		ld->ld_stack_exec = 0;
		break;
	default:
		break;
	}
}
Example #4
0
void
ld_options_parse(struct ld* ld, int argc, char **argv)
{
	enum ld_dash d;
	char *p, *p0, *oli;
	int ac, ac0;

	ac = 1;

	while (ac < argc) {
		p = argv[ac];
		if (*p != '-' || p[1] == '\0') {
			_process_options(ld, KEY_FILE, p);
			ac++;
			continue;
		}

		if (*++p == '-') {
			if (p[1] == '\0') {
				/* Option --. Ignore the rest of options. */
				return;
			}
			p++;
			d = TWO_DASH;
		} else {
			d = ONE_DASH;
			if (*p == 'B' || *p == 'z') {
				ac0 = ac;
				if (*(p0 = p + 1) == '\0')
					p0 = argv[++ac0];
				ac = _parse_long_options(ld,
				    *p == 'B' ? ld_opts_B : ld_opts_z,
				    ac0, argc, argv, p0, d);
				if (ac > 0)
					continue;
				ld_fatal(ld, "unrecognized options -%c: %s",
				    *p, p0);
			}
		}

		ac0 = _parse_long_options(ld, ld_opts, ac, argc, argv, p, d);
		if (ac0 > 0) {
			ac = ac0;
			continue;
		}

		if (d == TWO_DASH)
			ld_fatal(ld, "unrecognized option %s", p);

		/*
		 * Search short options.
		 */
		while (*p != '\0') {
			if ((oli = strchr(ld_short_opts, *p)) == NULL)
				ld_fatal(ld, "unrecognized option -%c", *p);
			if (*++oli != ':') {
				_process_options(ld, *p++, NULL);
				continue;
			}
			if (p[1] != '\0')
				_process_options(ld, *p, &p[1]);
			else if (oli[1] != ':') {
				if (++ac >= argc)
					ld_fatal(ld, "require arg for"
					    " option -%c", *p);
				_process_options(ld, *p, argv[ac]);
			}
			break;
		}

		ac++;
	}
}