想知道nm命令的实现原理吗---分析AIX平台下ELF文件的符号表

简介: 在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是:nm objfile objdump -x objfile (或其他选项)readelf -a objfile但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。
在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是:
nm objfile
objdump -x objfile (或其他选项)
readelf -a objfile

但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。这里针对AIX平台介绍附件中的代码所使用的方法来实现该功能。
附件中的C++代码巧妙利用了AIX提供的系统调用来读出ELF文件的符号表,它以面向对象的方式提供了如下接口:

  1. class XCOFFParser;
  2. //void * is SCNHDR * for 32 bit and SCNHDR_64 for 64 bit.
  3. //Return 0, contiue. Return 1: break the current parse.
  4. typedef int (*SectionCallback)(void *param, XCOFFParser *parser, int iIndex, void *secHeader);

  5. //void * is SYMENT * for 32 bit and SYMENT_64 for 64 bit.
  6. //Return 0, contiue. Return 1: break the current parse.
  7. typedef int (*SymbolCallback)(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry);

  8. enum XCOFF_SECTION{ SECTION_TEXT=0, SECTION_DATA, SECTION_BSS, SECTION_DEBUG, SECTION_LOADER};
  9. struct SectionInfo
  10. {
  11.     XCOFF_SECTION sectionType;
  12.     int sectionNum;
  13.     char sectionName[MAX_SECTION_NAME_LENGTH];
  14. };

  15. class XCOFFParser
  16. {
  17. public:
  18.     XCOFFParser(char *fileName)
  19.     {
  20.         strcpy(m_strFileName, fileName);
  21.         m_ldPointer = NULL;
  22.         m_bIs64 = 0;
  23.         m_lSections = m_lSymbols = 0;
  24.         memset(m_sections, -1, sizeof(m_sections));
  25.     }

  26.     virtual ~XCOFFParser();
  27.     

  28.     
  29.     int InitParser();
  30.     
  31.     int ParseSections(SectionCallback pfnCallback, void *param, int iIncludeDep=0);
  32.     int ParseSymbols(SymbolCallback pfnCallback, void *param, int iIncludeDep=0);
  33.     int DeinitParser();

  34.     int Is64Bit()
  35.     {
  36.         return m_bIs64;
  37.     }
  38.     
  39.     char *GetFileName(char *buf) const
  40.     {
  41.         strcpy(buf, m_strFileName);
  42.         return buf;
  43.     }

  44.     long GetSectionsNumber() const
  45.     {
  46.         return m_lSections;
  47.     }

  48.     long GetSymbolsNumber() const
  49.     {
  50.         return m_lSymbols;
  51.     }

  52.     int IsDebugSymbol(void *symEntry)
  53.     {
  54.         if(m_bIs64)
  55.         {
  56.             return ((SYMENT_64 *)symEntry)->n_scnum == N_DEBUG;
  57.         }
  58.         return ((SYMENT *)symEntry)->n_scnum == N_DEBUG;
  59.     }

  60.     int IsABSSymbol(void *symEntry)
  61.     {
  62.         if(m_bIs64)
  63.         {
  64.             return ((SYMENT_64 *)symEntry)->n_scnum == N_ABS;
  65.         }
  66.         return ((SYMENT *)symEntry)->n_scnum == N_ABS;
  67.     }


  68.     int IsUndefSymbol(void *symEntry)
  69.     {
  70.         if(m_bIs64)
  71.         {
  72.             return ((SYMENT_64 *)symEntry)->n_scnum == N_UNDEF;
  73.         }
  74.         return ((SYMENT *)symEntry)->n_scnum == N_UNDEF;
  75.     }

  76.     int IsDefinedSymbol(void *symEntry)
  77.     {
  78.         int iInMem = (m_bIs64? ((SYMENT_64 *)symEntry)->n_sclass C_BLOCK:((SYMENT *)symEntry)->n_sclass C_BLOCK);
  79.         return !IsDebugSymbol(symEntry) && !IsABSSymbol(symEntry)
  80.                 && !IsUndefSymbol(symEntry) && iInMem;
  81.     }

  82.     int IsTextSymbol(void *symEntry)//Functions' symbol
  83.     {
  84.         if(m_bIs64)
  85.         {
  86.             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;
  87.         }
  88.         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;
  89.     }

  90.        int IsDataSymbol(void *symEntry)//data symbol
  91.     {
  92.         if(m_bIs64)
  93.         {
  94.             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;
  95.         }
  96.         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;
  97.     }

  98.     int IsBssSymbol(void *symEntry)
  99.     {
  100.         if(m_bIs64)
  101.         {
  102.             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;
  103.         }
  104.         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;
  105.     }
  106. /*
  107.     int IsDebugSymbol(SYMENT *symEntry)
  108.     {
  109.         return symEntry->n_scnum == m_sections[SECTION_DEBUG].sectionNum;
  110.     }
  111. */

  112.     
  113. protected:
  114.     char m_strFileName[MAX_PATH_LEN];    
  115.     LDFILE* m_ldPointer;
  116.     int m_bIs64;
  117.     long m_lSections, m_lSymbols;

  118.     SectionInfo m_sections[MAX_SECTIONS];
  119. };
