Linux:符号和符号表

news2024/12/25 1:01:57

文章目录

  • 什么是符号?
  • 什么是符号表?
  • 全局符号和本地符号
    • 1. 全局符号:
      • symtab符号表
    • 2. 本地符号:
  • 符号在汇编阶段
  • 符号在链接阶段
    • 1.由模块 m 定义并能被其他模块引用的全局符号。
    • 2.由其他模块定义并被模块 m 引用的全局符号。
    • 3.只被模块 m 定义和引用的局部符号。
      • static 本地变量
  • QA:
    • 编译器和汇编器的区别?
    • 编译器包含汇编器吗?

什么是符号?

想象一下你在学校里,老师在黑板上写了一些字母和数字,比如"A"、“B”、“1”、“2”。这些字母和数字就是符号。在计算机编程或数学中,符号就是用来代表某个特定概念或值的标记。

举个例子,假设你写了一个计算机程序,里面有一个变量叫做"score",用来表示游戏中的分数。在这里,"score"就是一个符号,它代表了一个特定的值,即分数。

符号可以是字母、数字或其他字符的组合,它们被赋予特定的含义,让程序员或计算机能够理解并操作这些符号代表的信息。所以,通俗地说,符号就是一种用来代表东西的标记,让计算机或人能够更方便地理解和处理信息。

什么是符号表?

想象一下你在读一本书,遇到一个生词,你可能会查字典来找到这个词的解释和意义。符号表就有点像是一本程序的字典,但是不是用来解释生词的,而是用来解释程序中用到的各种符号、变量、函数等等。

在计算机程序中,我们使用各种符号(比如变量名、函数名)来表示不同的东西,就像字典中的单词一样。符号表就记录了这些符号对应的信息,比如变量的数据类型、函数的参数类型、以及它们在内存中的位置等等。

当计算机执行程序时,会根据符号表中的信息来理解和处理这些符号,就像你在阅读一本书时根据字典来理解生词一样。符号表有助于编程语言的解释器或编译器理解程序的结构和含义,使得计算机能够正确地执行你写的代码。

全局符号和本地符号

在编程中,有两种主要类型的符号:全局符号和本地符号。全局符号是在整个程序中都可见的,而本地符号仅在特定的作用域内可见。在链接器的上下文中,我们通常将这些符号称为外部符号和本地符号。

1. 全局符号:

  • 全局变量和函数是一种全局符号。它们可以在不同的文件中定义,并在整个程序中共享。
  • 链接器对全局符号感兴趣,因为它们需要在不同的目标文件之间解析引用关系,确保这些全局符号的定义能够正确地链接在一起。

symtab符号表

symtab 是符号表(Symbol Table)的缩写,用于存储程序中变量、函数和其他符号信息的数据结构。

关于 .symtab 中的符号表,它主要包含与全局符号相关的信息,因为链接器主要负责解决全局符号之间的引用关系。

本地符号,特别是本地非静态程序变量,通常不包含在符号表中,因为它们在运行时通过栈进行管理,链接器不需要关心这些细节。

这种分离全局和本地符号的处理方式有助于提高链接器的效率,并确保在链接阶段解决全局符号的引用关系时不会受到本地符号的干扰。

认识到本地链接器符号和本地程序变量不同是很重要的。
.symtab 中的符号表不包含对应于本地非静态程序变量的任何符号。这些符号在运行时在栈中被管理,链接器对此类符号不感兴趣。

.symtab 节中包含 ELF 符号表。这张符号表包含一个条目的数组。图 7-4 展示了每个条目的格式。
在这里插入图片描述
name是字符串表中的字节偏移,指向符号的以null结尾的字符串名字。

value 是符号的地址。对于可重定位的模块来说,value 是距定义目标的节的起始位置的偏移。对于可执行目标文件来说,该值是一个绝对运行时地址。

size 是目标的大小(以字节为单位)。

type 通常要么是数据,要么是函数。符号表还可以包含各个节的条目,以及对应原始源文件的路径名的条目。所以这些目标的类型也有所不同。

binding 字段表示符号是本地的还是全局的。

2. 本地符号:

  • 本地变量和本地函数是一种本地符号。它们通常只在定义它们的特定代码块(如函数)内部可见。
  • 链接器对本地符号不感兴趣,因为它们不需要在不同的目标文件之间解析引用关系。本地符号的生命周期通常限定在其定义的作用域内,例如在函数的栈帧中。

