WHY

As we all known, the default linker script of ld is hardcoded in it (you can check it by invoking "ld --verbose"). Of course we can specify our own script by passing the argument "-T scriptname", but sometimes we do want to change the default one.

HOW TO

Basically there are two ways to do that. The first one is to change the internal script of "ld" directly, yet you need to rebuild/install your new "ld" whenever you want to change a bit of your default script. The second one would be more convenience. The idea is that since the commandline argument can take the precedent of the internal linker script, why not use that feature.

I change the "ld" working like that:

ADVANTAGE

In that way, we can override the internal one without using "-T scriptname". The advantage is we can still use "-T scriptname" to take the place of our new default script. And, we don't need to rebuild the "ld" once we change that script. Moreover, once we delete that default script, the "ld" would work as the normal one (uses its hardcoded script as default).

PROGRAMMING DETAIL

Path and filename

+ static char* def_lsc[] = {"/usr/lib/ldscripts/elf64_ia64.x.def",  /*for exec*/
+                           "/usr/lib/ldscripts/elf64_ia64.xs.def" };  /*for dyn*/

Commandline parsing

case 'T':
          ldfile_open_command_file (optarg);
          parser_input = input_script;
          yyparse ();
+         has_linkerscript = TRUE;
          break;

If user specifies any script, skip the following procedure via the variable "has_linkerscript".

Process defaul script

+   if ( has_linkerscript == FALSE )
+   {
+
+     FILE *file;
+     char* fname;
+
+     if (link_info.shared == TRUE)//"TRUE" means user passed "-shared" to the commandline.
+           fname = def_lsc[1];
+     else
+           fname = def_lsc[0];
+
+     file = fopen(fname,"r"); //File existence check.
+     if ( file != NULL )
+        {
+          fclose(file);
+          ldfile_open_command_file (fname); //Process the script file as in the commandline parser.
+        parser_input = input_script;
+        yyparse ();
+        }
+   }

Update help message

+   printf (_("\n  ### Warning: The way using default linker script has been changed! ###\n\n"));
+   printf (_("    '%s' is the default script for normal exec. \n"), def_lsc[0]);
+   printf (_("    '%s' is the default script for shared libs. \n"), def_lsc[1]);
+   printf (_("    It will use the internal script if those files are not existed.\n\n"));

The diff file

shanliao@torrone:/usr/src/sliao/binutils.pak/develop/src$ cvs diff -r1.1.1.1 -r1.2 ld/lexsup.c -q
Index: ld/lexsup.c
===================================================================
RCS file: /usr/src/localCVSRoot/develop/src/ld/lexsup.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** ld/lexsup.c 6 Jan 2005 01:43:41 -0000       1.1.1.1
--- ld/lexsup.c 7 Jan 2005 05:17:48 -0000       1.2
***************
*** 519,524 ****
--- 519,526 ----

  #define OPTION_COUNT ARRAY_SIZE (ld_options)

+ static char* def_lsc[] = {"/usr/lib/ldscripts/elf64_ia64.x.def",
+                           "/usr/lib/ldscripts/elf64_ia64.xs.def" };
  void
  parse_args (unsigned argc, char **argv)
  {
***************
*** 531,537 ****
    struct option *really_longopts;
    int last_optind;
    enum report_method how_to_report_unresolved_symbols = RM_GENERATE_ERROR;
!
    shortopts = xmalloc (OPTION_COUNT * 3 + 2);
    longopts = xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
    really_longopts = xmalloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
--- 533,540 ----
    struct option *really_longopts;
    int last_optind;
    enum report_method how_to_report_unresolved_symbols = RM_GENERATE_ERROR;
!   bfd_boolean has_linkerscript = FALSE;
!
    shortopts = xmalloc (OPTION_COUNT * 3 + 2);
    longopts = xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
    really_longopts = xmalloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
***************
*** 1111,1116 ****
--- 1114,1120 ----
          ldfile_open_command_file (optarg);
          parser_input = input_script;
          yyparse ();
+         has_linkerscript = TRUE;
          break;
        case OPTION_SECTION_START:
          {
***************
*** 1343,1348 ****
--- 1347,1373 ----
        }
      }

+   if ( has_linkerscript == FALSE )
+   {
+
+     FILE *file;
+     char* fname;
+
+     if (link_info.shared == TRUE)
+           fname = def_lsc[1];
+     else
+           fname = def_lsc[0];
+
+     file = fopen(fname,"r"); //File existence check
+     if ( file != NULL )
+        {
+          fclose(file);
+          ldfile_open_command_file (fname);
+        parser_input = input_script;
+        yyparse ();
+        }
+   }
+
    if (ingroup)
      lang_leave_group ();

***************
*** 1436,1443 ****
    unsigned i;
    const char **targets, **pp;

    printf (_("Usage: %s [options] file...\n"), program_name);
-
    printf (_("Options:\n"));
    for (i = 0; i < OPTION_COUNT; i++)
      {
--- 1461,1471 ----
    unsigned i;
    const char **targets, **pp;

+   printf (_("\n  ### Warning: The way using default linker script has been changed! ###\n\n"));
+   printf (_("    '%s' is the default script for normal exec. \n"), def_lsc[0]);
+   printf (_("    '%s' is the default script for shared libs. \n"), def_lsc[1]);
+   printf (_("    It will use the internal script if those files are not existed.\n\n"));
    printf (_("Usage: %s [options] file...\n"), program_name);
    printf (_("Options:\n"));
    for (i = 0; i < OPTION_COUNT; i++)
      {

IA64wiki: ChangeDefLinkerScript (last edited 2009-12-10 03:13:58 by localhost)

Gelato@UNSW is sponsored by
the University of New South Wales National ICT Australia The Gelato Federation Hewlett-Packard Company Australian Research Council
Please contact us with any questions or comments.