ldlang.c

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

C
2,418
字号
/* Linker command language support.   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,   2001   Free Software Foundation, Inc.This file is part of GLD, the Gnu Linker.GLD is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GLD is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GLD; see the file COPYING.  If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA.  */#include "bfd.h"#include "sysdep.h"#include "libiberty.h"#include "obstack.h"#include "bfdlink.h"#include "ld.h"#include "ldmain.h"#include "ldgram.h"#include "ldexp.h"#include "ldlang.h"#include "ldlex.h"#include "ldmisc.h"#include "ldctor.h"#include "ldfile.h"#include "ldemul.h"#include "fnmatch.h"#include "demangle.h"#include <ctype.h>/* FORWARDS */static lang_statement_union_type *new_statement  PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));/* LOCALS */static struct obstack stat_obstack;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freestatic const char *startup_file;static lang_statement_list_type input_file_chain;static boolean placed_commons = false;static lang_output_section_statement_type *default_common_section;static boolean map_option_f;static bfd_vma print_dot;static lang_input_statement_type *first_file;static const char *current_target;static const char *output_target;static lang_statement_list_type statement_list;static struct lang_phdr *lang_phdr_list;static void lang_for_each_statement_worker  PARAMS ((void (*) (lang_statement_union_type *),	   lang_statement_union_type *));static lang_input_statement_type *new_afile  PARAMS ((const char *, lang_input_file_enum_type, const char *, boolean));static lang_memory_region_type *lang_memory_default PARAMS ((asection *));static void lang_map_flags PARAMS ((flagword));static void init_os PARAMS ((lang_output_section_statement_type *));static void exp_init_os PARAMS ((etree_type *));static void section_already_linked PARAMS ((bfd *, asection *, PTR));static struct bfd_hash_entry *already_linked_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static void already_linked_table_init PARAMS ((void));static void already_linked_table_free PARAMS ((void));static boolean wildcardp PARAMS ((const char *));static lang_statement_union_type *wild_sort  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,	   asection *));static void output_section_callback  PARAMS ((lang_wild_statement_type *, asection *,	   lang_input_statement_type *, PTR));static lang_input_statement_type *lookup_name PARAMS ((const char *));static void load_symbols  PARAMS ((lang_input_statement_type *, lang_statement_list_type *));static void wild  PARAMS ((lang_wild_statement_type *, const char *, const char *,	   const char *, lang_output_section_statement_type *));static bfd *open_output PARAMS ((const char *));static void ldlang_open_output PARAMS ((lang_statement_union_type *));static void open_input_bfds PARAMS ((lang_statement_union_type *, boolean));static void lang_reasonable_defaults PARAMS ((void));static void lang_place_undefineds PARAMS ((void));static void map_input_to_output_sections  PARAMS ((lang_statement_union_type *, const char *,	   lang_output_section_statement_type *));static void print_output_section_statement  PARAMS ((lang_output_section_statement_type *));static void print_assignment  PARAMS ((lang_assignment_statement_type *,	   lang_output_section_statement_type *));static void print_input_statement PARAMS ((lang_input_statement_type *));static boolean print_one_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));static void print_input_section PARAMS ((lang_input_section_type *));static void print_fill_statement PARAMS ((lang_fill_statement_type *));static void print_data_statement PARAMS ((lang_data_statement_type *));static void print_address_statement PARAMS ((lang_address_statement_type *));static void print_reloc_statement PARAMS ((lang_reloc_statement_type *));static void print_padding_statement PARAMS ((lang_padding_statement_type *));static void print_wild_statement  PARAMS ((lang_wild_statement_type *, lang_output_section_statement_type *));static void print_group  PARAMS ((lang_group_statement_type *, lang_output_section_statement_type *));static void print_statement  PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));static void print_statement_list  PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));static void print_statements PARAMS ((void));static bfd_vma insert_pad  PARAMS ((lang_statement_union_type **, fill_type,	   unsigned int, asection *, bfd_vma));static bfd_vma size_input_section  PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,	   fill_type, bfd_vma, boolean));static void lang_finish PARAMS ((void));static void ignore_bfd_errors PARAMS ((const char *, ...));static void lang_check PARAMS ((void));static void lang_common PARAMS ((void));static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));static void lang_place_orphans PARAMS ((void));static int topower PARAMS ((int));static void lang_set_startof PARAMS ((void));static void reset_memory_regions PARAMS ((void));static void gc_section_callback  PARAMS ((lang_wild_statement_type *, asection *,	   lang_input_statement_type *, PTR));static void lang_record_phdrs PARAMS ((void));static void lang_gc_wild  PARAMS ((lang_wild_statement_type *, const char *, const char *));static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));static void lang_gc_sections PARAMS ((void));static int lang_vers_match_lang_c  PARAMS ((struct bfd_elf_version_expr *, const char *));static int lang_vers_match_lang_cplusplus  PARAMS ((struct bfd_elf_version_expr *, const char *));static int lang_vers_match_lang_java  PARAMS ((struct bfd_elf_version_expr *, const char *));static void lang_do_version_exports_section PARAMS ((void));static void lang_check_section_addresses PARAMS ((void));static void os_region_check  PARAMS ((lang_output_section_statement_type *,	   struct memory_region_struct *, etree_type *, bfd_vma));typedef void (*callback_t) PARAMS ((lang_wild_statement_type *,				    asection *, lang_input_statement_type *,				    PTR));static void walk_wild  PARAMS ((lang_wild_statement_type *, const char *, const char *,	 callback_t, PTR));static void walk_wild_section  PARAMS ((lang_wild_statement_type *, const char *,	   lang_input_statement_type *, callback_t, PTR));static void walk_wild_file  PARAMS ((lang_wild_statement_type *, const char *,	   lang_input_statement_type *, callback_t, PTR));static int    get_target PARAMS ((const bfd_target *, PTR));static void   stricpy PARAMS ((char *, char *));static void   strcut PARAMS ((char *, char *));static int    name_compare PARAMS ((char *, char *));static int    closest_target_match PARAMS ((const bfd_target *, PTR));static char * get_first_input_target PARAMS ((void));/* EXPORTS */lang_output_section_statement_type *abs_output_section;lang_statement_list_type lang_output_section_statement;lang_statement_list_type *stat_ptr = &statement_list;lang_statement_list_type file_chain = { NULL, NULL };const char *entry_symbol = NULL;boolean entry_from_cmdline;boolean lang_has_input_file = false;boolean had_output_filename = false;boolean lang_float_flag = false;boolean delete_output_file_on_failure = false;struct lang_nocrossrefs *nocrossref_list;struct unique_sections *unique_section_list;etree_type *base; /* Relocation base - or null */#if defined (__STDC__) || defined (ALMOST_STDC)#define cat(a,b) a##b#else#define cat(a,b) a/**/b#endif/* Don't beautify the line below with "innocent" whitespace, it breaks   the K&R C preprocessor!  */#define new_stat(x, y) \  (cat (x,_type)*) new_statement (cat (x,_enum), sizeof (cat (x,_type)), y)#define outside_section_address(q) \  ((q)->output_offset + (q)->output_section->vma)#define outside_symbol_address(q) \  ((q)->value + outside_section_address (q->section))#define SECTION_NAME_MAP_LENGTH (16)PTRstat_alloc (size)     size_t size;{  return obstack_alloc (&stat_obstack, size);}booleanunique_section_p (secnam)     const char *secnam;{  struct unique_sections *unam;  for (unam = unique_section_list; unam; unam = unam->next)    if (wildcardp (unam->name)	? fnmatch (unam->name, secnam, 0) == 0	: strcmp (unam->name, secnam) == 0)      {	return true;      }  return false;}/* Generic traversal routines for finding matching sections.  */static voidwalk_wild_section (ptr, section, file, callback, data)     lang_wild_statement_type *ptr;     const char *section;     lang_input_statement_type *file;     callback_t callback;     PTR data;{  /* Don't process sections from files which were excluded.  */  if (ptr->exclude_filename_list != NULL)    {      struct name_list *list_tmp;      for (list_tmp = ptr->exclude_filename_list;	   list_tmp;	   list_tmp = list_tmp->next)	{	  boolean match;	  if (wildcardp (list_tmp->name))	    match = fnmatch (list_tmp->name, file->filename, 0) == 0;	  else	    match = strcmp (list_tmp->name, file->filename) == 0;	  if (match)	    return;	}    }  if (file->just_syms_flag == false)    {      register asection *s;      boolean wildcard = false;      if (section != NULL)	wildcard = wildcardp (section);      for (s = file->the_bfd->sections; s != NULL; s = s->next)	{	  boolean match;	  const char *sname = bfd_get_section_name (file->the_bfd, s);	  if (section == NULL)	    match = true;	  else if (wildcard)	    match = fnmatch (section, sname, 0) == 0;	  else	    match = strcmp (section, sname) == 0;	  /* If this is a wild-card output section statement, exclude	     sections that match UNIQUE_SECTION_LIST.  */	  if (match && (data == NULL || !unique_section_p (sname)))	    (*callback) (ptr, s, file, data);	}    }}/* Handle a wild statement for a single file F.  */static voidwalk_wild_file (s, section, f, callback, data)     lang_wild_statement_type *s;     const char *section;     lang_input_statement_type *f;     callback_t callback;     PTR data;{  if (f->the_bfd == NULL      || ! bfd_check_format (f->the_bfd, bfd_archive))    walk_wild_section (s, section, f, callback, data);  else    {      bfd *member;      /* This is an archive file.  We must map each member of the	 archive separately.  */      member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);      while (member != NULL)	{	  /* When lookup_name is called, it will call the add_symbols	     entry point for the archive.  For each element of the	     archive which is included, BFD will call ldlang_add_file,	     which will set the usrdata field of the member to the	     lang_input_statement.  */	  if (member->usrdata != NULL)	    {	      walk_wild_section (s, section,				 (lang_input_statement_type *) member->usrdata,				 callback, data);	    }	  member = bfd_openr_next_archived_file (f->the_bfd, member);	}    }}static voidwalk_wild (s, section, file, callback, data)     lang_wild_statement_type *s;     const char *section;     const char *file;     callback_t callback;     PTR data;{  if (file == (char *) NULL)    {      /* Perform the iteration over all files in the list.  */      LANG_FOR_EACH_INPUT_STATEMENT (f)	{	  walk_wild_file (s, section, f, callback, data);	}    }  else if (wildcardp (file))    {      LANG_FOR_EACH_INPUT_STATEMENT (f)	{	  if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)	    walk_wild_file (s, section, f, callback, data);	}    }  else    {      lang_input_statement_type *f;      /* Perform the iteration over a single file.  */      f = lookup_name (file);      walk_wild_file (s, section, f, callback, data);    }}/* lang_for_each_statement walks the parse tree and calls the provided   function for each node.  */static voidlang_for_each_statement_worker (func, s)     void (*func) PARAMS ((lang_statement_union_type *));     lang_statement_union_type *s;{  for (; s != (lang_statement_union_type *) NULL; s = s->next)    {      func (s);      switch (s->header.type)	{	case lang_constructors_statement_enum:	  lang_for_each_statement_worker (func, constructor_list.head);	  break;	case lang_output_section_statement_enum:	  lang_for_each_statement_worker	    (func,	     s->output_section_statement.children.head);	  break;	case lang_wild_statement_enum:	  lang_for_each_statement_worker	    (func,	     s->wild_statement.children.head);	  break;	case lang_group_statement_enum:	  lang_for_each_statement_worker (func,					  s->group_statement.children.head);	  break;	case lang_data_statement_enum:	case lang_reloc_statement_enum:	case lang_object_symbols_statement_enum:	case lang_output_statement_enum:	case lang_target_statement_enum:	case lang_input_section_enum:	case lang_input_statement_enum:	case lang_assignment_statement_enum:	case lang_padding_statement_enum:	case lang_address_statement_enum:	case lang_fill_statement_enum:	  break;	default:	  FAIL ();	  break;	}    }}voidlang_for_each_statement (func)     void (*func) PARAMS ((lang_statement_union_type *));{  lang_for_each_statement_worker (func, statement_list.head);}/*----------------------------------------------------------------------*/voidlang_list_init (list)     lang_statement_list_type *list;{  list->head = (lang_statement_union_type *) NULL;  list->tail = &list->head;}/* Build a new statement node for the parse tree.  */static lang_statement_union_type *new_statement (type, size, list)     enum statement_enum type;     size_t size;     lang_statement_list_type *list;{  lang_statement_union_type *new = (lang_statement_union_type *)  stat_alloc (size);  new->header.type = type;  new->header.next = (lang_statement_union_type *) NULL;  lang_statement_append (list, new, &new->header.next);  return new;}/* Build a new input file node for the language.  There are several   ways in which we treat an input file, eg, we only look at symbols,   or prefix it with a -l etc.   We can be supplied with requests for input files more than once;   they may, for example be split over serveral lines like foo.o(.text)   foo.o(.data) etc, so when asked for a file we check that we haven't   got it already so we don't duplicate the bfd.  */static lang_input_statement_type *new_afile (name, file_type, target, add_to_list)     const char *name;     lang_input_file_enum_type file_type;     const char *target;     boolean add_to_list;{  lang_input_statement_type *p;  if (add_to_list)    p = new_stat (lang_input_statement, stat_ptr);  else    {      p = ((lang_input_statement_type *)	   stat_alloc (sizeof (lang_input_statement_type)));      p->header.next = NULL;    }  lang_has_input_file = true;  p->target = target;  switch (file_type)    {    case lang_input_file_is_symbols_only_enum:      p->filename = name;      p->is_archive = false;

⌨️ 快捷键说明

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