一文带你实现解析android的so的区段信息

899 阅读2分钟

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实现界面)

2021.07.29_张增斌&df7bc55a54502ae2da74b81b6ba1dd5c.png