在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是:
nm objfile
objdump -x objfile (或其他选项)
readelf -a objfile
但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。这里针对AIX平台介绍附件中的代码所使用的方法来实现该功能。
附件中的C++代码巧妙利用了AIX提供的系统调用来读出ELF文件的符号表,它以面向对象的方式提供了如下接口:
示例程序:
xcoff_parser中所使用到的主要系统调用:
xcoff_parser.zip
当看完下面这本书之后,你会发现你也可以实现这个功能:
《返璞归真--UNIX技术内幕》
nm objfile
objdump -x objfile (或其他选项)
readelf -a objfile
但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。这里针对AIX平台介绍附件中的代码所使用的方法来实现该功能。
附件中的C++代码巧妙利用了AIX提供的系统调用来读出ELF文件的符号表,它以面向对象的方式提供了如下接口:
- class XCOFFParser;
- //void * is SCNHDR * for 32 bit and SCNHDR_64 for 64 bit.
- //Return 0, contiue. Return 1: break the current parse.
- typedef int (*SectionCallback)(void *param, XCOFFParser *parser, int iIndex, void *secHeader);
- //void * is SYMENT * for 32 bit and SYMENT_64 for 64 bit.
- //Return 0, contiue. Return 1: break the current parse.
- typedef int (*SymbolCallback)(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry);
-
- enum XCOFF_SECTION{SECTION_TEXT=0, SECTION_DATA, SECTION_BSS, SECTION_DEBUG, SECTION_LOADER};
- struct SectionInfo
- {
- XCOFF_SECTION sectionType;
- int sectionNum;
- char sectionName[MAX_SECTION_NAME_LENGTH];
- };
-
- class XCOFFParser
- {
- public:
- XCOFFParser(char *fileName)
- {
- strcpy(m_strFileName, fileName);
- m_ldPointer = NULL;
- m_bIs64 = 0;
- m_lSections = m_lSymbols = 0;
- memset(m_sections, -1, sizeof(m_sections));
- }
-
- virtual ~XCOFFParser();
-
-
-
- int InitParser();
-
- int ParseSections(SectionCallback pfnCallback, void *param, int iIncludeDep=0);
- int ParseSymbols(SymbolCallback pfnCallback, void *param, int iIncludeDep=0);
- int DeinitParser();
-
- int Is64Bit()
- {
- return m_bIs64;
- }
-
- char *GetFileName(char *buf) const
- {
- strcpy(buf, m_strFileName);
- return buf;
- }
-
- long GetSectionsNumber() const
- {
- return m_lSections;
- }
-
- long GetSymbolsNumber() const
- {
- return m_lSymbols;
- }
-
- int IsDebugSymbol(void *symEntry)
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == N_DEBUG;
- }
- return ((SYMENT *)symEntry)->n_scnum == N_DEBUG;
- }
-
- int IsABSSymbol(void *symEntry)
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == N_ABS;
- }
- return ((SYMENT *)symEntry)->n_scnum == N_ABS;
- }
-
-
- int IsUndefSymbol(void *symEntry)
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == N_UNDEF;
- }
- return ((SYMENT *)symEntry)->n_scnum == N_UNDEF;
- }
-
- int IsDefinedSymbol(void *symEntry)
- {
- int iInMem = (m_bIs64? ((SYMENT_64 *)symEntry)->n_sclass C_BLOCK:((SYMENT *)symEntry)->n_sclass C_BLOCK);
- return !IsDebugSymbol(symEntry) && !IsABSSymbol(symEntry)
- && !IsUndefSymbol(symEntry) && iInMem;
- }
-
- int IsTextSymbol(void *symEntry)//Functions' symbol
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;
- }
- return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;
- }
-
- int IsDataSymbol(void *symEntry)//data symbol
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;
- }
- return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;
- }
-
- int IsBssSymbol(void *symEntry)
- {
- if(m_bIs64)
- {
- return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;
- }
- return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;
- }
- /*
- int IsDebugSymbol(SYMENT *symEntry)
- {
- return symEntry->n_scnum == m_sections[SECTION_DEBUG].sectionNum;
- }
- */
-
-
- protected:
- char m_strFileName[MAX_PATH_LEN];
- LDFILE* m_ldPointer;
- int m_bIs64;
- long m_lSections, m_lSymbols;
-
- SectionInfo m_sections[MAX_SECTIONS];
- };
- #include
- #include "xcoff_parser.h"
- static int SymbolReadDefinedFuncs(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry)
- {
- //printf("In callback\n");
- if(strlen(symName) > 0 && parser->IsDefinedSymbol(symEntry) && parser->IsTextSymbol(symEntry))
- {
- //It's a function definition, let's store it into the map
- printf("Defined function name:%s, address:%p\n", symName,
- parser->Is64Bit()? ((SYMENT_64 *)symEntry)->n_value: ((SYMENT *)symEntry)->n_value);
-
- }
- return 0;
- }
-
- int main(int argc, char *argv[])
- {
- XCOFFParser parser(buf);
- int ret = parser.InitParser();
- if(ret != ERROR_XCOFF_SUCCESS)
- {
- printf("XCOFFParser::InitParser failed:%d.\n", ret);
- return ret;
- }
- ret = parser.ParseSections(NULL, NULL);
- if(ret != ERROR_XCOFF_SUCCESS)
- {
- printf("XCOFFParser::ParseSections failed:%d.\n", ret);
- return ret;
- }
-
- ret = parser.ParseSymbols(SymbolReadDefinedFuncs, NULL);
- if(ret != ERROR_XCOFF_SUCCESS)
- {
- printf("XCOFFParser::ParseSymbols failed:%d.\n", ret);
- return ret;
- }
- return 0;
- }
xcoff_parser中所使用到的主要系统调用:
- LDFILE *ldopen( char *, LDFILE * );
- int ldfhread( LDFILE *, void * );
- int ldshread( LDFILE *, unsigned short, void * );
- int ldtbread( LDFILE *, int, void * );
- int ldclose( LDFILE * );
xcoff_parser.zip
当看完下面这本书之后,你会发现你也可以实现这个功能:
《返璞归真--UNIX技术内幕》