疑难:同样的代码编译后得到的二进制文件完全不同。

matchchen 2008-10-06 05:47:27
某ARM编译平台(MTK手机平台)。仅编译的时间不同,没有修改任何东西。同一台机器环境一样。全编后得到的bin文件(ROM文件)完全不同,但功能未发现不同。请高手释疑!

分析:
1、比较ROM文件和Sym文件,发现的第一处不同是EXTSRAM_BSS_Limit_Ptr指向的地址内容不同。查找发现Bootarm.s文件有如下动作:

EXPORT EXTSRAM_BSS_Limit_Ptr
EXTSRAM_BSS_Limit_Ptr
IMPORT |Image$$EXTSRAM$$ZI$$Limit|
DCD |Image$$EXTSRAM$$ZI$$Limit|


可见是变量Image$$EXTSRAM$$ZI$$Limit的初值不同。查找整个工程,只发现在custom_scatstruct.c文件中有如下声明:

extern kal_uint32 Image$$EXTSRAM$$ZI$$Limit;

这个变量在哪里定义赋值的没找到,难道它是根据时间不同随机生成的?Why?看名字是某块存储区域的限制大小,这个不应该在编译阶段就产生区别了吧。

2、比较.lis文件(相当于Cbuilder中的.map文件),发现以下四个域的大小都不同:
ROM1、ROM3、ROM4、EXTSRAM.

如下表:

域 Build1(start:size) Build2(start:size)
ROM 0x08000000: 0x0000032c 0x08000000: 0x0000032c
ROM0 0x08001000: 0x00000054 0x08001000: 0x00000054
ROM1 0x08001054: 0x001f90f0 0x08001054: 0x001f9164
ROM2 0x081fa144: 0x00111ae4 0x081fa144: 0x00111ae4
ROM3 0x0830bc28: 0x000e437c 0x0830bc28: 0x000e43dc
ROM4 0x083effa4: 0x000e46ac 0x083effa4: 0x000e476c
...
EXTSRAM 0x00100280: 0x0023bd8c 0x00100280: 0x0023bd90
...

两次编译链接用的scatter文件完全相同,大致结构是这样:
ROM 0x08000000 0x00a00000
{
ROM 0x08000000 0x800
{
bootarm.obj (C$$code,+First)
}
ROM0 0x08001000 FIXED ;4KB
{
*.obj (SECINFO)
}
ROM1 +0x0 0x00400000
{
*.obj (LEADING_PART,+First)
*plutommi.lib (+RO-CODE)
*lcmmi.lib (+RO-CODE)
*l4_classb.lib (+RO-CODE)
*mtkapp.lib (+RO-CODE)
*l1_classb.lib (+RO-CODE)
*email.lib (+RO-CODE)
*l4misc.lib (+RO-CODE)

cpp_initialise.o(+RO)
cpp_finalise.o(+RO)
* (C$$pi_ctorvec)
* (C$$pi_dtorvec)
* (C$$ddtorvec)
}
ROM2 +0x0 0x00400000
{
; WAP family
*wapadp.lib (+RO-CODE)
*wap.lib (+RO-CODE)
*wae.lib (+RO-CODE)
*jataayu.lib (+RO-CODE)
*jataayuapp.lib (+RO-CODE)
*wapapp.lib (+RO-CODE)
*obigo05aadp.lib (+RO-CODE)
*obigo05alib.lib (+RO-CODE)
; J2ME family
*j2me_11.lib (+RO-CODE)
*j2me_hi.lib (+RO-CODE)
*jal.lib (+RO-CODE)
*ijet_adp.lib (+RO-CODE)
*jblendia.lib (+RO-CODE)
j2me_custom_*.obj (+RO-CODE)
}
ROM3 +0x0 0x00400000
{
.ANY (+RO-CODE)
}
ROM4 +0x0 0x00400000
{
.ANY (+RO-CODE)
}
ROM5 +0x0
{
.ANY (+RO-DATA)
}
ROM_TAIL +0x0
{
*.obj (SECINFO_TAIL)
}
...
怎么编译出来就不一样了呢?!

请高手解惑。
...全文
2649 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
chnxf 2010-02-04
  • 打赏
  • 举报
回复
The linker can link ARM code and Thumb code, and automatically generates
interworking veneers to switch processor state when required. The linker also
automatically generates long branch veneers, where required, to extend the range of
branch instructions.
Antoleen 2010-01-26
  • 打赏
  • 举报
回复
对anon$$obj.o这个文件比较好奇,因为这个文件是占用ROM空间的。这个文件的作用是什么?
Antoleen 2010-01-26
  • 打赏
  • 举报
回复
Image$$EXTSRAM$$ZI$$Limit 这个其实是链接时生成的一个变量,表示EXTSRAM段ZI区的上限值。可以看ads 连接器的相关文档。
matchchen 2008-12-01
  • 打赏
  • 举报
回复
如果大家还有新的见解,请转到
http://topic.csdn.net/u/20081028/11/f8124e2b-6e08-4707-985d-e4d96ae61948.html
下面,还有20分:)
matchchen 2008-12-01
  • 打赏
  • 举报
