GNU ld链接器 lang_process()(二)

一、ldemul_create_output_section_statements()

位于lang_process()中11行 。 该函数用于创建与目标有关的输出段的语句。这些语句将用于描述输出段的属性和分配。

cpp 复制代码
void
ldemul_create_output_section_statements (void)
{
  if (ld_emulation->create_output_section_statements)
    ld_emulation->create_output_section_statements ();
}
cpp 复制代码
static ld_emulation_xfer_type *ld_emulation;
cpp 复制代码
  /* Create any output sections needed by the target.  */
  void	(*create_output_section_statements) (void);  // 14
cpp 复制代码
typedef struct ld_emulation_xfer_struct {
  /* Run before parsing the command line and script file.
     Set the architecture, maybe other things.  */
  void   (*before_parse) (void); // 1

  /* Handle the SYSLIB (low level library) script command.  */
  void   (*syslib) (char *);  // 2

  /* Handle the HLL (high level library) script command.  */
  void   (*hll) (char *);  // 3

  /* Run after parsing the command line and script file.  */
  void   (*after_parse) (void);  // 4

  /* Run after opening all input files, and loading the symbols.  */
  void   (*after_open) (void);  // 5

  /* Run after allocating output sections.  */
  void   (*after_allocation)  (void);  // 6

  /* Set the output architecture and machine if possible.  */
  void   (*set_output_arch) (void);  // 7

  /* Decide which target name to use.  */
  char * (*choose_target) (int, char**);  // 8

  /* Run before allocating output sections.  */
  void   (*before_allocation) (void);  // 9

  /* Return the appropriate linker script.  */
  char * (*get_script) (int *isfile);  // 10

  /* The name of this emulation.  */
  char *emulation_name;  // 11

  /* The output format.  */
  char *target_name;  // 12

  /* Run after assigning values from the script.  */
  void	(*finish) (void);  // 13

  /* Create any output sections needed by the target.  */
  void	(*create_output_section_statements) (void);  // 14

  /* Try to open a dynamic library.  ARCH is an architecture name, and
     is normally the empty string.  ENTRY is the lang_input_statement
     that should be opened.  */
  bfd_boolean (*open_dynamic_archive)
    (const char *arch, struct search_dirs *,
     struct lang_input_statement_struct *entry);  // 15

  /* Place an orphan section.  Return TRUE if it was placed, FALSE if
     the default action should be taken.  This field may be NULL, in
     which case the default action will always be taken.  */
  lang_output_section_statement_type *(*place_orphan)
    (asection *, const char *, int);  // 16

  /* Run after assigning parsing with the args, but before
     reading the script.  Used to initialize symbols used in the script.  */
  void	(*set_symbols) (void);  // 17

  /* Parse args which the base linker doesn't understand.
     Return TRUE if the arg needs no further processing.  */
  bfd_boolean (*parse_args) (int, char **);  // 18

  /* Hook to add options to parameters passed by the base linker to
     getopt_long and getopt_long_only calls.  */
  void (*add_options)
    (int, char **, int, struct option **, int, struct option **);  // 19

  /* Companion to the above to handle an option.  Returns TRUE if it is
     one of our options.  */
  bfd_boolean (*handle_option) (int);  // 20

  /* Run to handle files which are not recognized as object files or
     archives.  Return TRUE if the file was handled.  */
  bfd_boolean (*unrecognized_file)
    (struct lang_input_statement_struct *);  // 21

  /* Run to list the command line options which parse_args handles.  */
  void (* list_options) (FILE *);  // 22

  /* Run to specially handle files which *are* recognized as object
     files or archives.  Return TRUE if the file was handled.  */
  bfd_boolean (*recognized_file)
    (struct lang_input_statement_struct *);  // 23

  /* Called when looking for libraries in a directory specified
     via a linker command line option or linker script option.
     Files that match the pattern "lib*.a" have already been scanned.
     (For VMS files matching ":lib*.a" have also been scanned).  */
  int (* find_potential_libraries)
    (char *, struct lang_input_statement_struct *);  // 24

  /* Called when adding a new version pattern.  PowerPC64-ELF uses
     this hook to add a pattern matching ".foo" for every "foo".  */
  struct bfd_elf_version_expr * (*new_vers_pattern)
    (struct bfd_elf_version_expr *);  // 25

  /* Called when printing the map file, in case there are
     emulation-specific sections for it.  */
  void (*extra_map_file_text)
    (bfd *, struct bfd_link_info *, FILE *);  // 26

} ld_emulation_xfer_type;

