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

📄 ld.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
intfile_open (entry)     register struct file_entry *entry;{  register int desc;  if (entry->superfile)    return file_open (entry->superfile);  if (entry == input_file)    return input_desc;  if (input_file) file_close ();  if (entry->search_dirs_flag)    {      int i;      for (i = 0; i < n_search_dirs; i++)	{	  register char *string	    = concat (search_dirs[i], "/", entry->filename);	  desc = open (string, O_RDONLY, 0);	  if (desc > 0)	    {	      entry->filename = string;	      entry->search_dirs_flag = 0;	      break;	    }	  free (string);	}    }  else    desc = open (entry->filename, O_RDONLY, 0);  if (desc > 0)    {      input_file = entry;      input_desc = desc;      return desc;    }  perror_file (entry);  /* NOTREACHED */}/* Print the filename of ENTRY on OUTFILE (a stdio stream),   and then a newline.  */voidprline_file_name (entry, outfile)     struct file_entry *entry;     FILE *outfile;{  print_file_name (entry, outfile);  fprintf (outfile, "\n");}/* Print the filename of ENTRY on OUTFILE (a stdio stream).  */voidprint_file_name (entry, outfile)     struct file_entry *entry;     FILE *outfile;{  if (entry->superfile)    {      print_file_name (entry->superfile, outfile);      fprintf (outfile, "(%s)", entry->filename);    }  else    fprintf (outfile, "%s", entry->filename);}/* Return the filename of entry as a string (malloc'd for the purpose) */char *get_file_name (entry)     struct file_entry *entry;{  char *result, *supfile;  if (entry->superfile)    {      supfile = get_file_name (entry->superfile);      result = (char *) xmalloc (strlen (supfile)				 + strlen (entry->filename) + 3);      sprintf (result, "%s(%s)", supfile, entry->filename);      free (supfile);    }  else    {      result = (char *) xmalloc (strlen (entry->filename) + 1);      strcpy (result, entry->filename);    }  return result;}/* Medium-level input routines for rel files.  *//* Read a file's header into the proper place in the file_entry.   DESC is the descriptor on which the file is open.   ENTRY is the file's entry.  */voidread_header (desc, entry)     int desc;     register struct file_entry *entry;{  register int len;  struct exec *loc = (struct exec *) &entry->header;  lseek (desc, entry->starting_offset, 0);#ifdef COFF_ENCAPSULATE  if (entry->just_syms_flag)    lseek (desc, sizeof(coffheader), 1);#endif  len = read (desc, loc, sizeof (struct exec));  if (len != sizeof (struct exec))    fatal_with_file ("failure reading header of ", entry);  if (N_BADMAG (*loc))    fatal_with_file ("bad magic number in ", entry);  entry->header_read_flag = 1;}/* Read the symbols of file ENTRY into core.   Assume it is already open, on descriptor DESC.   Also read the length of the string table, which follows the symbol table,   but don't read the contents of the string table.  */voidread_entry_symbols (desc, entry)     struct file_entry *entry;     int desc;{  int str_size;  if (!entry->header_read_flag)    read_header (desc, entry);  entry->symbols = (struct nlist *) xmalloc (entry->header.a_syms);  lseek (desc, N_SYMOFF (entry->header) + entry->starting_offset, 0);  if (entry->header.a_syms != read (desc, entry->symbols, entry->header.a_syms))    fatal_with_file ("premature end of file in symbols of ", entry);  lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);  if (sizeof str_size != read (desc, &str_size, sizeof str_size))    fatal_with_file ("bad string table size in ", entry);  entry->string_size = str_size;}/* Read the string table of file ENTRY into core.   Assume it is already open, on descriptor DESC.   Also record whether a GDB symbol segment follows the string table.  */voidread_entry_strings (desc, entry)     struct file_entry *entry;     int desc;{  int buffer;  if (!entry->header_read_flag)    read_header (desc, entry);  lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);  if (entry->string_size != read (desc, entry->strings, entry->string_size))    fatal_with_file ("premature end of file in strings of ", entry);  /* While we are here, see if the file has a symbol segment at the end.     For a separate file, just try reading some more.     For a library member, compare current pos against total size.  */  if (entry->superfile)    {      if (entry->total_size == N_STROFF (entry->header) + entry->string_size)	return;    }  else    {      buffer = read (desc, &buffer, sizeof buffer);      if (buffer == 0)	return;      if (buffer != sizeof buffer)	fatal_with_file ("premature end of file in GDB symbol segment of ", entry);    }  /* Don't try to do anything with symsegs.  */  return;#if 0  /* eliminate warning of `statement not reached'.  */  entry->symseg_offset = N_STROFF (entry->header) + entry->string_size;#endif}/* Read in the symbols of all input files.  */void read_file_symbols (), read_entry_symbols (), read_entry_strings ();void enter_file_symbols (), enter_global_ref (), search_library ();voidload_symbols (){  register int i;  if (trace_files) fprintf (stderr, "Loading symbols:\n\n");  for (i = 0; i < number_of_files; i++)    {      register struct file_entry *entry = &file_table[i];      read_file_symbols (entry);    }  if (trace_files) fprintf (stderr, "\n");}/* If ENTRY is a rel file, read its symbol and string sections into core.   If it is a library, search it and load the appropriate members   (which means calling this function recursively on those members).  */voidread_file_symbols (entry)     register struct file_entry *entry;{  register int desc;  register int len;  struct exec hdr;  desc = file_open (entry);#ifdef COFF_ENCAPSULATE  if (entry->just_syms_flag)    lseek (desc, sizeof(coffheader),0);#endif  len = read (desc, &hdr, sizeof hdr);  if (len != sizeof hdr)    fatal_with_file ("failure reading header of ", entry);  if (!N_BADMAG (hdr))    {      read_entry_symbols (desc, entry);      entry->strings = (char *) alloca (entry->string_size);      read_entry_strings (desc, entry);      enter_file_symbols (entry);      entry->strings = 0;    }  else    {      char armag[SARMAG];      lseek (desc, 0, 0);      if (SARMAG != read (desc, armag, SARMAG) || strncmp (armag, ARMAG, SARMAG))	fatal_with_file ("malformed input file (not rel or archive) ", entry);      entry->library_flag = 1;      search_library (desc, entry);    }  file_close ();}/* Enter the external symbol defs and refs of ENTRY in the hash table.  */voidenter_file_symbols (entry)     struct file_entry *entry;{  register struct nlist    *p,    *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);  if (trace_files) prline_file_name (entry, stderr);  for (p = entry->symbols; p < end; p++)    {      if (p->n_type == (N_SETV | N_EXT)) continue;      if (set_element_prefixes	  && set_element_prefixed_p (p->n_un.n_strx + entry->strings))	p->n_type += (N_SETA - N_ABS);      if (SET_ELEMENT_P (p->n_type))	{	  set_symbol_count++;	  if (!relocatable_output)	    enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);	}      else if (p->n_type == N_WARNING)	{	  char *name = p->n_un.n_strx + entry->strings;	  /* Grab the next entry.  */	  p++;	  if (p->n_type != (N_UNDF | N_EXT))	    {	      fprintf (stderr, "%s: Warning symbol found in %s without external reference following.\n",		       progname, entry->filename);	      make_executable = 0;	      p--;		/* Process normally.  */	    }	  else	    {	      symbol *sp;	      char *sname = p->n_un.n_strx + entry->strings;	      /* Deal with the warning symbol.  */	      enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);	      sp = getsym (sname);	      sp->warning = (char *) xmalloc (strlen(name) + 1);	      strcpy (sp->warning, name);	      warning_count++;	    }	}      else if (p->n_type & N_EXT)	enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);      else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))	{	  if ((p->n_un.n_strx + entry->strings)[0] != LPREFIX)	    non_L_local_sym_count++;	  local_sym_count++;	}      else debugger_sym_count++;    }   /* Count one for the local symbol that we generate,      whose name is the file's name (usually) and whose address      is the start of the file's text.  */  local_sym_count++;  non_L_local_sym_count++;}/* Enter one global symbol in the hash table.   NLIST_P points to the `struct nlist' read from the file   that describes the global symbol.  NAME is the symbol's name.   ENTRY is the file entry for the file the symbol comes from.   The `struct nlist' is modified by placing it on a chain of   all such structs that refer to the same global symbol.   This chain starts in the `refs' field of the symbol table entry   and is chained through the `n_name'.  */voidenter_global_ref (nlist_p, name, entry)     register struct nlist *nlist_p;     char *name;     struct file_entry *entry;{  register symbol *sp = getsym (name);  register int type = nlist_p->n_type;  int oldref = sp->referenced;  int olddef = sp->defined;  int com = sp->defined && sp->max_common_size;  nlist_p->n_un.n_name = (char *) sp->refs;  sp->refs = nlist_p;  sp->referenced = 1;  if (type != (N_UNDF | N_EXT) || nlist_p->n_value)    {      if (!sp->defined || sp->defined == (N_UNDF | N_EXT))	sp->defined = type;      if (oldref && !olddef)	/* It used to be undefined and we're defining it.  */	undefined_global_sym_count--;      if (!olddef && type == (N_UNDF | N_EXT) && nlist_p->n_value)	{	  /* First definition and it's common.  */	  common_defined_global_count++;	  sp->max_common_size = nlist_p->n_value;	}      else if (com && type != (N_UNDF | N_EXT))	{	  /* It used to be common and we're defining it as	     something else.  */	  common_defined_global_count--;	  sp->max_common_size = 0;	}      else if (com && type == (N_UNDF | N_EXT)	  && sp->max_common_size < nlist_p->n_value)	/* It used to be common and this is a new common entry to	   which we need to pay attention.  */	sp->max_common_size = nlist_p->n_value;      /* Are we defining it as a set element?  */      if (SET_ELEMENT_P (type) && (!olddef || com))	set_vector_count++;      /* As an indirection?  */      else if (type == (N_INDR | N_EXT))	{	  /* Indirect symbols value should be modified to point	     a symbol being equivalenced to. */	  nlist_p->n_value	    = (unsigned int) getsym ((nlist_p + 1)->n_un.n_strx				     + entry->strings);	  if ((symbol *) nlist_p->n_value == sp)	    {	      /* Somebody redefined a symbol to be itself.  */	      fprintf (stderr, "%s: Symbol %s indirected to itself.\n",		       entry->filename, name);	      /* Rewrite this symbol as being a global text symbol		 with value 0.  */	      nlist_p->n_type = sp->defined = N_TEXT | N_EXT;	      nlist_p->n_value = 0;	      /* Don't make the output executable.  */	      make_executable = 0;	    }	  else	    global_indirect_count++;	}    }  else    if (!oldref)#ifndef DOLLAR_KLUDGE      undefined_global_sym_count++;#else      {	if (entry->superfile && type == (N_UNDF | N_EXT) && name[1] == '$')	  {	    /* This is an (ISI?) $-conditional; skip it */	    sp->referenced = 0;	    if (sp->trace)	      {		fprintf (stderr, "symbol %s is a $-conditional ignored in ", sp->name);		print_file_name (entry, stderr);		fprintf (stderr, "\n");	      }	    return;	  }	else	  undefined_global_sym_count++;      }#endif  if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified)    text_start = nlist_p->n_value;  if (sp->trace)    {      register char *reftype;      switch (type & N_TYPE)	{	case N_UNDF:	  if (nlist_p->n_value)	    reftype = "defined as common";	  else reftype = "referenced";	  break;	case N_ABS:	  reftype = "defined as absolute";	  break;	case N_TEXT:	  reftype = "defined in text section";	  break;	case N_DATA:	  reftype = "defined in data section";	  break;	case N_BSS:	  reftype = "defined in BSS section";	  break;	case N_SETT:	  reftype = "is a text set element";	  break;	case N_SETD:	  reftype = "is a data set element";

⌨️ 快捷键说明

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