回复

今天看到一个相似的案例,有些启发:

首先我在前面已经证实目标文件相同:

编译出来的.obj文件和lib文件都完全相同(除了注释中的时间信息)

而armlink出来以后的elf文件和bin文件就大相径庭了。


那问题应该在link阶段。在前面我也查出link命令中包含了scatter文件作为参数:

c:\progra~1\arm\adsv1_2\bin\armlink.exe -map -info sizes,totals -symbols -xref -remove -first LARGEPOOL_FIRST_ZI -scatter .\scat.txt

正如楼上所说Scatter中使用了模糊定义,它没有指定每个obj的具体顺序。那么link程序一定有一个方法来确定顺序(对计算机来说不存在真正意义上的随机),这个排序很可能和编译时间有关,而不是和文件名相关,从而导致最终文件大相径庭。(Size不对可能是link中字节对齐的问题)

很长时间没看它了,代码得找找,有时间再验证一下。
CedarDiao 2008-11-09
  • 打赏
  • 举报
回复
首先,楼主肯定没有把你完整的Scatter文件贴出来,因为你的Scatter文件里面没有EXTSRAM域。Image$$EXTSRAM$$ZI$$Limit符号是连接器生成的,如果你的Scatter文件中没有定义EXTSRAM这个域,那么这个符号是不回存在的。

其次,anon$$obj.o这个目标应该就是包含在ROM1中的* (C$$pi_ctorvec) ,* (C$$pi_dtorvec) 或* (C$$ddtorvec) 中的某个东西。

* (C$$pi_ctorvec)
* (C$$pi_dtorvec)
* (C$$ddtorvec)

这3个东西是C++程序要使用的。

最后,程序前后Size有差异,个人认为是因为Scatter中使用了大量的模糊定义,或者叫模式定义:

* (C$$pi_ctorvec)
* (C$$pi_dtorvec)
* (C$$ddtorvec)


.ANY (+RO-CODE)

这样的目标是并不明确的,如果目标明确,那么连接出来的Size就一定应该一样。

补充,看到LZ的这段Map文件:

Memory Map of the image

Base Addr Size Type Attr Idx E Section Name Object
(ROM)
0x08000320 0x0000000c Code RO 88713 Veneer$$Code anon$$obj.o
...
(ROM1)
0x08006638 0x0000000c Code RO 88714 Veneer$$Code anon$$obj.o
0x08006644 0x0000000c Code RO 88715 Veneer$$Code anon$$obj.o
0x08006650 0x0000000c Code RO 88716 Veneer$$Code anon$$obj.o
...
(ROM3)
0x08310d50 0x0000000c Code RO 89108 Veneer$$Code anon$$obj.o
0x08310d5c 0x0000000c Code RO 89109 Veneer$$Code anon$$obj.o
...
(ROM4)
0x083f1e70 0x00000008 Code RO 89165 Veneer$$Code anon$$obj.o
0x083f1e78 0x0000000c Code RO 89166 Veneer$$Code anon$$obj.o
...

其中的Veneer$$Code,我有映像Veneer$$Code是编译器自动生成的代码,比如从ARM指令集的函数跳转到Thumb指令集的时候就会有这个东西(因为直接跳转是不允许的)。

就这些了,不知道说清楚没,楼主看得懂就多给分,看不懂就少给点分,哈哈。。。
xiaopoy 2008-10-29
  • 打赏
  • 举报