二、lang_place_undefineds ()

将命令行中所有未定义的符号加入哈希表中

结构体类型:

struct bfd_sym_chain

  • 这是一个结构体定义,表示符号链的链接列表节点。每个节点包含指向下一个节点的指针和指向字符字符串的指针(可能是符号名称)。

  • typedef struct bfd_sym_chain ldlang_undef_chain_list_type

  • 这行代码为struct bfd_sym_chain创建了类型别名ldlang_undef_chain_list_type,以便更容易使用和声明这种类型的变量。

  • #define ldlang_undef_chain_list_head entry_symbol.next

  • 这似乎是一个预处理器宏,将ldlang_undef_chain_list_head定义为entry_symbol.next。它可能用作访问符号链节点的next字段的简写。

cpp 复制代码
struct bfd_sym_chain
{
  struct bfd_sym_chain *next;
  const char *name;
};

typedef struct bfd_sym_chain ldlang_undef_chain_list_type;

#define ldlang_undef_chain_list_head entry_symbol.next
函数:

static void lang_place_undefineds(void)

  • 这是一个函数定义的开始,名为lang_place_undefineds。它是一个静态函数,意味着它仅限于当前的翻译单元。这个函数的目的是遍历未定义符号(ldlang_undef_chain_list_type)的列表,并为每个符号的名称调用insert_undefined
cpp 复制代码
static void
lang_place_undefineds (void)
//   /* Add to the hash table all undefineds on the command line.  */
{
  ldlang_undef_chain_list_type *ptr;

  for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
    insert_undefined (ptr->name);
}

static void insert_undefined(const char *name)

  • 这是另一个静态函数定义,名为insert_undefined。它以字符串(name)作为参数。这个函数的目的是将未定义符号插入符号表中。它首先使用bfd_link_hash_lookup在哈希表中查找符号,如果找不到,则使用bfd_link_add_undef添加它。
cpp 复制代码
/* Insert NAME as undefined in the symbol table.  */

static void
insert_undefined (const char *name)
{
  struct bfd_link_hash_entry *h;

  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
  if (h == NULL)
    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
  if (h->type == bfd_link_hash_new)
    {
      h->type = bfd_link_hash_undefined;
      h->u.undef.abfd = NULL;
      bfd_link_add_undef (link_info.hash, h);
    }
}

bfd_link_hash_lookupbfd_hash_lookup函数:

  • 这些函数用于在哈希表中查找条目。bfd_link_hash_lookup似乎用于在符号哈希表中查找条目,而bfd_hash_lookup是一个更一般的哈希表查找函数。这些函数通过对输入字符串进行哈希并在哈希表中搜索相应的条目来工作。

  • bfd_hash_insert函数:

  • 此函数用于将新条目插入哈希表。它为条目分配内存,计算哈希值,并将条目插入哈希表的适当位置。如果需要,它还处理表的大小调整。