符号在汇编阶段

编译器在处理源代码时,会将源代码转换为汇编语言代码,然后将汇编语言代码输出到.s文件中。在输出的.s文件中,编译器还会将源代码中所有的函数、变量和常量等符号标记,并生成一个符号表,包含了这些符号的信息,如位置、大小等。

这些符号将在后续的汇编和链接过程中起到重要的作用,比如在汇编过程中,汇编器会根据符号表中所包含的信息来解析和生成目标二进制代码。

汇编器的作用主要有以下几个方面:

  1. 将汇编语言代码转换为机器语言代码:汇编器通过读取汇编代码源文件并将其转换为机器语言代码,创建目标文件,这个文件包含二进制代码和其他与代码相关的元信息。

  2. 符号解析:汇编器通过符号表解析代码中出现的符号,如函数和变量,以便能够正确地连接和重定位代码。

  3. 代码调试:汇编器生成的目标文件中包含了关于代码的调试信息,可以被调试器用来调试代码。

  4. 优化代码:汇编器可以通过优化代码来提高代码的执行效率,例如,通过使用更快的指令集或者重排指令的执行顺序。

符号在链接阶段

每个可重定位目标模块,我们姑且命名一个目标模块为m。

那么,模块m都有一个符号表,它包含模块m 定义和引用的符号的信息。

在链接器的上下文中,有三种不同的符号:

1.由模块 m 定义并能被其他模块引用的全局符号。

全局链接器符号对应于非静态的 C函数和全局变量。

2.由其他模块定义并被模块 m 引用的全局符号。

这些符号称为外部符号,对应于在其他模块中定义的非静态 C 函数和全局变量。

3.只被模块 m 定义和引用的局部符号。

它们对应于带 static 属性的 C函数和全局变量。这些符号在模块 m 中任何位置都可见,但是不能被其他模块引用。

static 本地变量

有趣的是,定义为带有 C static 属性的本地过程变量是不在栈中管理的。

相反,编译器在.data或bss 中为每个定义分配空间,并在符号表中创建一个有唯一名字的本地链接器符号。

比如,假设在同一模块中的两个函数各自定义了一个静态局部变量 x:

下面是一个示例代码,展示了在同一模块中的两个函数各自定义了一个静态局部变量 x,并且这些变量在.data或bss段中分配空间,而不是在栈中管理:

#include <stdio.h>

void function1() {
    static int x = 1;
    printf("Function 1: x = %d\n", x);
    x++;
}

void function2() {
    static int x = 10;
    printf("Function 2: x = %d\n", x);
    x--;
}

int main() {
    function1();
    function1();
    function2();
    function2();
    function1();

    return 0;
}

输出结果:

Function 1: x = 1
Function 1: x = 2
Function 2: x = 10
Function 2: x = 9
Function 1: x = 3

可以看到,每个函数的静态局部变量都保留了它们的状态,并且它们在每个函数调用之间都保留了它们的值。这是因为它们在.data或bss段中分配了空间,而不是在栈中管理。

注意:
利用 static 属性隐藏变量和函数名字: C程序员使用 static属性隐藏模块内部的变量和函数声明,就像你在Java 和C++中使用
public和 private 声明一样。

在C中,源文件扮演模块的角色。任何带有static属性声明的全局变量或者函数都是模块私有的。类似地,任何不带 static
属性声明的全局变量和函数都是公共的,可以被其他模块访问。尽可能用 static 属性来保护你的变量和函数是很好的编程习惯。

QA:

编译器和汇编器的区别?

编译器和汇编器都是程序开发中使用的工具,但它们的功能不同,具体区别如下:

  1. 编译器和汇编器的语言级别不同。编译器通常用来将高级语言(如C、C++、Java等)转换为汇编语言或者机器语言,而汇编器是把汇编语言转换为机器语言。

  2. 编译器和汇编器的输入和输出不同。编译器的输入是高级语言源代码,输出是汇编语言或者机器语言代码;而汇编器的输入是汇编语言代码,输出是机器语言代码。

  3. 编译器和汇编器的编译过程不同。编译器会对源代码进行词法分析、语法分析、优化和生成目标代码等多个阶段的处理,而汇编器只是简单地将汇编语言代码翻译成机器语言代码。

  4. 编译器和汇编器的处理粒度不同。编译器处理的粒度更大,它会对整个程序进行处理,包括程序中的所有函数、变量和常量等;而汇编器处理的粒度更小,它只是针对单个汇编模块进行处理。