回复
LZ可以简单列举不一样的地方?只看顶楼那几个比较结果完全没有思路。

Image$$EXTSRAM$$ZI$$Limit字面意思 扩充内存大小不同?

看那几个东西猜测也许是设置的动态链接使用的数据有不同(?说不通)
不误导了,不知情,打住。
matchchen 2008-10-27
  • 打赏
  • 举报
回复
好长时间了,还是没有彻底弄明白:(

不过现在看应该和编译器没有多大关系。编译链接平台是ADS1.2

编译出来的.obj文件和lib文件都完全相同(除了注释中的时间信息)

而armlink出来以后的elf文件和bin文件就大相径庭了。从mak文件分析出来armlink命令大概是这样的:

c:\progra~1\arm\adsv1_2\bin\armlink.exe -map -info sizes,totals -symbols -xref -remove -first LARGEPOOL_FIRST_ZI -scatter .\scat.txt -output .\xxx.elf -symdefs .\xxx.sym -list .\xxx.lis -libpath c:\progra~1\arm\adsv1_2\lib -keep g_aaa -keep g_bbb -keep g_ccc -keep g_ddd -keep g_eee
(后面是lib文件列表)

从网上查找到的信息显示armlink语法如下:
armlink [-help] [-vsn] [-partial] [-output file] [-elf] [-reloc][-ro-base address] [-ropi] [-rw-base address] [-rwpi] [-split] [-scatter file][-debug|-nodebug][-remove?RO/RW/ZI/DBG]|-noremove] [-entry location ] [-keep section-id] [-first section-id] [-last section-id] [-libpath pathlist] [-scanlib|-noscanlib] [-locals|-nolocals] [-callgraph] [-info topics] [-map] [-symbols] [-symdefs file] [-edit file] [-xref] [-xreffrom object(section)] [-xrefto object(section)] [-errors file] [-list file] [-verbose] [-unmangled |-mangled] [-match crossmangled][-via file] [-strict] [-unresolved symbol][-MI|-LI|-BI] [input-file-list]

其中几个重要参数解释如下:

-map 这个选项创建映像文件的信息图。映像文件信息图包括映像文件中的每个加载域,运行域和输入段的大小和地址,这里的输入段还包括调试信息和链接器产生的输入段

-scatter file 这个选项使用在file中包含的分组和定位信息来创建映像内存映射。 注意,如果使用了该选项的话,必须要重新实现堆栈初始化函数__user_initial_stackheap()。

虽然猜测应该是armlink的问题,但是还不能确定是那个步骤,哪个参数造成的。
xiaopoy 2008-10-24
  • 打赏
  • 举报
回复
类似链接dll时产生.ext 那样的临时文件?
LZ尝试搜索一些所使用编译器和连接器的过程说明文档
matchchen 2008-10-07
  • 打赏
  • 举报
回复
to VBSpine:

非线性系统和人工智能可以另外开帖讨论,编译器还没复杂到那个程度。
yeah920 2008-10-07
  • 打赏
  • 举报
回复
帮忙顶一下,让了解的人来解答.
matchchen 2008-10-07
  • 打赏
  • 举报
回复
纠正一下昨晚在4楼写的一个错误(紫色字体):

1、错误描述
“另外从.lis文件中可以查到,ROM1中可以生成了一个叫anon$$obj.o的空文件,ROM1的不同都是由它引起的。”
“但整个工程中找不到“anon*”文件,在.lis文件中显示其大小为0,但占用了空间。”

2、纠正:
anon$$obj.o不是空文件,大小应该是8036Bytes,只有Code。如下:

Image component sizes
Code RO Data RW Data ZI Data Debug Object Name
8036 0 0 0 0 anon$$obj.o

...
==================================
Memory Map of the image

Base Addr Size Type Attr Idx E Section Name Object

(ROM)
0x08000320 0x0000000c Code RO 88713 Veneer$$Code anon$$obj.o
...
(ROM1)
0x08006638 0x0000000c Code RO 88714 Veneer$$Code anon$$obj.o
0x08006644 0x0000000c Code RO 88715 Veneer$$Code anon$$obj.o
0x08006650 0x0000000c Code RO 88716 Veneer$$Code anon$$obj.o

...
(ROM3)
0x08310d50 0x0000000c Code RO 89108 Veneer$$Code anon$$obj.o
0x08310d5c 0x0000000c Code RO 89109 Veneer$$Code anon$$obj.o