cpp 复制代码
struct bfd_link_hash_entry *
bfd_link_hash_lookup (struct bfd_link_hash_table *table,
		      const char *string,
		      bfd_boolean create,  // T
		      bfd_boolean copy,  // F
		      bfd_boolean follow)  // T
{
  struct bfd_link_hash_entry *ret;

  ret = ((struct bfd_link_hash_entry *)
	 bfd_hash_lookup (&table->table, string, create, copy));

  if (follow && ret != NULL)
    {
      while (ret->type == bfd_link_hash_indirect
	     || ret->type == bfd_link_hash_warning)
	ret = ret->u.i.link;
    }

  return ret;
}
cpp 复制代码
struct bfd_hash_entry *
bfd_hash_lookup (struct bfd_hash_table *table,
		 const char *string,
		 bfd_boolean create,  // T
		 bfd_boolean copy)  // F
{
  unsigned long hash;
  struct bfd_hash_entry *hashp;
  unsigned int len;
  unsigned int _index;

  hash = bfd_hash_hash (string, &len);
  _index = hash % table->size;
  for (hashp = table->table[_index];
       hashp != NULL;
       hashp = hashp->next)
    {
      if (hashp->hash == hash
	  && strcmp (hashp->string, string) == 0)
	return hashp;
    }

  if (! create)
    return NULL;

  if (copy)
    {
      char *new_string;

      new_string = (char *) objalloc_alloc ((struct objalloc *) table->memory,
                                            len + 1);
      if (!new_string)
	{
	  bfd_set_error (bfd_error_no_memory);
	  return NULL;
	}
      memcpy (new_string, string, len + 1);
      string = new_string;
    }

  return bfd_hash_insert (table, string, hash);
}
cpp 复制代码
struct bfd_hash_entry *
bfd_hash_insert (struct bfd_hash_table *table,
		 const char *string,
		 unsigned long hash)
{
  struct bfd_hash_entry *hashp;
  unsigned int _index;

  hashp = (*table->newfunc) (NULL, table, string);
  if (hashp == NULL)
    return NULL;
  hashp->string = string;
  hashp->hash = hash;
  _index = hash % table->size;
  hashp->next = table->table[_index];
  table->table[_index] = hashp;
  table->count++;

  if (!table->frozen && table->count > table->size * 3 / 4)
    {
      unsigned long newsize = higher_prime_number (table->size);
      struct bfd_hash_entry **newtable;
      unsigned int hi;
      unsigned long alloc = newsize * sizeof (struct bfd_hash_entry *);

      /* If we can't find a higher prime, or we can't possibly alloc
	 that much memory, don't try to grow the table.  */
      if (newsize == 0 || alloc / sizeof (struct bfd_hash_entry *) != newsize)
	{
	  table->frozen = 1;
	  return hashp;
	}

      newtable = ((struct bfd_hash_entry **)
		  objalloc_alloc ((struct objalloc *) table->memory, alloc));
      if (newtable == NULL)
	{
	  table->frozen = 1;
	  return hashp;
	}
      memset (newtable, 0, alloc);

      for (hi = 0; hi < table->size; hi ++)
	while (table->table[hi])
	  {
	    struct bfd_hash_entry *chain = table->table[hi];
	    struct bfd_hash_entry *chain_end = chain;

	    while (chain_end->next && chain_end->next->hash == chain->hash)
	      chain_end = chain_end->next;

	    table->table[hi] = chain_end->next;
	    _index = chain->hash % newsize;
	    chain_end->next = newtable[_index];
	    newtable[_index] = chain;
	  }
      table->table = newtable;
      table->size = newsize;
    }

  return hashp;
}
相关推荐
小安运维日记25 分钟前
Linux云计算 |【第四阶段】NOSQL-DAY1
linux·运维·redis·sql·云计算·nosql
kejijianwen1 小时前
JdbcTemplate常用方法一览AG网页参数绑定与数据寻址实操
服务器·数据库·oracle
limingade2 小时前
手机实时提取SIM卡打电话的信令和声音-新的篇章(一、可行的方案探讨)
物联网·算法·智能手机·数据分析·信息与通信
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
2401_858286113 小时前
52.【C语言】 字符函数和字符串函数(strcat函数)
c语言·开发语言
铁松溜达py3 小时前
编译器/工具链环境:GCC vs LLVM/Clang,MSVCRT vs UCRT
开发语言·网络
everyStudy3 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
CoolTiger、3 小时前
【Vmware16安装教程】
linux·虚拟机·vmware16
jiao000014 小时前
数据结构——队列
c语言·数据结构·算法
C-SDN花园GGbond4 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法