快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADSP-BF561
Visual DSP++ 5.0(update 6)
Bfin-uclinux-2009r1.6
欢迎转载,但请保留作者信息
在我们的应用程序开发完成后,我们需要将之发布使之可以独立运行,此时我们有的只有一个由vdsp生成的dxe文件,我们需要写一个loader完成此dxe文件的加载。
我们直接在appstub的基础上修改:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
#include <sched.h>
#include <elf.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/mman.h>
typedef int (*pfcall)(int argc, char *argv[]);
#define printf(fmt, ...) do {} while(0)
#ifndef EM_BLACKFIN
# define EM_BLACKFIN 106
#endif
#define IS_ELF(buff) /
(buff[EI_MAG0] == ELFMAG0 && /
buff[EI_MAG1] == ELFMAG1 && /
buff[EI_MAG2] == ELFMAG2 && /
buff[EI_MAG3] == ELFMAG3)
static void* find_entry(char* buf)
{
// 读取函数入口
Elf32_Ehdr* ehdr = (Elf32_Ehdr*)buf;
Elf32_Shdr* shdr_str, *shdr;
char* str_head;
int i;
pfcall entry = NULL;
shdr_str = buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize;
str_head = buf + shdr_str->sh_offset;
shdr = buf + ehdr->e_shoff;
for(i=0; i < ehdr->e_shnum; i++, shdr++)
{
printf("section found: %s/n", str_head + shdr->sh_name);
if(strcmp(str_head + shdr->sh_name, ".vdsp_comm") == 0)
{
printf("entry found./n");
memcpy(&entry, buf+shdr->sh_offset+4, 4);
return entry;
}
}
return NULL;
}
static void* load_dxe_file(const char* fname)
{
// 读取dxe文件中的所有section,并返回入口地址
int i, fd;
struct stat stat;
void *entry = NULL;
char* buf;
Elf32_Ehdr* ehdr;
Elf32_Phdr* phdr;
// 打开映射文件
fd = open(fname, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Unable to load %s: %s/n", fname, strerror(errno));
return NULL;
}
if (fstat(fd, &stat) < 0) {
fprintf(stderr, "Unable to stat %s: %s/n", fname, strerror(errno));
return NULL;
}
if (stat.st_size < EI_NIDENT) {
fprintf(stderr, "File is too small to be an ELF/n");
return NULL;
}
buf = mmap(0, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (buf == MAP_FAILED) {
fprintf(stderr, "Unable to mmap %s: %s/n", fname, strerror(errno));
return NULL;
}
// 判断内容是否合法
/* make sure we have a valid ELF */
ehdr = buf;
if (!IS_ELF(ehdr->e_ident) || ehdr->e_machine != EM_BLACKFIN)
{
fprintf(stderr, "file is not a Blackfin ELF file/n");
return NULL;
}
/* make sure we have no unhandled program headers */
phdr = (Elf32_Phdr *)(buf + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; ++i)
{
printf("program head %d: /ntype=%d offset=%d vaddr=%08x filesz=%d memsz=%d flags=%x/n",
i, phdr->p_type, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz, phdr->p_flags);
if(phdr->p_filesz > 0)
memcpy(phdr->p_vaddr, buf + phdr->p_offset, phdr->p_filesz);
else
memset(phdr->p_vaddr, 0, phdr->p_memsz);
printf("load OK!/n");
++phdr;
}
entry = find_entry(buf);
munmap(buf, stat.st_size);
close(fd);
return entry;
}
/*
* The main program.
*/
int main(int argc, char *argv[])
{
unsigned int addr = 0;
unsigned int *p;
pfcall entry = NULL;
if(argc < 2)
{
printf("not enough param.");
return 1;
}
if(argv[1][0] == '-' && argv[1][1] == 'L')
{
entry = load_dxe_file(argv[1] + 2);
if(entry)
{
printf("dxe entry found at 0x%08x/n", entry);
argv[1] = argv[0];
return entry(argc-1, argv+1);
}
else
printf("no dxe entry found/n");
}
else if(argv[1][0] == '-' && argv[1][1] == 'E')
{
// 直接跳转到指定位置
addr = strtoul(argv[1]+2, NULL, 16);
p = (unsigned int*)addr;
if(p[0])
{
printf("detect new app at %08x/n", p);
p[0] = 0;
if(p[1])
{
printf("prepare call %08x/n", p[1]);
argv[1] = argv[0];
return ((pfcall)p[1])(argc-1, argv+1);
}
else
printf("no function entry found./n");
}
else
printf("old app exist./n");
}
return 0;
}
这段程序很简单,它检测dxe文件中“.vdsp_comm”这个section,从这个section中读取这个dxe文件指定的入口,然后跳转到这个位置执行。
当我们在vdsp下调试程序的时候,可以用
appstub –Eaddr …
这样的方式让它检测是否重新加载vdsp程序。
当程序要发布的时候,直接用:
appstub –Lp0.dxe ….
这样的方式来加载dxe文件。
在这两种方式中,都可以使用参数且真正要运行的程序不用理会-L和-E的影响。
让vdsp与uclinux共舞(12):应用程序开发(2009-11-9)
让vdsp与uclinux共舞(11):方案改进(2009-11-6)
让vdsp与uclinux共舞(10):加载SMP内核(2009-11-4)
让vdsp与uclinux共舞(9):查找内核函数(2009-11-3)
让vdsp与uclinux共舞(8):vdsp驱动框架(2009-11-3)
让vdsp与uclinux共舞(7):在内核为驱动预留空间(2009-11-2)
让vdsp与uclinux共舞(6):用vdsp开发驱动的设想(2009-11-2)
让vdsp与uclinux共舞(5):加入dwarf调试信息(2009-11-2)
让vdsp与uclinux共舞(4):加载uclinux(2009-11-2)
让vdsp与uclinux共舞(3):boot kernel(2009-10-31)
让vdsp与uclinux共舞(2):vdsp的影响(2009-10-31)
让VDSP与uclinux共舞(1):开篇(2009-10-30)
近日,我家6岁的小姑娘参加了第六届POP全国少儿英语风采大赛,拉票进行中(2011-6-15前)。
请帮忙点击新东方网站的链接:
http://popdasai.xdf.cn/toupiao.php?do=space&uid=4237
投她一票,谢谢!