GNU ld链接器 lang_process()(二)

一、ldemul_create_output_section_statements()

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

void
ldemul_create_output_section_statements (void)
{
  if (ld_emulation->create_output_section_statements)
    ld_emulation->create_output_section_statements ();
}
static ld_emulation_xfer_type *ld_emulation;
  /* Create any output sections needed by the target.  */
  void	(*create_output_section_statements) (void);  // 14
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字段的简写。
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
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添加它。

 

/* 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函数:

  • 此函数用于将新条目插入哈希表。它为条目分配内存,计算哈希值,并将条目插入哈希表的适当位置。如果需要,它还处理表的大小调整。
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;
}
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);
}
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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/116977.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库之表的增删查改

目录 表的操作1.创建表创建表案例 2.查看表结构3.修改表4.删除表 表的操作 1.创建表 语法&#xff1a; CREATE TABLE table_name (field1 datatype,field2 datatype,field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明&#xff1a; field 表示列…

C# 基类中的虚函数调用基类的虚函数执行的是派生类实现的对应函数吗

答案 &#xff1a; 是的。 比如基类Base中有两个virtual 函数A和B&#xff0c;然后派生类为Derive&#xff0c;override了函数A记为A&#xff0c;override了函数B记为B&#xff0c;且B之中会执行base.B的逻辑&#xff1b; 在Base中&#xff0c;B调用了A的逻辑&#xff0c;那么外…

C++ 实现红黑树

红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍&#xff0c;因…

通过环境变量实现多个JDK切换

前文: 由于jdk版本需要升级为jdk17,因为jdk8比较常用且稳定,本人又不想卸载掉安装的jdk8,在经过查找资料后找到了可以通过修改环境变量在本地任意切换jdk版本 环境变量配置 网上教程一堆,直接跳过了,这里主要说明怎么通过配置环境变量切换 电脑->属性->高级系统设置-&g…

centos7中多版本go安装

安装go的方式 官网下载tar.gz包安装 # 1.下载tar包 wget https://go.dev/dl/go1.18.1.linux-amd64.tar.gz # 2.解压tar包到指定路径 tar -xvf go1.18.1.linux-amd64.tar.gz -C /usr/local/go1.18 # 3.配置环境变量&#xff0c;打开 /etc/profile 文件添加以下文件每次开机时…

【MATLAB源码-第65期】基于matlab的OFDM/OTFS通信系统性能对比,输处误码率曲线;对比是否采用LDPC编码。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OTFS&#xff08;Orthogonal Time Frequency Space&#xff09;是一种无线通信调制技术&#xff0c;它利用时间、频率和空间的正交性来传输数据&#xff0c;目的是提高无线通信系统的性能&#xff0c;尤其是在多径和高移动性环…

selenium自动化测试入门 —— 定位frame和iframe中的元素对象

< frame> <iframe> 标签&#xff0c;浏览器会在标签中打开一个特定的页面窗口&#xff08;框架&#xff09;&#xff0c;它在本窗口中嵌套进入一个网页&#xff0c;当用selenium定位页面元素的时候会遇到定位不到frame框架内的元素的问题。 定位frame中的元素前我…

node插件express(路由)的插件使用(二)——body-parser和ejs插件的基本使用

文章目录 前言一、express使用中间件body-parser获取请全体的数据1. 代码2. 效果 二、express使用ejs&#xff08;了解即可&#xff09;1.安装2.作用3.基本使用&#xff08;1&#xff09;代码&#xff08;2&#xff09;代码分析和效果 4.列表渲染&#xff08;1&#xff09;代码…

同步网盘与云盘:哪个更好用?

同步网盘、同步云盘现在是热门的文件管理工具&#xff0c;在回答“同步网盘云盘哪个好用”这个问题之前&#xff0c;我们需要知道什么样的同步网盘、同步云盘算好用&#xff1f; 什么样的同步网盘云盘好用&#xff1f; 1、存储空间大 对于文件管理工具而言&#xff0c;存储空…

从零开始学习PX4源码0(固件下载及编译)

目录 文章目录 目录摘要1.重点学习网址2.固件下载1.下载最新版本固件2.下载之前版本固件 摘要 本节主要记录从零开始学习PX4源码1(固件下载)的过程&#xff0c;欢迎批评指正&#xff01;&#xff01;&#xff01; 下载固件主要分为两个版本&#xff0c;之前稳定版本和最新官网…

3、Sentinel 动态限流规则

Sentinel 的理念是开发者只需要关注资源的定义&#xff0c;当资源定义成功后可以动态增加各种流控降级规则。Sentinel 提供两种方式修改规则&#xff1a; • 通过 API 直接修改 (loadRules) • 通过 DataSource 适配不同数据源修改 通过 API 修改比较直观&#xff0c;可以通…

C#中LINQtoSQL只能在.NetFramework下使用,不能在.net 下使用

目录 一、在net7.0下无法实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 二、在.NetFramework4.8下成功实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 三、结论 四、理由 本文是个人观点&#xff0c;因为我百般努力在.net7.0下无法实现LINQtoSQL的…

如何将 XxlJob 集成达梦数据库

1. 前言 在某些情况下&#xff0c;你的项目可能会面临数据库选择的特殊要求&#xff0c;随着国产化的不断推进&#xff0c;达梦数据库是一个常见的选择。本篇博客将教你如何解决 XxlJob 与达梦数据库之间的 SQL 兼容性问题&#xff0c;以便你的任务调度系统能够在这个数据库中…

Idea去掉显示的测试覆盖率

一.启东时 误点击了 快捷键调出 【Ctrl 】【Alt】【F6】

npm ERR! code ELIFECYCLE

问题&#xff1a; 一个老项目&#xff0c;现在想运行下&#xff0c;打不开了 npm install 也出错 尝试1 、使用cnpm npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install 还是不行 尝试2、 package.json 文件&#xff0c;去掉 那个插件 chorm…

Unity中Shader的GI的直接光实现

文章目录 前言一、在上一篇文章中&#xff0c;得到GI相关数据后&#xff0c;需要对其进行Lambert光照模型计算二、在准备好上面步骤后&#xff0c;我们需要准备缺少的数据1、准备上图中的 s.Normal2、准备上图中的 s.Albedo 前言 Unity中Shader的GI的直接光实现&#xff0c;基…

基于springboot实现在线考试平台项目【项目源码+论文说明】

基于springboot实现在线考试平台管理系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合&#xff0c;利用java技术建设在线考试系统&#xff0c;实现在线考试的信息化。则对于进一步提高在线考试管理发展&#xff0c;丰富在线考试管理经…

【计算机网络】同源策略及跨域问题

1. 同源策略 同源策略是一套浏览器安全机制&#xff0c;当一个源的文档和脚本&#xff0c;与另一个源的资源进行通信时&#xff0c;同源策略就会对这个通信做出不同程度的限制。 同源策略对 同源资源 放行&#xff0c;对 异源资源 限制。因此限制造成的开发问题&#xff0c;称…

OkHttp库爬取百度云视频详细步骤

以下是使用OkHttp库的Kotlin爬虫程序&#xff0c;该爬虫用于爬取百度云的视频。 首先&#xff0c;我们需要导入OkHttp库和Kotlin库。import okhttp3.OkHttpClient和import kotlin.jvm.JVM。 import okhttp3.OkHttpClient import kotlin.jvm.JVM然后&#xff0c;我们需要创建一…

单片机温湿度-光照-DHT11-烟雾气体检测控制系统-proteus仿真-源程序

一、系统方案 本设计采用52单片机作为主控器&#xff0c;液晶1602显示&#xff0c;DHT11温湿度&#xff0c;光照、烟雾气体检测&#xff0c;按键设置报警阀值&#xff0c;蜂鸣器报警。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 // // …