编译器包含汇编器吗?

在一些编译器中,汇编器的功能是由编译器自身来实现的,这些编译器被称为“集成编译器”或“自包含编译器”(self-contained compiler)。这种编译器可以直接将高级语言源代码转化成目标机器的机器语言代码,而不需要借助其他汇编器的支持。

但也有一些编译器是不包含汇编器的。在这种情况下,编译器只负责将高级语言源代码转换成汇编语言代码,然后再使用独立的汇编器将汇编语言代码转换成机器语言代码。这种分离的方式可以让用户有更多的选择,可以灵活地选择不同的汇编器来适应不同的需求。

是否包含汇编器取决于不同的编译器实现,而不是编译器的必要组成部分。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI跨界学习,不再是梦!

大家好&#xff01;今天给大家推荐的 GPTs 是【行业知识脉络】&#xff0c;帮助大家快速了解某个领域的脉络&#xff0c;并提供足够的学习资料和建议。 在AI时代&#xff0c;从小白到专家的1万小时定律即将失效&#xff0c;用少于1千小时掌握行业知识树和其核心概念是如何学习的…

Python Selenium3 自动化测试实战:构建高效测试项目

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今软件开发领域&#xff0c;自动化测试成为…

310v转5v 1A 4G模块供电稳压芯片-AH8665

AH8665是一个高性能的稳压芯片&#xff0c;适用于将310V输入电压转换为5V 1A的输出电压&#xff0c;为4G模块提供稳定的电源供应。该芯片具有出色的稳定性能、高效转换效率和紧凑的外形尺寸&#xff0c;广泛应用于通信、物联网等领域。 AH8665芯片采用先进的低压差线性稳压器&…

【新手解答9】深入探索 C 语言:递归与循环的应用2

C语言的相关问题解答 写在最前面问题交流递归和循环if-else 和循环的结合 递归中的 if-else例子 递归是否形成循环&#xff1f;可以理解为特殊形式的循环递归示例&#xff1a;计算阶乘递归与循环的区别 结论 写在最前面 一位粉丝私信交流&#xff0c;回想起了当初的我C语言一题…

2012-12-12 下载ndk编译出so和可执行文件,放到android 真机运行,包含源码。

一、下载ndk链接NDK 下载 | Android NDK | Android Developers 二、解压ndk后得到下面的文件&#xff0c;里面包含ndk-build.cmd&#xff0c;这个是用来编译的。 三、Android.mk和C源码。完整源码下载路径https://download.csdn.net/download/qq_37858386/88622702 3.1 A…

SD-WAN是怎样实现SaaS性能优化的?

在数字化时代&#xff0c;SaaS应用已经成为许多企业不可或缺的核心业务工具。为实现高效的SaaS应用和卓越的用户体验&#xff0c;企业可考虑采用SD-WAN技术。通过就近访问、智能带宽管理、多路径冗余、高级安全和简化的管理监控&#xff0c;SD-WAN为企业带来显著价值。 1. 就近…

单域名https证书怎么申请

单域名https证书可以保护www和两个域名记录&#xff0c;如果保护的域名是子域名时&#xff0c;只能保护一个子域名。单域名https证书能够为网站提供加密的HTTPS连接&#xff0c;保护网站的数据安全。今天随SSL盾小编了解单域名https证书的申请。 1. 确定证书类型&#xff1a;根…

python自动下载网页中的文件,python 自动下载脚本

本篇文章给大家谈谈python自动下载文件 下载的不完整&#xff0c;以及python登录网站自动下载文件&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 问题描述 Python自动下载文件&#xff0c;通用文件&#xff0c;包括但不限于压缩文件、图片等。 解决方法 一般…

隐语开源|周爱辉:隐语 TEE 技术解读与跨域管控实践

“隐语”是开源的可信隐私计算框架&#xff0c;内置 MPC、TEE、同态等多种密态计算虚拟设备供灵活选择&#xff0c;提供丰富的联邦学习算法和差分隐私机制 开源项目 github.com/secretflow gitee.com/secretflow 11月25日&#xff0c;「隐语开源社区 Meetup西安站」顺利举办&…

【动态规划】03斐波那契数列模型_最小花费爬楼梯_C++(easy1)

题目链接&#xff1a;leetcode使用最小花费爬楼梯 目录 题目解析&#xff1a; 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析&#xff1a; 题目让我们求达到楼梯顶部的最低花费. 由题可得&#xff1a; cost[i] 是从楼梯第 i 个…

