Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1933023
  • 博文数量: 77
  • 博客积分: 2175
  • 博客等级: 大尉
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 20:49
个人简介

欢迎光临我的博客

文章分类

全部博文(77)

文章存档

2023年(1)

2018年(4)

2017年(1)

2016年(2)

2015年(2)

2013年(5)

2012年(29)

2010年(33)

分类: C/C++

2012-01-17 10:33:31

在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 * );

 xcoff_parser.zip  

当看完下面这本书之后,你会发现你也可以实现这个功能:
《返璞归真--UNIX技术内幕》

阅读(16038) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~