...
(ROM4)
0x083f1e70 0x00000008 Code RO 89165 Veneer$$Code anon$$obj.o
0x083f1e78 0x0000000c Code RO 89166 Veneer$$Code anon$$obj.o

...



可见ROM1/ROM3/ROM4三个域的大小不同与anon$$obj.o有关(EXTSRAM情况特殊一些)。并且Image$$EXTSRAM$$ZI$$Limit也是在anon$$obj.o中定义的。大部分疑点都指向了anon$$obj.o。不知有何方法能追溯到anon$$obj.o文件内容。


Image$$EXTSRAM$$ZI$$Limit 0x0033c00c Number 0 anon$$obj.o ABSOLUTE
帅得不敢出门 2008-10-07
  • 打赏
  • 举报
回复
友情up 似乎得问编译器做了啥手脚 ^-^
九桔猫 2008-10-07
  • 打赏
  • 举报
回复
古希腊有人云:人不可能两次踏进同一条河流 。。。。。。。。。。。。。。
星羽 2008-10-07
  • 打赏
  • 举报
回复
编译器编译的时候可能有些东西依赖时间,或许是优化的原因,如果可以,换个编译器试试,或许两次编译的时候,强制把系统时间调成一个看看
matchchen 2008-10-07
  • 打赏
  • 举报
回复
5搂的思路不错。不过不知道怎么把时间弄到完全一致。
matchchen 2008-10-06
  • 打赏
  • 举报
回复
谢谢hqin6友情up!

在代码和编译环境不变的情况下,编译器弄出两套二进制文件来,对于版本管理会造成一定影响。

“编译器使用了概率性优化算法或是一些和time stamp有关的随机初始数据呢.”

能说得详细一些吗?如果单纯是优化目标代码,似乎没有必要用到概率性的或随机的数据,是出于安全考虑吗?

我是个比较喜欢追根究底的人。比如这个Image$$EXTSRAM$$ZI$$Limit,怎么找到它的初值,它总有赋值的时候吧,除非它是用随机算法算出,而算法封装到编译器.exe文件中了,否则我们还是应该能找到的。

另外从.lis文件中可以查到,ROM1中可以生成了一个叫anon$$obj.o的空文件,ROM1的不同都是由它引起的。该文件包含很多类似“Image$$DYNAMIC_CODE3$$Length”形式的符号,size都为0。例如:
Symbol Name Value Ov Type Size Object(Section)

BuildAttributes$$THUMB_ISAv2$M$E$P$PE$A:L22$X:L11$S22$IW$~IW$USESV6$~STKCKD$USESV7$~SHL$OTIME$PRES8
0x00000000 number 0 anon$$obj.o ABSOLUTE
Image$$DYNAMIC_CODE3$$Length 0x00000000 Number 0 anon$$obj.o ABSOLUTE
Image$$DYNAMIC_CODE3$$ZI$$Length 0x00000000 Number 0 anon$$obj.o ABSOLUTE
...


但整个工程中找不到“anon*”文件,在.lis文件中显示其大小为0,但占用了空间。如下:

Image component sizes
Code RO Data RW Data ZI Data Debug Object Name
8036 0 0 0 0 anon$$obj.o

...
==================================
Memory Map of the image

Base Addr Size Type Attr Idx E Section Name Object
0x08000320 0x0000000c Code RO 88713 Veneer$$Code anon$$obj.o

...

0x08006638 0x0000000c Code RO 88714 Veneer$$Code anon$$obj.o
0x08006644 0x0000000c Code RO 88715 Veneer$$Code anon$$obj.o
0x08006650 0x0000000c Code RO 88716 Veneer$$Code anon$$obj.o

...
anon$$obj.o到底是个什么东西,有什么方法能追潮到它的内容吗?
  • 打赏
  • 举报
回复
正常现象,编译器的手册上没写这种情况下一样,那就可能会不一样.
我啃 2008-10-06
  • 打赏
  • 举报
回复
编译器为什么要向你保证两次编译同一代码的二进制形式一样?如果编译器使用了概率性优化算法或是一些和time stamp有关的随机初始数据呢。。~
太乙 2008-10-06
  • 打赏
  • 举报
回复
友情up~~

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