【EMQX】通过EMQX webhook实现转发消息到Python web服务器

EMQX webhook消息转发Web服务器 一、前言二、实现1、EMQX服务器搭建EMQX下载、安装、启动 2、本地Web服务搭建创建Flask项目代码 3、EMQX中创建webhook数据桥接4、EMQX中创建数据转发规则 三、效果 一、前言 需求&#xff1a;获取设备通过mqtt协议发送过来的数据并将数据保存到…

【sqli靶场】第四关和第五关通关思路

目录 前言 一、sqli靶场第四关 1.1 判断注入类型 1.2 观察报错 1.3 判断数据表中的列数 1.4 使用union联合查询 1.5 使用group_concat()函数 二、sqli靶场第五关 2.1 判断注入类型 2.2 使用extractvalue函数报错 2.3 爆出数据库中的表名 2.4 爆出users表中的列名 2.5 爆出use…

异地现场工控设备,如何实现远程配置、调试?

南京某企业专注于工业物联领域&#xff0c;在相关项目中往往会在各个点位部署基于Linux系统的中控主机&#xff0c;实现各类物联设备信息的采集、汇总。但是&#xff0c;由于各点位分散多地&#xff0c;且数量达到了上百个&#xff0c;虽然中控主机具备4G物联网接入能力&#x…

Java设计模式-单例(Singleton)设计模式的概述及实现

目录 &#x1f436;1 设计模式概述 &#x1f436;2 何为单例模式 &#x1f436;3 实现思路 &#x1f436;4 饿汉式实现代码 &#x1f436;5 懒汉式实现代码 &#x1f436;6 对比两种模式&#xff08;特点、优缺点&#xff09; &#x1f436;7 单例模式的优点及应用场景 &…

系统提示:comres.dll丢失怎么办,comres.dll丢失的解决方法

comres.dll是Windows操作系统中一个非常重要的动态链接库文件&#xff0c;它负责提供一些重要的功能和资源。当这个文件丢失或损坏时&#xff0c;可能会导致一系列的问题和影响。本文将介绍comres.dll文件丢失对电脑的影响以及comres.dll丢失的原因&#xff0c;并提供5个解决方…

数据科学工作的20个Pandas函数(备忘)

Pandas 是数据科学社区中使用最广泛的库之一&#xff0c;它是一个强大的工具&#xff0c;可以进行数据操作、清理和分析。 本文将提供最常用的 Pandas 函数以及如何实际使用它们的样例。我们将涵盖从基本数据操作到高级数据分析技术的所有内容&#xff0c;到本文结束时&#xf…

Fnac、Darty跨境利用利用自养号测评补单提升销量和排名

Fnac是法国最有名字的零售商之一&#xff0c;成立于1954年&#xff0c;也是欧洲增长最快的平台之一&#xff0c;2016年&#xff0c;Fnac并购Darty&#xff0c;同时在自己的网站上添加了Darty板块&#xff0c;FnacDarty集团正式成立 国内的产品在Fnac&#xff0c;Darty平台上还…

使用shell脚本将一台虚拟机上面数据分发到其他虚拟机上面xsync

目录 1&#xff0c;功能2&#xff0c;注意点3&#xff0c;shell脚本介绍4&#xff0c;bash内容 1&#xff0c;功能 使用shell脚本将一台虚拟机上面数据分发到其他虚拟机上面。 2&#xff0c;注意点 需要修改的地方&#xff1a;hadoop250 hadoop251 hadoop252 hadoop253 hado…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(1.结构与源码概述)

在文章【Redis】不卡壳的 Redis 学习之路&#xff1a;从十大数据类型开始入手中我们介绍了Redis常用的10大数据类型&#xff0c;这10大数据类型可并不是直接在底层通过代码实现的&#xff0c;而是通过不同的底层数据结构组合起来的&#xff0c;这篇我们介绍下Redis常用数据类型…

多域名和通配符SSL证书的区别

域名SSL证书和通配符SSL证书都是SSL数字证书中用一张证书保护多个域名站点的证书产品&#xff0c;这两种类型的SSL数字证书各自有各自的特色&#xff0c;今天就随SSL盾小编了解多域名SSL证书和通配符SSL证书的区别。 1.保护的域名类型不同&#xff1a;多域名SSL证书默认保护3-…