示例程序:
  1. #include
  2. #include "xcoff_parser.h"

  3. static int SymbolReadDefinedFuncs(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry)
  4. {
  5.     //printf("In callback\n");
  6.     if(strlen(symName) > 0 && parser->IsDefinedSymbol(symEntry) && parser->IsTextSymbol(symEntry))
  7.     {
  8.         //It's a function definition, let's store it into the map
  9.         printf("Defined function name:%s, address:%p\n", symName,
  10.                             parser->Is64Bit()? ((SYMENT_64 *)symEntry)->n_value: ((SYMENT *)symEntry)->n_value);
  11.         
  12.     }
  13.     return 0;
  14. }

  15. int main(int argc, char *argv[])
  16. {
  17.      XCOFFParser parser(buf);
  18.      int ret = parser.InitParser();
  19.      if(ret != ERROR_XCOFF_SUCCESS)
  20.      {
  21.          printf("XCOFFParser::InitParser failed:%d.\n", ret);
  22.         return ret;
  23.      }
  24.      ret = parser.ParseSections(NULL, NULL);
  25.      if(ret != ERROR_XCOFF_SUCCESS)
  26.      {
  27.          printf("XCOFFParser::ParseSections failed:%d.\n", ret);
  28.         return ret;
  29.      }

  30.      ret = parser.ParseSymbols(SymbolReadDefinedFuncs, NULL);
  31.      if(ret != ERROR_XCOFF_SUCCESS)
  32.      {
  33.          printf("XCOFFParser::ParseSymbols failed:%d.\n", ret);
  34.         return ret;
  35.      }
  36.      return 0;
  37. }


xcoff_parser中所使用到的主要系统调用:
  1. LDFILE *ldopen( char *, LDFILE * );
  2. int ldfhread( LDFILE *, void * );
  3. int ldshread( LDFILE *, unsigned short, void * );
  4. int ldtbread( LDFILE *, int, void * );
  5. int ldclose( LDFILE * );
目录
相关文章
|
API 索引
ElasticSearch索引模板
ElasticSearch索引模板
485 1
|
机器学习/深度学习 数据采集 人工智能
大模型升级与设计之道:ChatGLM、LLAMA、Baichuan及LLM结构解析(上)
大模型升级与设计之道:ChatGLM、LLAMA、Baichuan及LLM结构解析(上)
1395 0
|
Ubuntu Python
Ubuntu16.04 安装多个python版本
Ubuntu16.04 安装多个python版本
1363 0
Ubuntu16.04 安装多个python版本
|
自然语言处理 索引 算法
HanLP分词命名实体提取详解
文本挖掘是抽取有效、新颖、有用、可理解的、散布在文本文件中的有价值知识,并且利用这些知识更好地组织信息的过程。对于文本来说,由于语言组织形式各异,表达方式多样,文本里面提到的很多要素,如人名、手机号、组织名、地名等都称之为实体。
7819 0
|
5月前
|
IDE 测试技术 API
python调试与测试
python调试与测试
[√]addr2line
[√]addr2line
348 0
|
Ubuntu Linux 测试技术
探索Linux中的`dbus-send`命令
`dbus-send`是Linux中用于进程间通信的D-Bus系统的命令行工具,允许应用程序通过消息总线相互交互。要安装它,可以使用包管理器(如`apt-get`或`dnf`)。基本语法包括指定总线类型、目标服务、消息类型、对象路径、接口及方法等。示例用法包括使用`dbus-send`来锁定屏幕(通过调用`org.gnome.ScreenSaver.Lock`)和设置音量(通过与PulseAudio服务交互)。在使用时,需了解目标服务的接口和方法,并确保具备相应权限。
759 10
|
安全 算法 网络安全
C语言在安全领域的应用
本文探讨了C语言在网络安全中的应用,包括密码学算法实现、网络安全工具开发和安全协议实现。C语言因其高效性、可控性和跨平台性,常用于实现AES、RSA等加密算法,开发网络扫描器和入侵检测系统,以及实现SSL/TLS、IPSec等安全协议。代码示例展示了C语言如何进行AES加密解密。尽管C语言在安全领域有显著优势,但面对不断演变的威胁,持续学习和研究新的安全技术至关重要。
|
小程序 JavaScript Java
商城|商城小程序|基于微信小程序的智慧商城系统设计与实现(源码+数据库+文档)
商城|商城小程序|基于微信小程序的智慧商城系统设计与实现(源码+数据库+文档)
459 1
|
JSON Java API
JSON & GSON - 读取 JSON 文件
JSON & GSON - 读取 JSON 文件
1402 0