{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/elf-symbol-table-visibility/",
  "atlas": "https://www.pystone.net/?node=elf-symbol-table-visibility#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/elf-symbol-table-visibility.md",
  "context": "https://www.pystone.net/notes/elf-symbol-table-visibility.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:elf-symbol-table-visibility",
  "slug": "elf-symbol-table-visibility",
  "title": "ELF文件-符号表与符号可见性",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "ELF文件 符号表与符号可见性",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "1a7449482c68d74b85f88178ac8e44014ec80728379956539c7a4547d7bba628",
  "assets": [],
  "headings": [
    {
      "depth": 1,
      "text": "ELF文件-符号表与符号可见性",
      "anchor": "elf文件-符号表与符号可见性",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#elf%E6%96%87%E4%BB%B6-%E7%AC%A6%E5%8F%B7%E8%A1%A8%E4%B8%8E%E7%AC%A6%E5%8F%B7%E5%8F%AF%E8%A7%81%E6%80%A7"
    },
    {
      "depth": 2,
      "text": "符号表",
      "anchor": "符号表",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#%E7%AC%A6%E5%8F%B7%E8%A1%A8"
    },
    {
      "depth": 4,
      "text": ".symtab （静态）符号表",
      "anchor": "symtab-静态符号表",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#symtab-%E9%9D%99%E6%80%81%E7%AC%A6%E5%8F%B7%E8%A1%A8"
    },
    {
      "depth": 4,
      "text": ".dynsym（动态符号表）",
      "anchor": "dynsym动态符号表",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#dynsym%E5%8A%A8%E6%80%81%E7%AC%A6%E5%8F%B7%E8%A1%A8"
    },
    {
      "depth": 2,
      "text": "函数名称修饰",
      "anchor": "函数名称修饰",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#%E5%87%BD%E6%95%B0%E5%90%8D%E7%A7%B0%E4%BF%AE%E9%A5%B0"
    },
    {
      "depth": 4,
      "text": "extern \"C\"：禁用名称修饰",
      "anchor": "extern-c禁用名称修饰",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#extern-c%E7%A6%81%E7%94%A8%E5%90%8D%E7%A7%B0%E4%BF%AE%E9%A5%B0"
    },
    {
      "depth": 4,
      "text": "attribute((visibility(\"default\")))：控制符号的可见性",
      "anchor": "attributevisibilitydefault控制符号的可见性",
      "citation": "https://www.pystone.net/notes/elf-symbol-table-visibility/#attributevisibilitydefault%E6%8E%A7%E5%88%B6%E7%AC%A6%E5%8F%B7%E7%9A%84%E5%8F%AF%E8%A7%81%E6%80%A7"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:programming-languages-and-runtimes",
      "title": "编程语言与运行时",
      "url": "https://www.pystone.net/notes/programming-languages-and-runtimes/",
      "atlas": "https://www.pystone.net/?node=programming-languages-and-runtimes#knowledge-atlas",
      "label": "编程语言与运行时",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "本层中的“ELF文件-符号表与符号可见性”导航项",
      "citation": "https://www.pystone.net/notes/programming-languages-and-runtimes/#%E6%9C%AC%E5%B1%82"
    }
  ],
  "contentMarkdown": "# ELF文件-符号表与符号可见性\n\n﻿# ELF文件-符号表与符号可见性\n\n## 符号表\n- `.symtab` 是静态符号表，包含了所有符号（包括调试符号），用于静态链接。\n- `.dynsym` 是动态符号表，包含了动态链接需要的符号，用于运行时符号解析。\n\n#### **`.symtab` （静态）符号表**\n`.symtab` 是 ELF 文件中的符号表，包含了程序或库中所有的符号信息，包括函数、全局变量等。它通常用于**静态链接**和**调试**。符号表包含符号的名称、地址、类型等信息，并且支持调试信息和符号的重定位。\n- - **内容**：\n\t- 符号的名称。\n\t- 符号的地址（如果已知）。\n\t- 符号的类型和绑定信息（例如，是否是函数、变量等）。\n\t- 符号的段或节（例如，`.text`、`.data`）。\n- **用途**：\n\t- 静态链接：编译器和链接器会通过 `.symtab` 来解析符号，进行符号重定位。\n\t- 调试：`.symtab` 保存了符号信息和调试信息，使得调试器能够读取符号名称、源代码行号等信息。\n- **特点**：\n\t- 包含所有符号的详细信息。\n\t- 静态链接时使用。\n\t- 可以包含调试信息。\n\n```bash\n$ readelf -s my_program.o\n```\n列出 `.symtab` 中的符号信息。\n\n#### **`.dynsym`（动态符号表）**\n\n`.dynsym` 是 ELF 文件中的动态符号表，专门用于动态链接。它只包含程序运行时需要解析的符号，通常用于**动态链接**（即共享库）。`.dynsym` 中的符号不包含调试信息和一些其他的静态符号信息，它包含的是在运行时需要查找和链接的符号。\n\n- **内容**：\n    - 符号的名称（存储在 `.dynstr` 字符串表中）。\n    - 符号的类型、地址（通常在运行时解析）。\n    - 符号的绑定信息（如共享库的符号）。\n- **用途**：\n    - 动态链接：当程序需要加载共享库时，动态链接器会通过 `.dynsym` 来查找符号，完成符号的解析和链接。\n    - 符号解析：动态加载时，`.dynsym` 中的符号会被动态链接器处理，确保外部函数和变量的调用能够正确映射。\n- **特点**：\n    - 只包含动态链接所需的符号。\n    - 不包含调试信息。\n    - 仅用于动态链接时解析符号。\n\n```bash\n$ readelf -sW my_program.so\n```\n列出 `.dynsym` 中的符号信息。\n\n## 函数名称修饰\n\n#### **`extern \"C\"`：禁用名称修饰**\n让 C++ 符号变得与 C 符号一样，不会进行名称修饰，这样在不同语言间（如 C/C++、Java）进行调用时，可以确保符号一致性，避免因名称修饰导致的链接错误。\n\n在 C++ 中，函数名称通常会被编译器**名称修饰**（name mangling）以支持函数重载等特性。`extern \"C\"` 是一种指示编译器使用 **C** 的链接方式，禁止对符号进行名称修饰，使得 C++ 编译器生成的符号与 C 编译器一样，保持简单的函数名。\n\n\n#### **`__attribute__((visibility(\"default\")))`：控制符号的可见性**\n\n`__attribute__((visibility(\"default\")))` 用于控制符号在共享库中的可见性。它告诉编译器将符号暴露给外部程序或库，使得该符号可被动态链接器找到。\n\n默认情况下，C++ 编译器会将符号标记为“隐藏”（“`hidden`”），这意味着只有定义它的模块内部可以访问该符号。\n\n通过 `visibility(\"default\")`，符号将变为“公共的”，可以被其他程序链接和使用。\n\n\n* 对于动态链接的库，**只有可见的符号**（标记为 `default`）会被**添加到动态符号表（`.dynsym`）中**，这些符号可以被外部程序或其他共享库引用和解析。\n- 如果符号的可见性是 `hidden`，则该符号不会出现在动态符号表中，其他程序无法通过动态链接找到该符号。\n"
}
