dxe文件到flat文件格式转换的几个问题

 
本文的开发环境为:uclinux-2.6(已移植到VDSP下),VDSP 5.0
本文为上文《 uclinux中调试dxe文件》的补充,所用的示例也为上文的示例。
1   crt的问题
由于程序最终需要在uclinux下运行,这与独立运行的DXE程序是有很大区别的,所以在程序开始运行之前必须做一些初始化的工作,这就是CRT代码的任务。
uclinux下的应用程序通常是从uclibc/libc/sysdeps/linux/bfin/crt1.s开始的,这个文件中的代码稍做修改就可以用在DXE中了:
 
/* When we enter this piece of code, the user stack looks like this:
*       argc            argument counter (integer)
*       argv[0]         program name (pointer)
*       argv[1...N]     program args (pointers)
*       NULL
*       env[0...N]      environment variables (pointers)
*       NULL
      
*    When we are done here, we want
*      R0=argc
*      R1=*argv[0]
*      R2=*envp[0] 
*/
 
 
.text
.align 2
.global __start;
.type        __start,STT_FUNC;
.global      ___uClibc_main;
.type        ___uClibc_main,STT_FUNC;
 
/* Stick in a dummy reference to main(), so that if an application
 * is linking when the main() function is in a static library (.a)
 * we can be sure that main() actually gets linked in */
 
.type        _main,STT_FUNC;
 
__start:
/*     clear the frame pointer and the L registers. */
       FP = 0;
       L0 = 0;
       L1 = 0;
       L2 = 0;
       L3 = 0;
 
/*     Load register R1 (argc) from the stack to its final resting place */
       P0 = SP;
       R1 = [P0++];
 
/*     Copy argv pointer into R2 -- which its final resting place */
       R2 = P0;
 
       SP += -28;
 
       R7 = 0;
       /* Pass highest stack pointer to the app. */
       [SP + 24] = P2;
       /* Store the pointer to ld.so's fini that we got in P1. */
       [SP + 20] = R7;
 
/*     Ok, now run uClibc's main() -- shouldn't return */
       R3 = 0;
       [SP + 12] = R3;
       [SP + 16] = R3;
 
       R0.H = _main;
       R0.L = _main;
       jump.l     ___uClibc_main;
 
__start.end:
在这段CRT代码的最后跳转到uClibc_main中,它的声明如下:
void __uClibc_main(int (*main)(int, char **, char **), int argc,
                  char **argv, void (*app_init)(void), void (*app_fini)(void),
                  void (*rtld_fini)(void), void *stack_end)
{
}
这们只需在此函数中做一些初始化的工作,再调用main()函数就可以了。如果要正确使用VDSP中的库,还需要加上对_mc_data_initialise()和 init_devtab() 两个初始化函数的调用。
2   LDF文件的问题
在生成供转换用的DXE文件的时候,必须使用关键字:
DYNAMIC p0
这个时候,VDSP不会将程序中的符号表用实际的值进行替换,而是会记录下需要替换的位置,这个替换工作要在uclinux实际加载可执行文件后再进行。编译完成后,在DXE文件中可以看到一个.rela.text的section,这个section中就记录了这个替换表。注意此时生成的DXE文件是无法在VDSP中加载的,因为在所有的section中的vaddr和paddr都为0!
当需要使用此DXE文件中的调试信息时,必须将LDF文件中的几个地址定义设置为与uclinux分配的地址相同,然后使用关键字:
PROCESSOR p0
这样,VDSP会将代码中的地址替换为实际的地址,并生成一个可以在VDSP中加载的DXE文件,注意,仅仅是加载,而不能正常运行。再看DXE文件中,已经没有了.rela.text这个section。
其实,在刚开始的时候也可以指定具体的地址并使用PROCESSOR关键字,它也可以用elf2flt转换为FLT文件,只是由于uclinux加载可执行文件时是动态分配空间的,往往地址总是可变的,从而造成运行失败。当然,如果能够保证此程序在uclinux中的加载次序是固定的(init完成之后),这种方法也未尝不可。
3   dxe文件的问题
dxe文件的问题主要集中在.rela.text这个section上。我们知道在flat文件中是没有符号表的(.symtab),所以在转换之前必须将符号表中的符号值写入到代码中去,即用一个相对地址进行替换,在uclinux加载程序时再进行一次替换转变为绝对地址。但是在VDSP生成的DXE文件中并没有进行这一步替换工作,在用elf2flt转换时也没有完成这一步工作。
dxe文件的另一个问题是.rela.text中的偏移量。对于uclinux而言,这个偏移量应该指向要替换的字节。而对于VDSP而言,这个偏移量却指向了这个指令。也就是说它们将相差2个字节。
比如说:
       ++g_iTimesCalled;
这行语句的汇编代码是:
I1.L = 0;
I1.H = 0;
R2 = [I1];
R2 += 1;
[I1] = R2;
其中,对I1赋值的两行语句中的地址必须在运行时替换为g_iTimesCalled的绝对地址。这两行语句的二进制代码为:
11E1 0000 51E1 0000
对于VDSP而言,它将要替换的指针指向11E1,而uclinux在计算绝对地址时要求此指针指向0000。
DXE文件的另外一个问题是在Release的条件下,如果在LDF文件中使用DYNAMIC,而不是PROCESSOR,那么它居然不会生成二进制代码,估计是eliminate unused symbols在捣乱(未经证实)!
4   elf2flt的问题
第一个问题是转换后flt的版本问题,elf2flt生成的版本是5,而uclinux只认2和4的版本。
第二个问题是代码的起始位置。通常uclinux中的flt文件的代码起始位置是0x40,但是VDSP生成的文件代码起始位置则为0x44,这可能导致在计算绝对地址时出现错误。
第三个问题比较严重,这是个关于reloc值的格式问题。
每个reloc的值是一个4字节32位的整数,且是按big-endian排列的。
31~30这两个数据位指明了要替换的数据段:
#define FLAT_RELOC_TYPE_TEXT 0
#define FLAT_RELOC_TYPE_DATA 1
#define FLAT_RELOC_TYPE_BSS 2
29这一位指明是相对地址还是绝对地址。
28~26这三位指明了要替换的数据类型:
#define FLAT_BFIN_RELOC_TYPE_16_BIT 0
#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
#define FLAT_BFIN_RELOC_TYPE_32_BIT 2
25~0指明了要替换的代码的相对地址。
比如要对数据段中的某个数进行替换,那么其reloc值可能为:
01 0 000 00 0000 0000 0000 0001 0101 1010
这意味着要对程序中的0x015a这个相对地址中的数据进行替换,且这个地址位于数据段,其十六进制数为 0x4000015a。
但是在VDSP中,这个数却变成了:
00 0000 0000 0000 0001 0101 1010 000 0 01
最后一个问题:uclinux处理flat格式的文件时要求data段以4对齐,但是elf2flt并不完成这个工作,它是以2对齐的。
 

你可能感兴趣的:(工作,Integer,application,reference,variables,Pointers)