ldlang.c

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

C
2,418
字号
      p->real = true;      p->local_sym_name = name;      p->just_syms_flag = true;      p->search_dirs_flag = false;      break;    case lang_input_file_is_fake_enum:      p->filename = name;      p->is_archive = false;      p->real = false;      p->local_sym_name = name;      p->just_syms_flag = false;      p->search_dirs_flag = false;      break;    case lang_input_file_is_l_enum:      p->is_archive = true;      p->filename = name;      p->real = true;      p->local_sym_name = concat ("-l", name, (const char *) NULL);      p->just_syms_flag = false;      p->search_dirs_flag = true;      break;    case lang_input_file_is_marker_enum:      p->filename = name;      p->is_archive = false;      p->real = false;      p->local_sym_name = name;      p->just_syms_flag = false;      p->search_dirs_flag = true;      break;    case lang_input_file_is_search_file_enum:      p->filename = name;      p->is_archive = false;      p->real = true;      p->local_sym_name = name;      p->just_syms_flag = false;      p->search_dirs_flag = true;      break;    case lang_input_file_is_file_enum:      p->filename = name;      p->is_archive = false;      p->real = true;      p->local_sym_name = name;      p->just_syms_flag = false;      p->search_dirs_flag = false;      break;    default:      FAIL ();    }  p->the_bfd = (bfd *) NULL;  p->asymbols = (asymbol **) NULL;  p->next_real_file = (lang_statement_union_type *) NULL;  p->next = (lang_statement_union_type *) NULL;  p->symbol_count = 0;  p->dynamic = config.dynamic_link;  p->whole_archive = whole_archive;  p->loaded = false;  lang_statement_append (&input_file_chain,			 (lang_statement_union_type *) p,			 &p->next_real_file);  return p;}lang_input_statement_type *lang_add_input_file (name, file_type, target)     const char *name;     lang_input_file_enum_type file_type;     const char *target;{  lang_has_input_file = true;  return new_afile (name, file_type, target, true);}/* Build enough state so that the parser can build its tree.  */voidlang_init (){  obstack_begin (&stat_obstack, 1000);  stat_ptr = &statement_list;  lang_list_init (stat_ptr);  lang_list_init (&input_file_chain);  lang_list_init (&lang_output_section_statement);  lang_list_init (&file_chain);  first_file = lang_add_input_file ((char *) NULL,				    lang_input_file_is_marker_enum,				    (char *) NULL);  abs_output_section =    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);  abs_output_section->bfd_section = bfd_abs_section_ptr;}/*----------------------------------------------------------------------  A region is an area of memory declared with the  MEMORY {  name:org=exp, len=exp ... }  syntax.  We maintain a list of all the regions here.  If no regions are specified in the script, then the default is used  which is created when looked up to be the entire data space.  */static lang_memory_region_type *lang_memory_region_list;static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;lang_memory_region_type *lang_memory_region_lookup (name)     const char *const name;{  lang_memory_region_type *p;  for (p = lang_memory_region_list;       p != (lang_memory_region_type *) NULL;       p = p->next)    {      if (strcmp (p->name, name) == 0)	{	  return p;	}    }#if 0  /* This code used to always use the first region in the list as the     default region.  I changed it to instead use a region     encompassing all of memory as the default region.  This permits     NOLOAD sections to work reasonably without requiring a region.     People should specify what region they mean, if they really want     a region.  */  if (strcmp (name, "*default*") == 0)    {      if (lang_memory_region_list != (lang_memory_region_type *) NULL)	{	  return lang_memory_region_list;	}    }#endif  {    lang_memory_region_type *new =    (lang_memory_region_type *) stat_alloc (sizeof (lang_memory_region_type));    new->name = xstrdup (name);    new->next = (lang_memory_region_type *) NULL;    *lang_memory_region_list_tail = new;    lang_memory_region_list_tail = &new->next;    new->origin = 0;    new->flags = 0;    new->not_flags = 0;    new->length = ~(bfd_size_type) 0;    new->current = 0;    new->had_full_message = false;    return new;  }}static lang_memory_region_type *lang_memory_default (section)     asection *section;{  lang_memory_region_type *p;  flagword sec_flags = section->flags;  /* Override SEC_DATA to mean a writable section.  */  if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)    sec_flags |= SEC_DATA;  for (p = lang_memory_region_list;       p != (lang_memory_region_type *) NULL;       p = p->next)    {      if ((p->flags & sec_flags) != 0	  && (p->not_flags & sec_flags) == 0)	{	  return p;	}    }  return lang_memory_region_lookup ("*default*");}lang_output_section_statement_type *lang_output_section_find (name)     const char *const name;{  lang_statement_union_type *u;  lang_output_section_statement_type *lookup;  for (u = lang_output_section_statement.head;       u != (lang_statement_union_type *) NULL;       u = lookup->next)    {      lookup = &u->output_section_statement;      if (strcmp (name, lookup->name) == 0)	{	  return lookup;	}    }  return (lang_output_section_statement_type *) NULL;}lang_output_section_statement_type *lang_output_section_statement_lookup (name)     const char *const name;{  lang_output_section_statement_type *lookup;  lookup = lang_output_section_find (name);  if (lookup == (lang_output_section_statement_type *) NULL)    {      lookup = (lang_output_section_statement_type *)	new_stat (lang_output_section_statement, stat_ptr);      lookup->region = (lang_memory_region_type *) NULL;      lookup->lma_region = (lang_memory_region_type *) NULL;      lookup->fill = 0;      lookup->block_value = 1;      lookup->name = name;      lookup->next = (lang_statement_union_type *) NULL;      lookup->bfd_section = (asection *) NULL;      lookup->processed = false;      lookup->sectype = normal_section;      lookup->addr_tree = (etree_type *) NULL;      lang_list_init (&lookup->children);      lookup->memspec = (const char *) NULL;      lookup->flags = 0;      lookup->subsection_alignment = -1;      lookup->section_alignment = -1;      lookup->load_base = (union etree_union *) NULL;      lookup->phdrs = NULL;      lang_statement_append (&lang_output_section_statement,			     (lang_statement_union_type *) lookup,			     &lookup->next);    }  return lookup;}static voidlang_map_flags (flag)     flagword flag;{  if (flag & SEC_ALLOC)    minfo ("a");  if (flag & SEC_CODE)    minfo ("x");  if (flag & SEC_READONLY)    minfo ("r");  if (flag & SEC_DATA)    minfo ("w");  if (flag & SEC_LOAD)    minfo ("l");}voidlang_map (){  lang_memory_region_type *m;  minfo (_("\nMemory Configuration\n\n"));  fprintf (config.map_file, "%-16s %-18s %-18s %s\n",	   _("Name"), _("Origin"), _("Length"), _("Attributes"));  for (m = lang_memory_region_list;       m != (lang_memory_region_type *) NULL;       m = m->next)    {      char buf[100];      int len;      fprintf (config.map_file, "%-16s ", m->name);      sprintf_vma (buf, m->origin);      minfo ("0x%s ", buf);      len = strlen (buf);      while (len < 16)	{	  print_space ();	  ++len;	}      minfo ("0x%V", m->length);      if (m->flags || m->not_flags)	{#ifndef BFD64	  minfo ("        ");#endif	  if (m->flags)	    {	      print_space ();	      lang_map_flags (m->flags);	    }	  if (m->not_flags)	    {	      minfo (" !");	      lang_map_flags (m->not_flags);	    }	}      print_nl ();    }  fprintf (config.map_file, _("\nLinker script and memory map\n\n"));  print_statements ();}/* Initialize an output section.  */static voidinit_os (s)     lang_output_section_statement_type *s;{  section_userdata_type *new;  if (s->bfd_section != NULL)    return;  if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)    einfo (_("%P%F: Illegal use of `%s' section"), DISCARD_SECTION_NAME);  new = ((section_userdata_type *)	 stat_alloc (sizeof (section_userdata_type)));  s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);  if (s->bfd_section == (asection *) NULL)    s->bfd_section = bfd_make_section (output_bfd, s->name);  if (s->bfd_section == (asection *) NULL)    {      einfo (_("%P%F: output format %s cannot represent section called %s\n"),	     output_bfd->xvec->name, s->name);    }  s->bfd_section->output_section = s->bfd_section;  /* We initialize an output sections output offset to minus its own     vma to allow us to output a section through itself.  */  s->bfd_section->output_offset = 0;  get_userdata (s->bfd_section) = (PTR) new;  /* If there is a base address, make sure that any sections it might     mention are initialized.  */  if (s->addr_tree != NULL)    exp_init_os (s->addr_tree);}/* Make sure that all output sections mentioned in an expression are   initialized.  */static voidexp_init_os (exp)     etree_type *exp;{  switch (exp->type.node_class)    {    case etree_assign:      exp_init_os (exp->assign.src);      break;    case etree_binary:      exp_init_os (exp->binary.lhs);      exp_init_os (exp->binary.rhs);      break;    case etree_trinary:      exp_init_os (exp->trinary.cond);      exp_init_os (exp->trinary.lhs);      exp_init_os (exp->trinary.rhs);      break;    case etree_unary:      exp_init_os (exp->unary.child);      break;    case etree_name:      switch (exp->type.node_code)	{	case ADDR:	case LOADADDR:	case SIZEOF:	  {	    lang_output_section_statement_type *os;	    os = lang_output_section_find (exp->name.name);	    if (os != NULL && os->bfd_section == NULL)	      init_os (os);	  }	}      break;    default:      break;    }}/* Sections marked with the SEC_LINK_ONCE flag should only be linked   once into the output.  This routine checks each section, and   arrange to discard it if a section of the same name has already   been linked.  If the section has COMDAT information, then it uses   that to decide whether the section should be included.  This code   assumes that all relevant sections have the SEC_LINK_ONCE flag set;   that is, it does not depend solely upon the section name.   section_already_linked is called via bfd_map_over_sections.  *//* This is the shape of the elements inside the already_linked hash   table. It maps a name onto a list of already_linked elements with   the same name.  It's possible to get more than one element in a   list if the COMDAT sections have different names.  */struct already_linked_hash_entry{  struct bfd_hash_entry root;  struct already_linked *entry;};struct already_linked{  struct already_linked *next;  asection *sec;};/* The hash table.  */static struct bfd_hash_table already_linked_table;static voidsection_already_linked (abfd, sec, data)     bfd *abfd;     asection *sec;     PTR data;{  lang_input_statement_type *entry = (lang_input_statement_type *) data;  flagword flags;  const char *name;  struct already_linked *l;  struct already_linked_hash_entry *already_linked_list;  /* If we are only reading symbols from this object, then we want to     discard all sections.  */  if (entry->just_syms_flag)    {      sec->output_section = bfd_abs_section_ptr;      sec->output_offset = sec->vma;      return;    }  flags = bfd_get_section_flags (abfd, sec);  if ((flags & SEC_LINK_ONCE) == 0)    return;  /* FIXME: When doing a relocatable link, we may have trouble     copying relocations in other sections that refer to local symbols     in the section being discarded.  Those relocations will have to     be converted somehow; as of this writing I'm not sure that any of     the backends handle that correctly.     It is tempting to instead not discard link once sections when     doing a relocatable link (technically, they should be discarded     whenever we are building constructors).  However, that fails,     because the linker winds up combining all the link once sections     into a single large link once section, which defeats the purpose     of having link once sections in the first place.     Also, not merging link once sections in a relocatable link     causes trouble for MIPS ELF, which relies in link once semantics     to handle the .reginfo section correctly.  */  name = bfd_get_section_name (abfd, sec);  already_linked_list =    ((struct already_linked_hash_entry *)     bfd_hash_lookup (&already_linked_table, name, true, false));

⌨️ 快捷键说明

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