1.解析so文件的准备
so文件是ELF文件格式实现的,它是由各种区段信息组成的,有代码段(.text)、.got、.data、.init_array等等。所以对这个区段解析获取就很重要的。 通过解析读取elf文件结构,同时调用系统函数进行做解析。
2.实现获取so文件区段
//函数功能:将so文件用创建文件方式进行读取问下信息
//函数参数1:要载入的so文件路径,参数2:内容中的so文件数据,参数3:so文件大小
BOOL LoadELFFileData(char* FilePath, char** FileData, ULONG* FileSize)
{
if(NULL == FilePath)
{
return FALSE;
}
HANDLE hFile;
hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
ULONG ulHight = 0;
ULONG ulReturn = 0;
*FileSize = GetFileSize(hFile, &ulHight);
*FileData = new char[*FileSize + 20];
if(ReadFile(hFile, *FileData, *FileSize, &ulReturn, NULL) == 0)
{
CloseHandle(hFile);
hFile = NULL;
delete *FileData;
return FALSE;
}
return TRUE;
}
//函数功能:获取函数区段新,函数参数:需要解析的so文件路径
BOOL GetSectionInfo(char* FilePath)
{
if(NULL == FilePath)
{
return FALSE;
}
//加载elf文件
if(LoadELFFileData(FilePath, &m_fileData, &m_fileSize) == FALSE)
{
AfxMessageBox("LoadElfFileData is false\n");
return FALSE;
}
if(!( (((char*)m_fileData)[EI_MAG0] == 0x7F) && (((char*)m_fileData)[EI_MAG1] == 'E') && (((char*)m_fileData)[EI_MAG2] == 'L') && (((char*)m_fileData)[EI_MAG3] == 'F')))
{
AfxMessageBox("不是标准的ELF文件\n");
return FALSE;
}
if(((char*)m_fileData)[EI_CLASS] == ELFCLASS64)
{
//AfxMessageBox("64位的so文件\n");
UpdateData(FALSE);
Is64Arm = TRUE;
}
else if(((char*)m_fileData)[EI_CLASS] == ELFCLASS32)
{
//AfxMessageBox("32位的so文件");
UpdateData(FALSE);
Is64Arm = FALSE;
}
else if(((char*)m_fileData)[EI_CLASS] == ELFCLASSNONE)
{
AfxMessageBox("无效的类文件\n");
return FALSE;
}
//获取区段信息
GetSoFileSection(m_fileData);
return TRUE;
}
//用于解析32位的so文件信息
Elf32_Ehdr* elf32_ehdr = (Elf32_Ehdr*)FileData;
Elf32_Phdr* elf32_phdr = (Elf32_Phdr*)(FileData + elf32_ehdr->e_phoff);
char* pSection;
Elf32_Shdr* shdr32stringTable =(Elf32_Shdr*)(FileData + elf32_ehdr->e_shoff) + elf32_ehdr->e_shstrndx;
pSection =(char*)(FileData + shdr32stringTable->sh_offset);
Elf32_Shdr* Shdr =(Elf32_Shdr*)(FileData + elf32_ehdr->e_shoff);
for(int i =0; i < elf32_ehdr->e_shnum; i++, Shdr++)
{
char* name = pSection + Shdr->sh_name;
if(NULL == name)
{
continue;
}
CString test;
test.Format("%d",i);
m_section.InsertItem(i, test);
m_section.SetItemText(i,1, name);
CString offset;
offset.Format("0x%X",Shdr->sh_offset);
m_section.SetItemText(i, 2, offset);
CString endaddr;
endaddr.Format("0x%x",Shdr->sh_offset + Shdr->sh_size);
m_section.SetItemText(i, 3, endaddr);
CString size;
size.Format("0x%X", Shdr->sh_size);
m_section.SetItemText(i, 4, size);
CString align;
align.Format("%d", Shdr->sh_addralign);
m_section.SetItemText(i, 5, align);
CString type;
type.Format("%d", Shdr->sh_type);
m_section.SetItemText(i, 6, type);
UpdateData(FALSE);
}
}
3.实现效果
(MFC实现界面)