modifying ld options in the enviroment

Marty Leisner leisner@rochester.rr.com
Sun May 15 01:12:00 GMT 2005


I've often tried to do things like 
	make CC='gcc -Wl,-t'
to find out why builds were doing strange things -- in complicated
situations this doesn't work for a variety of reasons (depending
on how the system was architected).

Instead of rearchitecting the make architecture, or seeing the
failing the command line (which is sometimes not shown) and running it 
standalone,
I inserted a environemnt variable 
	LD_ENV_OPTIONS
which allows you to inject options into ld
(another approach is to write a script in front of the real ld which does
this, but this gets old fast)...

A simple case is:
: leisner@dell3;LD_ENV_OPTIONS=-t gcc foo.c
option is -t
/usr/gnu/binutils/bin/ld: mode elf_i386
/usr/lib/gcc/i386-redhat-linux/3.4.2/../../../crt1.o
/usr/lib/gcc/i386-redhat-linux/3.4.2/../../../crti.o
/usr/lib/gcc/i386-redhat-linux/3.4.2/crtbegin.o
/tmp/ccOGmbte.o
-lgcc_s (/usr/lib/gcc/i386-redhat-linux/3.4.2/libgcc_s.so)
/lib/libc.so.6
(/usr/lib/libc_nonshared.a)elf-init.oS
-lgcc_s (/usr/lib/gcc/i386-redhat-linux/3.4.2/libgcc_s.so)
/usr/lib/gcc/i386-redhat-linux/3.4.2/crtend.o
/usr/lib/gcc/i386-redhat-linux/3.4.2/../../../crtn.o

This is wrt 2.16 -- I've had this for a few years...I've found it 
very useful...I'm thinking of duplicating something like this for gcc...



Marty Leisner
leisner@rochester.rr.com

-------------- next part --------------
--- ldmain.c	2005/05/12 05:49:05	1.1
+++ ldmain.c	2005/05/14 20:33:57
@@ -164,6 +164,10 @@
 };
 
 struct bfd_link_info link_info;
+
+static int modify_env_argc(int argc, char ***);
+
+ 
 
 static void
 remove_output (void)
@@ -320,12 +324,14 @@
   config.magic_demand_paged = TRUE;
   config.text_read_only = TRUE;
 
+  argc = modify_env_args(argc, &argv);
   emulation = get_emulation (argc, argv);
   ldemul_choose_mode (emulation);
   default_target = ldemul_choose_target (argc, argv);
   lang_init ();
   ldemul_before_parse ();
   lang_has_input_file = FALSE;
+ 
   parse_args (argc, argv);
 
   if (config.hash_table_size != 0)
@@ -1526,3 +1532,93 @@
 
   return TRUE;
 }
+
+static int count_options(const char *env)
+{
+	int i;
+
+	i = 0;
+
+	while(*env) {
+		/* skip white */
+		while(*env == ' ')
+			env++;
+
+		if(*env) 
+			i++;
+
+		/* find white */
+		while(*env && *env != ' ' )
+			env++;
+	}
+	return i;
+}
+
+/* malloc space and figure out option, copy it into the space */
+static char *get_env_option(char *env)
+{
+	char *end;
+	int size;
+	char *new;
+
+	for(end = env; *end && *end != ' '; end++)
+		;
+
+	size = end - env + 1;
+	new = malloc(size);
+	strncpy(new, env, size - 1);
+	new[size - 1] = 0;
+#if 0
+	printf("option is %s\n", new);
+#endif
+	return new;
+}	
+
+static char *skip_white(char *env)
+{
+	while(*env && *env == ' ')
+		env++;
+
+	return env;
+}
+
+/* possibly modify the argc/argv list from an environment
+ * variable.
+ * If the list is modified, new arguments are inserts started
+ * at position argv[1] and everything else is shifted down.
+ * New space is allocated for the argv array.
+ */
+static int modify_env_args(int argc, 
+		           char ***pass_argv)
+{
+	char *env;
+	int count;
+	int space_needed;
+	char *cp;
+	char **new_argv;
+	char *space;
+	int i;
+	char **argv;
+
+	env = getenv("LD_ENV_OPTIONS");
+	if(!env)
+		return argc;
+
+	argv = *pass_argv;
+	count = count_options(env);
+	new_argv = malloc((argc + count + 1) * sizeof(char *));
+	new_argv[0] = argv[0];
+	for(i = 0; i < count; i++) {
+		env = skip_white(env);
+		new_argv[i + 1] = get_env_option(env);
+		env = index(env, ' ');
+	}
+	
+	/* move rest of argv to new_argv */
+	memcpy(new_argv + (i + 1), argv + 1, sizeof(char *) * argc);
+
+	*pass_argv = new_argv;
+
+	return argc + count;
+}
+	


More information about the Binutils mailing list