在uclinux for bf561中使用B核(3):corebld的实现
来源:互联网 发布:淘宝消保金怎么交 编辑:程序博客网 时间:2024/06/07 05:27
在有了/dev/coreb之后,uclinux还提供了一个工具corebld。它用于将elf格式的文件作为一个普通文件读出来,提取出相应的可执行代码,再调用/dev/coreb提供的功能将这些可执行代码写入到B核的L1 Instruction Memory或者SDRAM中,最后再调用驱动程序的功能开始执行这些代码。它的实现在user/blkfin-apps/corebld/corebld.c中。
目前corebld只能分析elf格式的文件,但是经过适当的修改,它应该也可以分析在vdsp下生成的可执行代码。
1、elf格式简介
Executable and linking format(ELF)文件是x86 Linux系统下的一种常用目标文件(object file)格式,为了方便和高效,ELF文件内容有两个平行的视角:一个是程序连接角度,另一个是程序运行角度,如下图所示。
ELF header在文件开始处描述了整个文件的组织,Section提供了目标文件的各项信息(如指令、数据、符号表、重定位信息等),Program header table指出怎样创建进程映像,含有每个program header的入口,Section header table包含每一个section的入口,给出名字、大小等信息。
下面的结构体给出了ELF header所能提供的信息:
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
Elf32_Half e_machine; /* Machine architecture. */
Elf32_Word e_version; /* ELF format version. */
Elf32_Addr e_entry; /* Entry point. */
Elf32_Off e_phoff; /* Program header file offset. */
Elf32_Off e_shoff; /* Section header file offset. */
Elf32_Word e_flags; /* Architecture-specific flags. */
Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
Elf32_Half e_phentsize; /* Size of program header entry. */
Elf32_Half e_phnum; /* Number of program header entries. */
Elf32_Half e_shentsize; /* Size of section header entry. */
Elf32_Half e_shnum; /* Number of section header entries. */
Elf32_Half e_shstrndx; /* Section name strings section. */
} Elf32_Ehdr;
下面的结构体给出了每个section所能提供的信息:
typedef struct {
Elf32_Word sh_name; /* Section name (index into the
section header string table). */
Elf32_Word sh_type; /* Section type. */
Elf32_Word sh_flags; /* Section flags. */
Elf32_Addr sh_addr; /* Address in memory image. */
Elf32_Off sh_offset; /* Offset in file. */
Elf32_Size sh_size; /* Size in bytes. */
Elf32_Word sh_link; /* Index of a related section. */
Elf32_Word sh_info; /* Depends on section type. */
Elf32_Size sh_addralign; /* Alignment in bytes. */
Elf32_Size sh_entsize; /* Size of each entry in section. */
} Elf32_Shdr;
因为我们的目标只是将每个Section中的可执行代码提取出来放在Core B中的适当位置,因此只要使用这两个结构体就足够了。至于ELF的更详细的信息可查阅ELF手册或者文档。
2、corebld的实现
corebld的实现其实很简单,就是把每一个section中的可执行代码提取出来,再写入到Elf32_Shdr结构体中的sh_addr指定的位置。最后调用/dev/coreb提供的功能启动B核。
下面的代码说明了这一过程:
#define COMPILER_VDSP 0
#define COMPILER_GCC 1
int elf_load(const char *buf)
{
Elf32_Ehdr *ehdr = (Elf32_Ehdr*)buf;
int compiler;
if (!IS_ELF(*ehdr)) {
printf("File is not an ELF file./n");
return -1;
}
if (ehdr->e_flags == 4 && ehdr->e_machine == 0x6a)
compiler = COMPILER_VDSP;
else if (ehdr->e_flags == 0 && ehdr->e_machine == 0x6a)
compiler = COMPILER_GCC;
else {
printf("File is not a Blackfin ELF file/n");
return -1;
}
{
// 取第一个section所在的偏移量、此文件中的section的数量和每个section的大小
unsigned int section_ptr = (unsigned int)buf + ehdr->e_shoff;
unsigned int section_cnt = ehdr->e_shnum;
unsigned int section_sz = ehdr->e_shentsize;
int i;
// 将每个section中的可执行代码写入到指定的区域
for (i = 0; i < section_cnt; ++i) {
Elf32_Shdr *shdr = (Elf32_Shdr*)((char*)section_ptr + i*section_sz);
unsigned long addr = shdr->sh_addr;
unsigned long size = shdr->sh_size;
if ((compiler == COMPILER_VDSP && (shdr->sh_flags & 0x408000) == 0x8000)
|| (compiler == COMPILER_GCC && (shdr->sh_flags & 0x0003) == 0x0003)) {
printf("Write %zi bytes to 0x%p/n", size, (void*)addr);
put_region((char*)addr, buf + shdr->sh_offset, size);
}
}
}
return 0;
}
下面再看一看每个section中的代码是如何写入到指定的区域的:
static void put_region(char *dst, const char *src, size_t count)
{
int f = open("/dev/coreb", O_RDWR);
int index = 0, ret = 0;
unsigned long seek = 0;
// 根据要写入的不同区域指定调用驱动时要使用的命令和参数
if (((unsigned long)dst >= 0xff600000) &&
((unsigned long)dst < 0xff604000)) {
if ((unsigned long)dst + count < 0xff604000) {
index = 0;
seek = (unsigned long)dst & 0x3fff;
}
} else if (((unsigned long)dst >= 0xff610000) &&
((unsigned long)dst < 0xff614000)) {
if ((unsigned long)dst + count < 0xff614000) {
index = 1;
seek = (unsigned long)dst & 0x3fff;
}
} else if (((unsigned long)dst >= 0xff500000) &&
((unsigned long)dst < 0xff508000)) {
if ((unsigned long)dst + count < 0xff508000) {
index = 2;
seek = (unsigned long)dst & 0x7fff;
}
} else if (((unsigned long)dst >= 0xff400000) &&
((unsigned long)dst < 0xff408000)) {
if ((unsigned long)dst + count < 0xff408000) {
index = 3;
seek = (unsigned long)dst & 0x7fff;
}
/* copy sdram code */
} else if (((unsigned long)dst >= 0x3C00000) &&
((unsigned long)dst < 0x4000000)) {
memcpy(dst, src, count);
} else {
printf("Cowardly refusing to load an incorrectly linked binary./n"
"Please make sure the binary you are trying to load is linked for BF561 Core B./n"
"You will need a specially crafted linker definition file to do this for you./n");
close(f);
return;
}
// 调用功能设置后面要写入区域的基地址
if ((ret = ioctl(f, 1, &index)) != 0)
printf("ioctl return %d/n", ret);
// 设置要读写的偏移量
if (seek)
if ((ret = lseek(f, seek, SEEK_SET)) < 0)
printf("seek failed!/n");
if (write(f, src, count) != count)
printf("write failed!/n");
close(f);
printf("wrote %zi bytes to 0x%p/n", count, dst);
}
- 在uclinux for bf561中使用B核(3):corebld的实现
- 在uclinux for bf561中使用B核(4):B核代码的编写
- 在uclinux for bf561中使用B核(2): /dev/coreb提供的功能
- 在uclinux for bf561中使用B核(1):示例实践
- uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(65):B核启动
- 关于uClinux-2.6(bf561) for VDSP的移植
- 在u-boot for bf561中使用nand flash
- uclinux-2008r1-rc8(bf561)的中断处理(3):trap
- uclinux-2008r1(bf561)内核的icache支持(3):__fill_code_cplbtab
- SQLite for uClinux(一个可以在嵌入式系统中使用的小型数据库)
- uclinux-2008r1(bf561)内核中与存储管理相关的几个全局变量
- uclinux-2008r1(bf561)内核中内存管理相关的几个结构体
- uClinux for bf561中的中断处理(1):中断初始化
- 在uClinux中实现 pppoe拨号上网功能
- uclinux-2008R1-RC8(bf561)到VDSP5的移植(3):Head.s
- 重读uclinux-2008r1-rc8(bf561)内核的中断处理(3):中断处理流程
- uclinux-2008r1-rc8(bf561)内核的console(3):通过console输出信息
- uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(3):vdsp项目创建
- sitemesh建立复合视图(2)
- Lucene学习笔记
- VirtualStream, SeekableReadonlyStream and MarkableForwardOnlyEventingReadStream
- map[]的正确使用:自以为是导致map的一个错误使用
- 在uclinux for bf561中使用B核(2): /dev/coreb提供的功能
- 在uclinux for bf561中使用B核(3):corebld的实现
- 在uclinux for bf561中使用B核(4):B核代码的编写
- 试验网站#1搜索引擎优化收录情况记录(断续运行)2007-9-29
- 试验网站#3搜索引擎优化收录情况记录2007-9-29
- 说说我与C语言...
- 开博第一天
- 复制代码的错误
- 瑞星杀毒软件2008全功能体验版免费使用
- “Google Code Search代码搜索”-程序员的搜索软件