|
楼主 |
发表于 2019-12-29 10:28:37
|
显示全部楼层
elf_file.h 文件:
/*
*********************************************************************************************************
*
* 模块名称 : elf文件解析模块
* 文件名称 : elf_file.h
* 说 明 : 头文件
*
*********************************************************************************************************
*/
#ifndef __ELF_FILE_H_
#define __ELF_FILE_H_
#define ELF_TEST_FILE_1 "0:/H7-TOOL/Programmer/FLM/ST/STM32F0xx/STM32F0xx_16.FLM"
#define ELF_TEST_FILE_2 "0:/H7-TOOL/Programmer/FLM/ST/STM32F4xx/STM32F446_Quad_SPI.FLM"
#define ELF_TEST_FILE_3 "0:/H7-TOOL/Programmer/FLM/ST/STM32H7x/STM32H743_H7-TOOLS_QSPI.FLM"
#define FUNC_NUM 8 /* 全局符号个数(函数和一个常量数组) */
#define LOAD_NUM 4 /* 需要加载到RAM的段个数 */
enum
{
IDX_FlashDevice = 0,
IDX_Init,
IDX_UnInit,
IDX_BlankCheck,
IDX_EraseChip,
IDX_EraseSector,
IDX_ProgramPage,
IDX_Verify,
};
typedef struct
{
uint32_t Valid;
uint32_t Offset;
uint32_t Size;
}
ELF_FUNC_T;
typedef struct
{
uint32_t Valid;
uint32_t Offset;
uint32_t Addr;
uint32_t Size;
}
ELF_LOAD_T;
/* FLM文件分析结构 */
typedef struct
{
uint32_t FileOk;
ELF_LOAD_T Load[LOAD_NUM];
ELF_FUNC_T Func[FUNC_NUM];
}FLM_PARSE_T;
extern FLM_PARSE_T g_tFLM;
uint8_t ELF_ParseFile(char *_path);
#endif
elf_file.c 文件:
/*
*********************************************************************************************************
*
* 模块名称 : elf文件解码模块
* 文件名称 : elf_file.c
* 版 本 : V1.0
* 说 明 : 用于解码KEIL中FLM算法文件,提取加载到CPU RAM的代码。
* FLM文件中的字符串表和符号表长度不能超过4096。
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2019-12-29 armfly 正式发布
*
* Copyright (C), 2019-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "file_lib.h"
#include "elf_file.h"
#include "elf.h"
const char *strFuncName[FUNC_NUM] = {"FlashDevice", "Init", "UnInit", "BlankCheck",
"EraseChip", "EraseSector", "ProgramPage", "Verify"};
FLM_PARSE_T g_tFLM;
/* 测试代码
ELF_ParseFile(ELF_TEST_FILE_1);
ELF_ParseFile(ELF_TEST_FILE_2);
ELF_ParseFile(ELF_TEST_FILE_3);
while(1);
*/
/*
*********************************************************************************************************
* 函 数 名: ELF_ParseFile
* 功能说明: 解析elf文件. 使用了 FsReadBuf[4096]全部变量做缓冲区。解析结果放到全局变量g_tFLM
* 形 参: _path : 文件路径
* 返 回 值: 0 = ok, 其他值表示错误
*********************************************************************************************************
*/
uint8_t ELF_ParseFile(char *_path)
{
uint32_t bytes;
uint32_t i,j;
char *p;
uint32_t StrFoud[FUNC_NUM] = {0};
uint32_t StrIdx[FUNC_NUM] = {0};
Elf_Ehdr Ehdr;
Elf_Phdr *pPhdr;
Elf_Shdr *pShdr;
Elf_Sym *pSym;
Elf_Shdr ShdrSym; /* 符号表头 */
Elf_Shdr ShdrStr; /* 字符串表头 */
/* 解析结果先全部清零 */
for (i = 0; i < LOAD_NUM; i++)
{
g_tFLM.Load.Valid = 0;
g_tFLM.Load.Offset = 0;
g_tFLM.Load.Addr = 0;
g_tFLM.Load.Size = 0;
}
for (i = 0; i < FUNC_NUM; i++)
{
g_tFLM.Func.Valid = 0;
g_tFLM.Func.Offset = 0;
g_tFLM.Func.Size = 0;
}
/* 解析文件头部 ELF Header */
bytes = ReadFileToMem(_path, 0, FsReadBuf, 52);
if (bytes != 52)
{
goto err; /* 读文件错误 */
}
memcpy((char *)&Ehdr, FsReadBuf, sizeof(Elf_Ehdr));
if (IS_ELF(Ehdr) == 0)
{
goto err; /* 不是ELF文件 */
}
if (Ehdr.e_type != ET_EXEC)
{
goto err; /* 不是可执行的镜像文件 */
}
/* 解析程序头部(Program Header) - 2段 */
if (Ehdr.e_phnum > LOAD_NUM)
{
goto err; /* Program Header 个数过大 */
}
bytes = ReadFileToMem(_path, Ehdr.e_phoff, FsReadBuf, Ehdr.e_phnum * 32);
if (bytes != Ehdr.e_phnum * 32)
{
goto err; /* 读文件错误 */
}
for (i = 0; i < Ehdr.e_phnum; i++)
{
pPhdr = (Elf_Phdr *)(FsReadBuf + i * 32);
if (pPhdr->p_type == PT_LOAD)
{
g_tFLM.Load.Valid = 1;
g_tFLM.Load.Offset = pPhdr->p_offset;
g_tFLM.Load.Addr = pPhdr->p_vaddr;
g_tFLM.Load.Size = pPhdr->p_filesz;
}
}
/* 解析节区头部 (Sections Header) */
if (Ehdr.e_shnum < 25)
{
uint8_t found = 0;
bytes = ReadFileToMem(_path, Ehdr.e_shoff, FsReadBuf, 40 * Ehdr.e_shnum);
/* 先查找符号表 */
for (i = 0; i < Ehdr.e_shnum; i++)
{
pShdr = (Elf_Shdr *)(FsReadBuf + 40 * i);
if (pShdr->sh_type == SHT_SYMTAB)
{
memcpy((char *)&ShdrSym, (char *)pShdr, sizeof(Elf_Shdr));
found++;
}
}
if (found == 0)
{
goto err; /* 未找到符号表 */
}
/* 查找符号表对应的字符串表 (ELF文件中可能有多个字符串表)*/
if (ShdrSym.sh_link >= Ehdr.e_shnum)
{
goto err; /* 未找到字符串表 */
}
pShdr = (Elf_Shdr *)(FsReadBuf + 40 * ShdrSym.sh_link);
if (pShdr->sh_type == SHT_STRTAB)
{
memcpy((char *)&ShdrStr, (char *)pShdr, sizeof(Elf_Shdr));
}
else
{
goto err; /* 未找到字符串表 */
}
}
else
{
goto err; /* Sections个数过大 */;
}
/* 字符串表 */
if (ShdrStr.sh_size < sizeof(FsReadBuf))
{
bytes = ReadFileToMem(_path, ShdrStr.sh_offset, FsReadBuf, ShdrStr.sh_size);
if (bytes == ShdrStr.sh_size)
{
p = FsReadBuf;
for (i = 0; i < bytes - 1; i++)
{
if (*p++ == 0)
{
for (j = 0; j < 8; j++)
{
if (strcmp(p, strFuncName[j]) == 0)
{
StrFoud[j] = 1;
StrIdx[j] = i + 1;
}
}
}
}
}
else
{
goto err; /* 读文件失败 */
}
}
else
{
goto err; /* 字符串表过大 */
}
/* 解析符号表 */
if (ShdrSym.sh_size < sizeof(FsReadBuf))
{
bytes = ReadFileToMem(_path, ShdrSym.sh_offset, FsReadBuf, ShdrSym.sh_size);
for (i = 0; i < bytes / sizeof(Elf_Sym); i++)
{
for (j = 0; j < FUNC_NUM; j++)
{
pSym = (Elf_Sym *)(FsReadBuf + 16 * i);
if (pSym->st_name == StrIdx[j] && StrFoud[j] == 1)
{
g_tFLM.Func[j].Valid = 1;
g_tFLM.Func[j].Offset = pSym->st_value;
g_tFLM.Func[j].Size = pSym->st_size;
}
}
}
}
else
{
/* 符号表过大 */
}
return 0; /* 解析成功 */
err:
return 1; /* 解析失败 */
}
|
|