在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是:
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技术内幕》
阅读(16152) | 评论(0) | 转发(0) |