ldlang.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,418 行 · 第 1/5 页

C
2,418
字号
	  einfo ("%F\n");	}      else if (err != bfd_error_file_not_recognized	       || place == NULL)	einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);      bfd_close (entry->the_bfd);      entry->the_bfd = NULL;      /* Try to interpret the file as a linker script.  */      ldfile_open_command_file (entry->filename);      hold = stat_ptr;      stat_ptr = place;      ldfile_assumed_script = true;      parser_input = input_script;      yyparse ();      ldfile_assumed_script = false;      stat_ptr = hold;      return;    }  if (ldemul_recognized_file (entry))    return;  /* We don't call ldlang_add_file for an archive.  Instead, the     add_symbols entry point will call ldlang_add_file, via the     add_archive_element callback, for each element of the archive     which is used.  */  switch (bfd_get_format (entry->the_bfd))    {    default:      break;    case bfd_object:      ldlang_add_file (entry);      if (trace_files || trace_file_tries)	info_msg ("%I\n", entry);      break;    case bfd_archive:      if (entry->whole_archive)	{	  bfd *member = bfd_openr_next_archived_file (entry->the_bfd,						      (bfd *) NULL);	  while (member != NULL)	    {	      if (! bfd_check_format (member, bfd_object))		einfo (_("%F%B: object %B in archive is not object\n"),		       entry->the_bfd, member);	      if (! ((*link_info.callbacks->add_archive_element)		     (&link_info, member, "--whole-archive")))		abort ();	      if (! bfd_link_add_symbols (member, &link_info))		einfo (_("%F%B: could not read symbols: %E\n"), member);	      member = bfd_openr_next_archived_file (entry->the_bfd,						     member);	    }	  entry->loaded = true;	  return;	}    }  if (! bfd_link_add_symbols (entry->the_bfd, &link_info))    einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);  entry->loaded = true;}/* Handle a wild statement.  SECTION or FILE or both may be NULL,   indicating that it is a wildcard.  Separate lang_input_section   statements are created for each part of the expansion; they are   added after the wild statement S.  OUTPUT is the output section.  */static voidwild (s, section, file, target, output)     lang_wild_statement_type *s;     const char *section;     const char *file;     const char *target ATTRIBUTE_UNUSED;     lang_output_section_statement_type *output;{  walk_wild (s, section, file, output_section_callback, (PTR) output);  if (section != (char *) NULL      && strcmp (section, "COMMON") == 0      && default_common_section == NULL)    {      /* Remember the section that common is going to in case we later         get something which doesn't know where to put it.  */      default_common_section = output;    }}/* Return true iff target is the sought target.  */static intget_target (target, data)     const bfd_target *target;     PTR data;{  const char *sought = (const char *) data;  return strcmp (target->name, sought) == 0;}/* Like strcpy() but convert to lower case as well.  */static voidstricpy (dest, src)     char *dest;     char *src;{  char c;  while ((c = *src++) != 0)    {      if (isupper ((unsigned char) c))	c = tolower (c);      *dest++ = c;    }  *dest = 0;}/* Remove the first occurance of needle (if any) in haystack   from haystack.  */static voidstrcut (haystack, needle)     char *haystack;     char *needle;{  haystack = strstr (haystack, needle);  if (haystack)    {      char *src;      for (src = haystack + strlen (needle); *src;)	*haystack++ = *src++;      *haystack = 0;    }}/* Compare two target format name strings.   Return a value indicating how "similar" they are.  */static intname_compare (first, second)     char *first;     char *second;{  char *copy1;  char *copy2;  int result;  copy1 = xmalloc (strlen (first) + 1);  copy2 = xmalloc (strlen (second) + 1);  /* Convert the names to lower case.  */  stricpy (copy1, first);  stricpy (copy2, second);  /* Remove and endian strings from the name.  */  strcut (copy1, "big");  strcut (copy1, "little");  strcut (copy2, "big");  strcut (copy2, "little");  /* Return a value based on how many characters match,     starting from the beginning.   If both strings are     the same then return 10 * their length.  */  for (result = 0; copy1[result] == copy2[result]; result++)    if (copy1[result] == 0)      {	result *= 10;	break;      }  free (copy1);  free (copy2);  return result;}/* Set by closest_target_match() below.  */static const bfd_target *winner;/* Scan all the valid bfd targets looking for one that has the endianness   requirement that was specified on the command line, and is the nearest   match to the original output target.  */static intclosest_target_match (target, data)     const bfd_target *target;     PTR data;{  const bfd_target *original = (const bfd_target *) data;  if (command_line.endian == ENDIAN_BIG      && target->byteorder != BFD_ENDIAN_BIG)    return 0;  if (command_line.endian == ENDIAN_LITTLE      && target->byteorder != BFD_ENDIAN_LITTLE)    return 0;  /* Must be the same flavour.  */  if (target->flavour != original->flavour)    return 0;  /* If we have not found a potential winner yet, then record this one.  */  if (winner == NULL)    {      winner = target;      return 0;    }  /* Oh dear, we now have two potential candidates for a successful match.     Compare their names and choose the better one.  */  if (name_compare (target->name, original->name)      > name_compare (winner->name, original->name))    winner = target;  /* Keep on searching until wqe have checked them all.  */  return 0;}/* Return the BFD target format of the first input file.  */static char *get_first_input_target (){  char *target = NULL;  LANG_FOR_EACH_INPUT_STATEMENT (s)    {      if (s->header.type == lang_input_statement_enum	  && s->real)	{	  ldfile_open_file (s);	  if (s->the_bfd != NULL	      && bfd_check_format (s->the_bfd, bfd_object))	    {	      target = bfd_get_target (s->the_bfd);	      if (target != NULL)		break;	    }	}    }  return target;}/* Open the output file.  */static bfd *open_output (name)     const char *name;{  bfd *output;  /* Has the user told us which output format to use?  */  if (output_target == (char *) NULL)    {      /* No - has the current target been set to something other than         the default?  */      if (current_target != default_target)	output_target = current_target;      /* No - can we determine the format of the first input file?  */      else	{	  output_target = get_first_input_target ();	  /* Failed - use the default output target.  */	  if (output_target == NULL)	    output_target = default_target;	}    }  /* Has the user requested a particular endianness on the command     line?  */  if (command_line.endian != ENDIAN_UNSET)    {      const bfd_target *target;      enum bfd_endian desired_endian;      /* Get the chosen target.  */      target = bfd_search_for_target (get_target, (PTR) output_target);      /* If the target is not supported, we cannot do anything.  */      if (target != NULL)	{	  if (command_line.endian == ENDIAN_BIG)	    desired_endian = BFD_ENDIAN_BIG;	  else	    desired_endian = BFD_ENDIAN_LITTLE;	  /* See if the target has the wrong endianness.  This should	     not happen if the linker script has provided big and	     little endian alternatives, but some scrips don't do	     this.  */	  if (target->byteorder != desired_endian)	    {	      /* If it does, then see if the target provides		 an alternative with the correct endianness.  */	      if (target->alternative_target != NULL		  && (target->alternative_target->byteorder == desired_endian))		output_target = target->alternative_target->name;	      else		{		  /* Try to find a target as similar as possible to		     the default target, but which has the desired		     endian characteristic.  */		  (void) bfd_search_for_target (closest_target_match,						(PTR) target);		  /* Oh dear - we could not find any targets that		     satisfy our requirements.  */		  if (winner == NULL)		    einfo (_("%P: warning: could not find any targets that match endianness requirement\n"));		  else		    output_target = winner->name;		}	    }	}    }  output = bfd_openw (name, output_target);  if (output == (bfd *) NULL)    {      if (bfd_get_error () == bfd_error_invalid_target)	einfo (_("%P%F: target %s not found\n"), output_target);      einfo (_("%P%F: cannot open output file %s: %E\n"), name);    }  delete_output_file_on_failure = true;#if 0  output->flags |= D_PAGED;#endif  if (! bfd_set_format (output, bfd_object))    einfo (_("%P%F:%s: can not make object file: %E\n"), name);  if (! bfd_set_arch_mach (output,			   ldfile_output_architecture,			   ldfile_output_machine))    einfo (_("%P%F:%s: can not set architecture: %E\n"), name);  link_info.hash = bfd_link_hash_table_create (output);  if (link_info.hash == (struct bfd_link_hash_table *) NULL)    einfo (_("%P%F: can not create link hash table: %E\n"));  bfd_set_gp_size (output, g_switch_value);  return output;}static voidldlang_open_output (statement)     lang_statement_union_type *statement;{  switch (statement->header.type)    {    case lang_output_statement_enum:      ASSERT (output_bfd == (bfd *) NULL);      output_bfd = open_output (statement->output_statement.name);      ldemul_set_output_arch ();      if (config.magic_demand_paged && !link_info.relocateable)	output_bfd->flags |= D_PAGED;      else	output_bfd->flags &= ~D_PAGED;      if (config.text_read_only)	output_bfd->flags |= WP_TEXT;      else	output_bfd->flags &= ~WP_TEXT;      if (link_info.traditional_format)	output_bfd->flags |= BFD_TRADITIONAL_FORMAT;      else	output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;      break;    case lang_target_statement_enum:      current_target = statement->target_statement.target;      break;    default:      break;    }}/* Open all the input files.  */static voidopen_input_bfds (s, force)     lang_statement_union_type *s;     boolean force;{  for (; s != (lang_statement_union_type *) NULL; s = s->next)    {      switch (s->header.type)	{	case lang_constructors_statement_enum:	  open_input_bfds (constructor_list.head, force);	  break;	case lang_output_section_statement_enum:	  open_input_bfds (s->output_section_statement.children.head, force);	  break;	case lang_wild_statement_enum:	  /* Maybe we should load the file's symbols.  */	  if (s->wild_statement.filename	      && ! wildcardp (s->wild_statement.filename))	    (void) lookup_name (s->wild_statement.filename);	  open_input_bfds (s->wild_statement.children.head, force);	  break;	case lang_group_statement_enum:	  {	    struct bfd_link_hash_entry *undefs;	    /* We must continually search the entries in the group	       until no new symbols are added to the list of undefined	       symbols.  */	    do	      {		undefs = link_info.hash->undefs_tail;		open_input_bfds (s->group_statement.children.head, true);	      }	    while (undefs != link_info.hash->undefs_tail);	  }	  break;	case lang_target_statement_enum:	  current_target = s->target_statement.target;	  break;	case lang_input_statement_enum:	  if (s->input_statement.real)	    {	      lang_statement_list_type add;	      s->input_statement.target = current_target;	      /* If we are being called from within a group, and this                 is an archive which has already been searched, then                 force it to be researched unless the whole archive		 has been loaded already.  */	      if (force		  && !s->input_statement.whole_archive		  && s->input_statement.loaded		  && bfd_check_format (s->input_statement.the_bfd,				       bfd_archive))		s->input_statement.loaded = false;	      lang_list_init (&add);	      load_symbols (&s->input_statement, &add);	      if (add.head != NULL)		{		  *add.tail = s->next;		  s->next = add.head;		}	    }	  break;	default:	  break;	}    }}/* If there are [COMMONS] statements, put a wild one into the bss   section.  */static void

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?