gcc 源码阅读--全局符号表管理

C/C++程序编译全流程解析:从源码到可执行文件的完整链路 在软件开发领域,编译是将高级语言代码转换为机器可执行指令的核心过程。其基本原理涉及将人类可读的源代码通过一系列自动化阶段,最终生成可在特定硬件上运行的二进制程序。从技术价值看,深入理解编译流程不仅能帮助开发者高效定位编译错误和链接问题,更是进行程序性能优化和复杂项目依赖管理的基础。在实际应用场景中,无论是桌面应用、嵌入式系统还是高性能服务器开发,掌握编译链路的四个核心阶段——预处理、编译、汇编和链接——都至关重要。本文聚焦于GCC和Clang/LLVM两大主流工具链,通过解析目标文件格式、静态库与动态库的创 阅读详情

重点查看几个类的定义

enum symtab_type
{
  SYMTAB_SYMBOL,
  SYMTAB_FUNCTION,
  SYMTAB_VARIABLE
};

/* Base of all entries in the symbol table.
   The symtab_node is inherited by cgraph and varpol nodes.  */
struct 
  symtab_node

{
public:
  friend class symbol_table;

  /* Constructor.  */
  explicit symtab_node (symtab_type t)
    : type (t), resolution (LDPR_UNKNOWN), definition (false), alias (false),
      transparent_alias (false), weakref (false), cpp_implicit_alias (false),
      symver (false), analyzed (false), writeonly (false),
      refuse_visibility_changes (false), externally_visible (false),
      no_reorder (false), force_output (false), forced_by_abi (false),
      unique_name (false), implicit_section (false), body_removed (false),
      semantic_interposition (flag_semantic_interposition),
      used_from_other_partition (false), in_other_partition (false),
      address_taken (false), in_init_priority_hash (false),
      need_lto_streaming (false), offloadable (false), ifunc_resolver (false),
      order (-1), next_sharing_asm_name (NULL),
      previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (),
      alias_target (NULL), lto_file_data (NULL), aux (NULL),
      x_comdat_group (NULL_TREE), x_section (NULL), m_uid (-1)
  {}

  /* Return name.  */
  const char *name () const;

  /* Return dump name.  */
  const char *dump_name () const;

  /* Return asm name.  */
  const char *asm_name () const;

  /* Return dump name with assembler name.  */
  const char *dump_asm_name () const;

  /* Return visibility name.  */
  const char *get_visibility_string () const;

  /* Return type_name name.  */
  const char *get_symtab_type_string () const;

  /* Add node into symbol table.  This function is not used directly, but via
     cgraph/varpool node creation routines.  */
  void register_symbol (void);

  /* Remove symbol from symbol table.  */
  void remove (void);

  /* Undo any definition or use of the symbol.  */
  void reset (bool preserve_comdat_group = false);

  /* Dump symtab node to F.  */
  void dump (FILE *f);

  /* Dump symtab callgraph in graphviz format.  */
  void dump_graphviz (FILE *f);

  /* Dump symtab node to stderr.  */
  void DEBUG_FUNCTION debug (void);

  /* Verify consistency of node.  */
  void DEBUG_FUNCTION verify (void);

  /* Return ipa reference from this symtab_node to
     REFERRED_NODE or REFERRED_VARPOOL_NODE. USE_TYPE specify type
     of the use and STMT the statement (if it exists).  */
  ipa_ref *create_reference (symtab_node *referred_node,
                 enum ipa_ref_use use_type);

  /* Return ipa reference from this symtab_node to
     REFERRED_NODE or REFERRED_VARPOOL_NODE. USE_TYPE specify type
     of the use and STMT the statement (if it exists).  */
  ipa_ref *create_reference (symtab_node *referred_node,
                 enum ipa_ref_use use_type, gimple *stmt);

  /* If VAL is a reference to a function or a variable, add a reference from
     this symtab_node to the corresponding symbol table node.  Return the new
     reference or NULL if none was created.  */
  ipa_ref *maybe_create_reference (tree val, gimple *stmt);

  /* Clone all references from symtab NODE to this symtab_node.  */
  void clone_references (symtab_node *node);

  /* Remove all stmt references in non-speculative references.
     Those are not maintained during inlining & clonning.
     The exception are speculative references that are updated along
     with callgraph edges associated with them.  */
  void clone_referring (symtab_node *node);

  /* Clone reference REF to this symtab_node and set its stmt to STMT.  */
  ipa_ref *clone_reference (ipa_ref *ref, gimple *stmt);

  /* Find the structure describing a reference to REFERRED_NODE of USE_TYPE and
     associated with statement STMT or LTO_STMT_UID.  */
  ipa_ref *find_reference (symtab_node *referred_node, gimple *stmt,
               unsigned int lto_stmt_uid,
               enum ipa_ref_use use_type);

  /* Remove all references that are associated with statement STMT.  */
  void remove_stmt_references (gimple *stmt);

  /* Remove all stmt references in non-speculative references.
     Those are not maintained during inlining & clonning.
     The exception are speculative references that are updated along
     with callgraph edges associated with them.  */
  void clear_stmts_in_references (void);

  /* Remove all references in ref list.  */
  void remove_all_references (void);

  /* Remove all referring items in ref list.  */
  void remove_all_referring (void);

  /* Dump references in ref list to FILE.  */
  void dump_references (FILE *file);

  /* Dump referring in list to FILE.  */
  void dump_referring (FILE *);

  /* Get number of references for this node.  */
  inline unsigned num_references (void)
  {
    return ref_list.references.length ();
  }

  /* Iterates I-th reference in the list, REF is also set.  */
  ipa_ref *iterate_reference (unsigned i, ipa_ref *&ref);

  /* Iterates I-th referring item in the list, REF is also set.  */
  ipa_ref *iterate_referring (unsigned i, ipa_ref *&ref);

  /* Iterates I-th referring alias item in the list, REF is also set.  */
  ipa_ref *iterate_direct_aliases (unsigned i, ipa_ref *&ref);

  /* Return true if symtab node and TARGET represents
     semantically equivalent symbols.  */
  bool semantically_equivalent_p (symtab_node *target);

  /* Classify symbol symtab node for partitioning.  */
  enum symbol_partitioning_class get_partitioning_class (void);

  /* Return comdat group.  */
  tree get_comdat_group ()
    {
      return x_comdat_group;
    }

  /* Return comdat group as identifier_node.  */
  tree get_comdat_group_id ()
    {
      if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE)
    x_comdat_group = DECL_ASSEMBLER_NAME (x_comdat_group);
      return x_comdat_group;
    }

  /* Set comdat group.  */
  void set_comdat_group (tree group)
    {
      gcc_checking_assert (!group || TREE_CODE (group) == IDENTIFIER_NODE
               || DECL_P (group));
      x_comdat_group = group;
    }

  /* Return section as string.  */
  const char * get_section () const
    {
      if (!x_section)
    return NULL;
      return x_section->name;
    }

  /* Remove node from same comdat group.   */
  void remove_from_same_comdat_group (void);

  /* Add this symtab_node to the same comdat group that OLD is in.  */
  void add_to_same_comdat_group (symtab_node *old_node);

  /* Dissolve the same_comdat_group list in which NODE resides.  */
  void dissolve_same_comdat_group_list (void);

  /* Return true when symtab_node is known to be used from other (non-LTO)
     object file. Known only when doing LTO via linker plugin.  */
  bool used_from_object_file_p (void);

  /* Walk the alias chain to return the symbol NODE is alias of.
     If NODE is not an alias, return NODE.
     When AVAILABILITY is non-NULL, get minimal availability in the chain.
     When REF is non-NULL, assume that reference happens in symbol REF
     when determining the availability.  */
  symtab_node *ultimate_alias_target (enum availability *avail = NULL,
                      struct symtab_node *ref = NULL);

  /* Return next reachable static symbol with initializer after NODE.  */
  inline symtab_node *next_defined_symbol (void);

  /* Add reference recording that symtab node is alias of TARGET.
     If TRANSPARENT is true make the alias to be transparent alias.
     The function can fail in the case of aliasing cycles; in this case
     it returns false.  */
  bool resolve_alias (symtab_node *target, bool transparent = false);

  /* C++ FE sometimes change linkage flags after producing same
     body aliases.  */
  void fixup_same_cpp_alias_visibility (symtab_node *target);

  /* Call callback on symtab node and aliases associated to this node.
     When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
     skipped.  */
  bool call_for_symbol_and_aliases (bool (*callback) (symtab_node *, void *),
                    void *data,
                    bool include_overwrite);

  /* If node cannot be interposable by static or dynamic linker to point to
     different definition, return this symbol. Otherwise look for alias with
     such property and if none exists, introduce new one.  */
  symtab_node *noninterposable_alias (void);

  /* Return node that alias is aliasing.  */
  inline symtab_node *get_alias_target (void);

  /* Return DECL that alias is aliasing.  */
  inline tree get_alias_target_tree ();

  /* Set section for symbol and its aliases.  */
  void set_section (const char *section);

  /* Like set_section, but copying the section name from another node.  */
  void set_section (const symtab_node &other);

  /* Set section, do not recurse into aliases.
     When one wants to change section of symbol and its aliases,
     use set_section.  */
  void set_section_for_node (const char *section);

  /* Like set_section_for_node, but copying the section name from another
     node.  */
  void set_section_for_node (const symtab_node &other);

  /* Set initialization priority to PRIORITY.  */
  void set_init_priority (priority_type priority);

  /* Return the initialization priority.  */
  priority_type get_init_priority ();

  /* Return availability of NODE when referenced from REF.  */
  enum availability get_availability (symtab_node *ref = NULL);

  /* During LTO stream-in this predicate can be used to check whether node
     in question prevails in the linking to save some memory usage.  */
  bool prevailing_p (void);

  /* Return true if NODE binds to current definition in final executable
     when referenced from REF.  If REF is NULL return conservative value
     for any reference.  */
  bool binds_to_current_def_p (symtab_node *ref = NULL);

  /* Make DECL local.  */
  void make_decl_local (void);

  /* Copy visibility from N.  */
  void copy_visibility_from (symtab_node *n);

  /* Return desired alignment of the definition.  This is NOT alignment useful
     to access THIS, because THIS may be interposable and DECL_ALIGN should
     be used instead.  It however must be guaranteed when output definition
     of THIS.  */
  unsigned int definition_alignment ();

  /* Return true if alignment can be increased.  */
  bool can_increase_alignment_p ();

  /* Increase alignment of symbol to ALIGN.  */
  void increase_alignment (unsigned int align);

  /* Return true if list contains an alias.  */
  bool has_aliases_p (void);

  /* Return true when the symbol is real symbol, i.e. it is not inline clone
     or abstract function kept for debug info purposes only.  */
  bool real_symbol_p (void);

  /* Return true when the symbol needs to be output to the LTO symbol table.  */
  bool output_to_lto_symbol_table_p (void);

  /* Determine if symbol declaration is needed.  That is, visible to something
     either outside this translation unit, something magic in the system
     configury. This function is used just during symbol creation.  */
  bool needed_p (void);

  /* Return true if this symbol is a function from the C frontend specified
     directly in RTL form (with "__RTL").  */
  bool native_rtl_p () const;

  /* Return true when there are references to the node.  */
  bool referred_to_p (bool include_self = true);

  /* Return true if symbol can be discarded by linker from the binary.
     Assume that symbol is used (so there is no need to take into account
     garbage collecting linkers)

     This can happen for comdats, commons and weaks when they are prevailed
     by other definition at static linking time.  */
  inline bool
  can_be_discarded_p (void)
  {
    return ((DECL_EXTERNAL (decl)
         && !in_other_partition)
        || ((get_comdat_group ()
         || DECL_COMMON (decl)
         || (DECL_SECTION_NAME (decl) && DECL_WEAK (decl)))
        && ((resolution != LDPR_PREVAILING_DEF
             && resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)
            || flag_incremental_link)
        && resolution != LDPR_PREVAILING_DEF_IRONLY));
  }

  /* Return true if NODE is local to a particular COMDAT group, and must not
     be named from outside the COMDAT.  This is used for C++ decloned
     constructors.  */
  inline bool comdat_local_p (void)
  {
    return (same_comdat_group && !TREE_PUBLIC (decl));
  }

  /* Return true if ONE and TWO are part of the same COMDAT group.  */
  inline bool in_same_comdat_group_p (symtab_node *target);

  /* Return true if symbol is known to be nonzero, assume that
     flag_delete_null_pointer_checks is equal to delete_null_pointer_checks.  */
  bool nonzero_address (bool delete_null_pointer_checks);

  /* Return true if symbol is known to be nonzero.  */
  bool nonzero_address ();

  /* Return 0 if symbol is known to have different address than S2,
     Return 1 if symbol is known to have same address as S2,
     return 2 otherwise.

     If MEMORY_ACCESSED is true, assume that both memory pointer to THIS
     and S2 is going to be accessed.  This eliminates the situations when
     either THIS or S2 is NULL and is useful for comparing bases when deciding
     about memory aliasing.  */
  int equal_address_to (symtab_node *s2, bool memory_accessed = false);

  /* Return true if symbol's address may possibly be compared to other
     symbol's address.  */
  bool address_matters_p ();

  /* Return true if NODE's address can be compared.  This use properties
     of NODE only and does not look if the address is actually taken in
     interesting way.  For that use ADDRESS_MATTERS_P instead.  */
  bool address_can_be_compared_p (void);

  /* Return symbol table node associated with DECL, if any,
    &

C/C++编译过程全解析:从源码到可执行文件的四步曲 编译是将高级语言转换为机器可执行代码的核心技术过程,其原理涉及词法分析、语法分析、语义分析等多个阶段。在软件工程实践中,理解编译过程对于代码优化、性能调优和错误调试具有重要价值,尤其在底层系统开发、嵌入式编程和高性能计算等场景中至关重要。本文聚焦于C和C++语言的编译流程,通过对比分析预处理、编译、汇编和链接四个关键步骤,深入探讨了函数名修饰和链接错误等常见问题的成因与解决方案,帮助开发者掌握从源码到可执行文件的完整转换机制。 阅读详情

相关推荐

C++编译链接全流程解析:从源码到可执行文件的完整旅程

在软件开发中,编译和链接是将高级语言代码转换为可执行程序的核心技术流程。其基本原理是将人类可读的源代码通过一系列自动化步骤,转化为计算机能够直接执行的机器指令。从技术价值角度看,深入理解编译链接过程不仅能帮助开发者编写更高效的代码,还能在遇到构建错误时快速定位问题根源,提升调试效率。这一流程在C/C++、Rust等系统级语言中尤为重要,涉及预处理、编译、汇编、链接四个关键阶段。预处理阶段处理宏定义和头文件包含,编译阶段进行语法分析和代码优化,汇编阶段生成目标文件,链接阶段则解决符号引用和库依赖问题。在实际应

359

Linux动态库symbol lookup error:五大原因与系统化排查实战

动态链接是现代软件模块化设计的核心技术,它允许程序在运行时加载共享库,实现代码复用和解耦。其核心原理是运行时链接器(ld-linux.so)根据全局符号表,为程序中的未定义符号查找并绑定到动态库中的定义。这项技术的价值在于提升开发效率、减少内存占用并支持插件化架构,广泛应用于操作系统核心服务、数据库中间件及大型应用程序中。然而,在涉及多个动态库相互调用的复杂系统中,常因**符号可见性**或**ABI兼容性**等问题,引发运行时链接错误。本文聚焦于典型的`symbol lookup error`,深入剖析其五

weixin_33739523的博客 392

C++工程化实践:多文件编程、编译链接与调试技巧详解

在C++开发中,多文件编程是实现代码模块化和可维护性的基础技术。其核心原理在于通过头文件与源文件的职责分离,构建编译防火墙,从而提升编译效率并降低代码耦合度。这一技术价值在于将学生作业式的单一文件思维,转变为适用于大型软件工程的模块化架构,是C++开发者从语法学习迈向工程实践的关键一步。在实际应用场景中,多文件编程需要配合头文件守卫、合理的include策略以及清晰的目录结构,才能有效管理复杂项目。本文围绕C++工程化这一主题,深入探讨了编译与链接的底层机制,并分享了包括数据断点、条件断点在内的高效调试技巧

weixin_33895516的博客 463

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器04 LLVM编译器02

B-WUCL(用户权重均匀对比损失)和D-WUCL(物品权重均匀对比损失)中,动态调整参数λ_new(新用户补偿因子)和α(长尾补偿强度)是优化推荐系统适应数据分布变化的核心。

weixin_49199313的博客 1242

3dMax脚本类插件:不写 C++也能造“原生”工具

从plugin关键字到场景持久化,拆解 MAXScript 插件开发全流程!

沐风老师 37

halcon 查找圆形

先找到大概位置进行拟合,然后再以拟合出的位置作为测量的大概位置进行找圆;

qq_59062726的博客 734

论文笔记--Spatial-Temporal Fusion Graph Neural Networks for Traffic Flow Forecasting

Summary 在交通预测问题上,现有的框架通常利用给定的空间邻接图和复杂的机制来建模空间和时间关联。作者认为使用给定的空间邻接图会限制模型的有效时空相关性学习,并且它们通常使用单独的模块来实现空间和时间相关性,或者只使用独立的组件来捕获局部或全局的异质依赖关系,割裂了时空依赖关系。为此作者提出一种时空融合图神经网络用于交通预测。提出一种数据驱动的“时间图”生成方法,以此来补偿空间图可能没有反映的相关性。提出一种新的交通预测方法。 Problem Definition 交通预测中的挑战 以上图为

chenxino的博客 1755

智能座舱架构与芯片- (10) 音频篇 下

若将有限个 量化样值的绝对值从小到大依次排列,并对应地依次赋予一个十进制数字代码(例如,赋予样值0的十进制数字代码为0),在码前以“+”、“-”号为前缀,来 区分样值的正、负,则量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流,即十进制数字信号。如果声学密封不牢,来自内部结构的噪声可能到达传感器,两个传感器之间的泄漏可能降低BF算法的性能。未来,随着汽车电动化的普及,传统的ANC降噪所针对的发动机噪音已经不复存在,而路噪问题将越发明显,因此,全新的RNC主动路噪消减技术将会有一个更为宽广的市场。

joanna_xiao的博客 3838

电力市场小白必看:手把手教你用Matlab实现市场出清电价计算(附完整代码)

本文为电力市场初学者提供了使用Matlab计算市场出清电价的完整指南。通过Yalmip和Matpower工具包,详细讲解了从环境配置到模型构建、求解及结果分析的整个过程,帮助读者快速掌握节点电价计算的核心技术。

weixin_30379531的博客 73

ZXDoc工业级CAN总线仿真工具全解析与应用实践

CAN总线作为现代工业通信的核心协议,其仿真技术是汽车电子和工业控制领域的关键支撑。通过物理层信号模拟、协议层报文解析和应用层人机交互的三维仿真,开发者能够构建完整的硬件在环测试环境。ZXDoc作为工业级仿真工具,集成了DBC工程化管理、HMI面板设计和自动化测试脚本等核心功能,特别适用于ECU开发、产线验证等场景。工具支持ISO11898标准协议,提供错误帧注入、负载压力测试等高级特性,结合Python API可实现复杂测试用例的自动化执行。在新能源车VCU测试等实践中,通过优化采样点等参数配置,显著提升

weixin_30096975的博客 469

深入理解梅尔刻度、梅尔滤波器组和梅尔时频谱图

读取一段音频,使用短时傅里叶变换,得到普通的时频谱图,然后绘制梅尔滤波器组,值得注意的是,librosa的梅尔滤波器组函数还带有权重归一化功能,即对一个三角形滤波器的每个权重,都除以该三角形的面积,如果不希望进行该归一化,设置参数。从公式可见,对数部分可以以自然对数为底数,也可以以10为底数,不同的底数对应不同的系数,要确定当前的系数,只需要代入(1000Hz, 1000mel)即可。其中,m是当前滤波器的序号,表征了当前的时间段,k是当前频率的序号,表征了当前正在对哪一频率的。

DEDSEC_Roger的博客 1万+

基于Python的链家与贝壳租房数据爬取及城市性价比分析

本文通过Python爬虫技术,实现对链家和贝壳平台全国主要城市租房数据的采集与分析。研究使用requestsSelenium和Playwright等现代化爬虫工具,结合代理IP和验证码识别技术应对反爬机制。采集的数据经过清洗后,从多维度分析不同城市租房市场的价格分布、面积特征和性价比差异,并使用可视化技术展示分析结果。本研究为租房者提供决策参考,也为租房市场研究提供数据支撑。关键词:Python爬虫;租房数据;数据分析;链家;贝壳。

2201_76125261的博客 530

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

上一篇: gcc源码阅读--语法解析
下一篇: gcc 源码阅读---语法树
GoldKey
博客等级 码龄25年 82粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoldKey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值