我在debian squeeze / gcc 4.5下稳定了2年之前创build了自己的bootloader。 现在在debian喘息/ sID不能用4.6和4.7编译,因为从这些我创build更大的部分,我期望手工生成最终的二进制文件。 这对我来说现在不是问题,因为在debian wheezy / sID中, gcc 4.5仍然存在,但是我想使用gcc 4.6和4.7来编译。
我产生这样的最终二进制文件:
源文件编译为:
gcc-4.5 -Wall -O3 -c -m32 -I. -o assemblybin-objects/vga_pm.so vga_pm.S
与连接:
我们如何加载linux映像来适应内存中的位置
用GRUB定制代码?
如何在正常启动后触发启动光盘的启动过程?
在bcdedit中为windows 8创build启动项目
如何在ARM Cortex M3主板上运行linux?
ld -nostdlib -T binary.ld assemblybin-objects/vga_pm.so ... and other objects here ... -o bootloader.bin
binary.ld的内容是:
OUTPUT_FORMAT("binary","binary","binary") OUTPUT_ARCH(i386) SECTIONS { . = 0; .bootloader : { . = 0x600; *(.bootstrap); . = 0x7fa; BYTE(0x11); BYTE(0x33); BYTE(0x55); BYTE(0x77); BYTE(0x55); BYTE(0xaa); _bootstrap_end = .; . = 0x800; *(.sysinit); _sysinit_end = .; . = 0x1000; *(.pages); _pages_end = .; . = 0x5000; *(.sysconf); *(.presystem); *(.system); *(.library); *(.text); *(.data); *(.bss); *(.rodata); *(.rodata.*); . = 0xeffc; BYTE(0x11); BYTE(0x33); BYTE(0x55); BYTE(0x77); _system_end = .; } . = ASSERT(_bootstrap_end <= 0x800,"bootstrap section big!"); . = ASSERT(_sysinit_end <= 0x1000,"Sysinit section big!"); . = ASSERT(_pages_end <= 0x5000,"Pages section big!"); . = ASSERT(_system_end <= 0xf000,"System initialization section big!"); }
最后用dd创build最终的二进制文件。
我看到,使用gcc 4.6和4.7进行编译时,链接器会在bootloader.bin的开始处添加一些字节(250-300)。
我使用binutils 2.22中的ld ,并用我自己的食谱做了构build过程。
我的实际问题是:
这些版本的gcc编译器之间有什么区别,他们产生更大的部分或通过elf对象文件指示链接器在bootloader.bin文件的开头添加这些字节?
是否有任何命令行参数为gcc 4.6和/或4.7,这将closures一个function,可能会产生比gcc 4.5更大的部分,或删除说的链接器添加这些字节在bootloader.bin文件的开始?
编辑17-08-2012:这些天我很忙,但很快我会更新我做的testing结果。
回答@strnk和@丹Aloni:当我看到这个问题时,我做的第一个是排除无用的部分,但结果是一样的…我认为,因为bootloader.bin是一个简单的二进制与所需的链接代码部分在正确的位置作为链接器指示做的,没有段名,重定位和deBUGging信息和符号… bootloader.bin文件不是一个精灵对象文件。
请考虑实际问题的变化。 谢谢你的一切…我马上回来
编辑31-08-2012:好的,谢谢你的帮助。 @Dan Aloni给出的答案是通过@strnk显示的ld脚本完成的
/disCARD/ : { *(.eh_frame) *(.eh_frame_hdr) }
在断言之后。
如何更改U-Boot内存映射
运行linux可执行文件的过程
Bootloader – 显示string运行时错误
windows XP引导加载程序(NTLDR)是否关注内核导入声明?
为什么我们需要embedded式设备中的引导程序?
通过使用您提供的标志(在gcc-4.5和gcc-4.6之间)编译一个普通的C文件,并使用objdump -h来检查输出,似乎在gcc-4.6引入了.eh_frame部分。
你提供的ld脚本并不关心那个部分,它可能应该。 您可以使用strip -R .eh_frame -R .eh_frame_hdr在链接之前从对象文件中删除该部分和其他部分。
无论如何,因为两个gcc版本的链接器都是相同的,所以对象文件的objdump -h会提示导致这个问题的差异。
是否有任何命令行参数将关闭可能会产生更大的部分的功能
是的:如果你关心体型,你应该用-Os来建造。 -O3显式启用可能导致更大代码大小的优化。 由于自举程序执行一次 ,因此使用-O3几乎肯定是错误的。
编辑:
“装配优化是没有意义的…
…和其他对象在这里…“
你的代码是在汇编中吗? 如果是这样,优化级别确实没有意义,但是你应该能够简单地比较readelf -S vga_pm.so和两个编译器readelf -S vga_pm.so输出,并且确切地看哪些节是不同的。
但是看起来你的一些物体更有可能不在装配中,在这种情况下, -O3和-Os之间的区别将是非常有意义的。
GCC在它的二进制输出中添加了一些不需要的调试部分(使用objdump -h <file>来查看它们),我通常把我不想要的/disCARD/规则放在我的ld脚本中去除它们:
/disCARD/ : { *(.deBUG_*) *(.note*) *(.indent) *(.comment) *(.stab) *(.stabstr) *(.eh_frame) }
你可能想要注意到你根本没有使用GCC 。
从文件扩展名来看,vga_pm.S是包含预处理器指令的汇编源代码,因此您需要cpp预处理器将其转换为预处理(.s)源代码。 请注意,GNU汇编程序( as )具有所有必需的本地指令,例如用于文件包含,使此步骤不必要。
“.source”编译为.o目标文件并不需要GCC,因为这可以直接使用(这是binutils包的一部分)。
然后你使用ld把目标文件链接成一个二进制文件。 再次, ld是binutils包的一部分。
使用GCC作为前端混淆了这个问题,几乎没有任何好处,而且实际上可能成为问题的根源。 点,以防万一,你告诉我们你使用的GCC版本,但你没有告诉我们你使用的binutils版本…
我建议不要依赖并非严格必要的工具,以保持构建过程尽可能简单。 在这种情况下,从引导加载程序构建步骤中删除GCC。
总结以上是内存溢出为你收集整理的我的引导程序不能使用gcc 4.6和4.7 … 4.5编译全部内容,希望文章能够帮你解决我的引导程序不能使用gcc 4.6和4.7 … 4.5编译所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)