⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ld.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	  break;	case N_SETB:	  reftype = "is a BSS set element";	  break;	case N_SETA:	  reftype = "is an absolute set element";	  break;	case N_SETV:	  reftype = "defined in data section as vector";	  break;	case N_INDR:	  reftype = (char *) alloca (23				     + strlen ((nlist_p + 1)->n_un.n_strx					       + entry->strings));	  sprintf (reftype, "defined equivalent to %s",		   (nlist_p + 1)->n_un.n_strx + entry->strings);	  break;#ifdef sequent	case N_SHUNDF:	  reftype = "shared undf";	  break;/* These conflict with cases above.	case N_SHDATA:	  reftype = "shared data";	  break;	case N_SHBSS:	  reftype = "shared BSS";	  break;*/	default:	  reftype = "I don't know this type";	  break;#endif	}      fprintf (stderr, "symbol %s %s in ", sp->name, reftype);      print_file_name (entry, stderr);      fprintf (stderr, "\n");    }}/* This return 0 if the given file entry's symbol table does *not*   contain the nlist point entry, and it returns the files entry   pointer (cast to unsigned long) if it does. */unsigned longcontains_symbol (entry, n_ptr)     struct file_entry *entry;     register struct nlist *n_ptr;{  if (n_ptr >= entry->symbols &&      n_ptr < (entry->symbols	       + (entry->header.a_syms / sizeof (struct nlist))))    return (unsigned long) entry;  return 0;}/* Searching libraries */struct file_entry *decode_library_subfile ();void linear_library (), symdef_library ();/* Search the library ENTRY, already open on descriptor DESC.   This means deciding which library members to load,   making a chain of `struct file_entry' for those members,   and entering their global symbols in the hash table.  */voidsearch_library (desc, entry)     int desc;     struct file_entry *entry;{  int member_length;  register char *name;  register struct file_entry *subentry;  if (!undefined_global_sym_count) return;  /* Examine its first member, which starts SARMAG bytes in.  */  subentry = decode_library_subfile (desc, entry, SARMAG, &member_length);  if (!subentry) return;  name = subentry->filename;  free (subentry);  /* Search via __.SYMDEF if that exists, else linearly.  */  if (!strcmp (name, "__.SYMDEF"))    symdef_library (desc, entry, member_length);  else    linear_library (desc, entry);}/* Construct and return a file_entry for a library member.   The library's file_entry is library_entry, and the library is open on DESC.   SUBFILE_OFFSET is the byte index in the library of this member's header.   We store the length of the member into *LENGTH_LOC.  */struct file_entry *decode_library_subfile (desc, library_entry, subfile_offset, length_loc)     int desc;     struct file_entry *library_entry;     int subfile_offset;     int *length_loc;{  int bytes_read;  register int namelen;  int member_length;  register char *name;  struct ar_hdr hdr1;  register struct file_entry *subentry;  lseek (desc, subfile_offset, 0);  bytes_read = read (desc, &hdr1, sizeof hdr1);  if (!bytes_read)    return 0;		/* end of archive */  if (sizeof hdr1 != bytes_read)    fatal_with_file ("malformed library archive ", library_entry);  if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)    fatal_with_file ("malformatted header of archive member in ", library_entry);  subentry = (struct file_entry *) xmalloc (sizeof (struct file_entry));  bzero (subentry, sizeof (struct file_entry));  for (namelen = 0;       namelen < sizeof hdr1.ar_name       && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '       && hdr1.ar_name[namelen] != '/';       namelen++);  name = (char *) xmalloc (namelen+1);  strncpy (name, hdr1.ar_name, namelen);  name[namelen] = 0;  subentry->filename = name;  subentry->local_sym_name = name;  subentry->symbols = 0;  subentry->strings = 0;  subentry->subfiles = 0;  subentry->starting_offset = subfile_offset + sizeof hdr1;  subentry->superfile = library_entry;  subentry->library_flag = 0;  subentry->header_read_flag = 0;  subentry->just_syms_flag = 0;  subentry->chain = 0;  subentry->total_size = member_length;  (*length_loc) = member_length;  return subentry;}int subfile_wanted_p ();/* Search a library that has a __.SYMDEF member.   DESC is a descriptor on which the library is open.     The file pointer is assumed to point at the __.SYMDEF data.   ENTRY is the library's file_entry.   MEMBER_LENGTH is the length of the __.SYMDEF data.  */voidsymdef_library (desc, entry, member_length)     int desc;     struct file_entry *entry;     int member_length;{  int *symdef_data = (int *) xmalloc (member_length);  register struct symdef *symdef_base;  char *sym_name_base;  int number_of_symdefs;  int length_of_strings;  int not_finished;  int bytes_read;  register int i;  struct file_entry *prev = 0;  int prev_offset = 0;  bytes_read = read (desc, symdef_data, member_length);  if (bytes_read != member_length)    fatal_with_file ("malformatted __.SYMDEF in ", entry);  number_of_symdefs = *symdef_data / sizeof (struct symdef);  if (number_of_symdefs < 0 ||       number_of_symdefs * sizeof (struct symdef) + 2 * sizeof (int) > member_length)    fatal_with_file ("malformatted __.SYMDEF in ", entry);  symdef_base = (struct symdef *) (symdef_data + 1);  length_of_strings = *(int *) (symdef_base + number_of_symdefs);  if (length_of_strings < 0      || number_of_symdefs * sizeof (struct symdef) + length_of_strings	  + 2 * sizeof (int) > member_length)    fatal_with_file ("malformatted __.SYMDEF in ", entry);  sym_name_base = sizeof (int) + (char *) (symdef_base + number_of_symdefs);  /* Check all the string indexes for validity.  */  for (i = 0; i < number_of_symdefs; i++)    {      register int index = symdef_base[i].symbol_name_string_index;      if (index < 0 || index >= length_of_strings	  || (index && *(sym_name_base + index - 1)))	fatal_with_file ("malformatted __.SYMDEF in ", entry);    }  /* Search the symdef data for members to load.     Do this until one whole pass finds nothing to load.  */  not_finished = 1;  while (not_finished)    {      not_finished = 0;      /* Scan all the symbols mentioned in the symdef for ones that we need.	 Load the library members that contain such symbols.  */      for (i = 0;	   (i < number_of_symdefs	    && (undefined_global_sym_count || common_defined_global_count));	   i++)	if (symdef_base[i].symbol_name_string_index >= 0)	  {	    register symbol *sp;	    sp = getsym_soft (sym_name_base			      + symdef_base[i].symbol_name_string_index);	    /* If we find a symbol that appears to be needed, think carefully	       about the archive member that the symbol is in.  */	    /*	     * Per Mike Karels' recommendation, we no longer load library	     * files if the only reference(s) that would be satisfied are	     * 'common' references.  This prevents some problems with name	     * pollution (e.g. a global common 'utime' linked to a function).	     */	    if (sp && sp->referenced && !sp->defined)	      {		int junk;		register int j;		register int offset = symdef_base[i].library_member_offset;		struct file_entry *subentry;		/* Don't think carefully about any archive member		   more than once in a given pass.  */		if (prev_offset == offset)		  continue;		prev_offset = offset;		/* Read the symbol table of the archive member.  */		subentry = decode_library_subfile (desc, entry, offset, &junk);		if (subentry == 0)		  fatal ("invalid offset for %s in symbol table of %s",			 sym_name_base			 + symdef_base[i].symbol_name_string_index,			 entry->filename);		read_entry_symbols (desc, subentry);		subentry->strings = (char *) malloc (subentry->string_size);		read_entry_strings (desc, subentry);		/* Now scan the symbol table and decide whether to load.  */		if (!subfile_wanted_p (subentry))		  {		    free (subentry->symbols);		    free (subentry);		  }		else		  {		    /* This member is needed; load it.		       Since we are loading something on this pass,		       we must make another pass through the symdef data.  */		    not_finished = 1;		    enter_file_symbols (subentry);		    if (prev)		      prev->chain = subentry;		    else entry->subfiles = subentry;		    prev = subentry;		    /* Clear out this member's symbols from the symdef data		       so that following passes won't waste time on them.  */		    for (j = 0; j < number_of_symdefs; j++)		      {			if (symdef_base[j].library_member_offset == offset)			  symdef_base[j].symbol_name_string_index = -1;		      }		  }		/* We'll read the strings again if we need them again.  */		free (subentry->strings);		subentry->strings = 0;	      }	  }    }  free (symdef_data);}/* Search a library that has no __.SYMDEF.   ENTRY is the library's file_entry.   DESC is the descriptor it is open on.  */voidlinear_library (desc, entry)     int desc;     struct file_entry *entry;{  register struct file_entry *prev = 0;  register int this_subfile_offset = SARMAG;  while (undefined_global_sym_count || common_defined_global_count)    {      int member_length;      register struct file_entry *subentry;      subentry = decode_library_subfile (desc, entry, this_subfile_offset,					 &member_length);      if (!subentry) return;      read_entry_symbols (desc, subentry);      subentry->strings = (char *) alloca (subentry->string_size);      read_entry_strings (desc, subentry);      if (!subfile_wanted_p (subentry))	{	  free (subentry->symbols);	  free (subentry);	}      else	{	  enter_file_symbols (subentry);	  if (prev)	    prev->chain = subentry;	  else entry->subfiles = subentry;	  prev = subentry;	  subentry->strings = 0; /* Since space will dissapear on return */	}      this_subfile_offset += member_length + sizeof (struct ar_hdr);      if (this_subfile_offset & 1) this_subfile_offset++;    }}/* ENTRY is an entry for a library member.   Its symbols have been read into core, but not entered.   Return nonzero if we ought to load this member.  */intsubfile_wanted_p (entry)     struct file_entry *entry;{  register struct nlist *p;  register struct nlist *end    = entry->symbols + entry->header.a_syms / sizeof (struct nlist);#ifdef DOLLAR_KLUDGE  register int dollar_cond = 0;#endif  for (p = entry->symbols; p < end; p++)    {      register int type = p->n_type;      register char *name = p->n_un.n_strx + entry->strings;      /* If the symbol has an interesting definition, we could	 potentially want it.  */      if (type & N_EXT	  && (type != (N_UNDF | N_EXT) || p->n_value#ifdef DOLLAR_KLUDGE	       || name[1] == '$'#endif	      )	  && !SET_ELEMENT_P (type)	  && !set_element_prefixed_p (name))	{	  register symbol *sp = getsym_soft (name);#ifdef DOLLAR_KLUDGE	  if (name[1] == '$')	    {	      sp = getsym_soft (&name[2]);	      dollar_cond = 1;	      if (!sp) continue;	      if (sp->referenced)		{		  if (write_map)		    {		      print_file_name (entry, stdout);		      fprintf (stdout, " needed due to $-conditional %s\n", name);		    }		  return 1;		}	      continue;	    }#endif	  /* If this symbol has not been hashed, we can't be looking for it. */	  if (!sp) continue;	  /*	   * We don't load a file if it merely satisfies a common reference	   * (see explanation above in symdef_library()).	   */	  if (sp->referenced && !sp->defined)	    {	      /* This is a symbol we are looking for.  It is either	         not yet defined or defined as a common.  */#ifdef DOLLAR_KLUDGE	      if (dollar_cond) continue;#endif	      if (type == (N_UNDF | N_EXT))		{		  /* Symbol being defined as common.		     Remember this, but don't load subfile just for this.  */		  /* If it didn't used to be common, up the count of		     common symbols.  */		  if (!sp->max_common_size)		    common_defined_global_count++;		  if (sp->max_common_size < p->n_value)		    sp->max_common_size = p->n_value;		  if (!sp->defined)		    undefined_global_sym_count--;		  sp->defined = 1;		  continue;		}	      if (write_map)		{		  print_file_name (entry, stdout);		  fprintf (stdout, " needed due to %s\n", sp->name);		}	      return 1;	    }	}    }  return 0;}void consider_file_section_lengths (), relocate_file_addresses ();/* Having entered all the global symbols and found the sizes of sections   of all files to be linked, make all appropriate deductions from this data.   We propagate global 

⌨️ 快捷键说明

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