免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5015 | 回复: 12
打印 上一主题 下一主题

[C] 请教加载的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-09-20 23:50 |只看该作者 |倒序浏览
本帖最后由 landker 于 2013-09-21 13:58 编辑

1)
  1. 代码1(start.asm):
  2. [BITS        32]
  3. extern        L0
  4. [section .text]
  5. global        _start

  6. _start:
  7.         jmp        $
  8.         .......
复制代码
编译后为: start.o

2)其他的目标文件集合假设为 others.o

3)我自己写了一个简单的链接器,将1)和2)一起链接,

test_ld  -o test start.o others.o

4)加载运行出错(ubuntu系统提示:已杀死)!

按照正常情况,系统在加载 test 后,整个代码段都被复制至起始地址为 0x8048000 的地方,而且第一条执行的代码应该是 0x80480bf(即:_start:的第一条语句:jmp $),即执行一个死循环(要手工ctrl+c 退出),但却提示出错.....

请教一下各位,到底哪里出错了?

5)相关信息如下:
  1. ELF header(readelf -h test):
  2. ELF Header:
  3.   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  4.   Class:                             ELF32
  5.   Data:                              2's complement, little endian
  6.   Version:                           1 (current)
  7.   OS/ABI:                            UNIX - System V
  8.   ABI Version:                       0
  9.   Type:                              EXEC (Executable file)
  10.   Machine:                           Intel 80386
  11.   Version:                           0x1
  12.   Entry point address:               0x80480bf
  13.   Start of program headers:          52 (bytes into file)
  14.   Start of section headers:          148 (bytes into file)
  15.   Flags:                             0x0
  16.   Size of this header:               52 (bytes)
  17.   Size of program headers:           32 (bytes)
  18.   Number of program headers:         3
  19.   Size of section headers:           40 (bytes)
  20.   Number of section headers:         13
  21.   Section header string table index: 6
复制代码
  1. 程序头(readelf -l test):
  2. Elf file type is EXEC (Executable file)
  3. Entry point 0x80480bf
  4. There are 3 program headers, starting at offset 52

  5. Program Headers:
  6.   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  7.   LOAD           0x00029c 0x08048000 0x08048000 0x008e5 0x008e5 R E 0x1000
  8.   LOAD           0x000b81 0x08049000 0x08049000 0x00013 0x00013 RW  0x1000
  9.   GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x1000

  10. Section to Segment mapping:
  11.   Segment Sections...
  12.    00     .text
  13.    01     .data
  14.    02     
复制代码
  1. section 列表(readelf -S test)

  2. There are 13 section headers, starting at offset 0x94:

  3. Section Headers:
  4.   [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  5.   [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  6.   [ 1] .text             PROGBITS        08048000 00029c 0008e5 00  AX  0   0 16
  7.   [ 2] .data             PROGBITS        08049000 000b81 000013 00  WA  0   0  4
  8.   [ 3] .bss              NOBITS          080488f8 000b94 000000 00  WA  0   0  4
  9.   [ 4] .rodata           PROGBITS        080488f8 000b94 0000dc 00   A  0   0  1
  10.   [ 5] .rel.text         REL             080489d4 000c70 000180 08      7   1  4
  11.   [ 6] .shstrtab         STRTAB          08048b54 000df0 00006e 00      0   0  1
  12.   [ 7] .symtab           SYMTAB          08048bc2 000e5e 000510 10      8   8  4
  13.   [ 8] .strtab           STRTAB          080490d2 00136e 0001c5 00      0   1  1
  14.   [ 9] .comment          PROGBITS        08049297 001533 000056 01  MS  0   0  1
  15.   [10] .eh_frame         PROGBITS        080492ed 001589 000294 01   A  0   0  4
  16.   [11] .rel.eh_frame     REL             08049581 00181d 000098 08      7   1  4
  17.   [12] .note.GNU-stack   NOBITS          08049619 0018b5 000000 01  WA  0   0  4
复制代码
  1. 代码反编译(objdump -s -d --start-address=0x8048000 --stop-address=0x8048100 test):

  2. 080480bf <_start>:
  3. 80480bf:        eb fe                        jmp    80480bf <_start>
  4. .......
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-09-20 23:53 |只看该作者
回复 1# landker


    ..........

论坛徽章:
0
3 [报告]
发表于 2013-09-21 13:48 |只看该作者
回复 1# landker

有人知道吗?
   

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
4 [报告]
发表于 2013-09-22 08:54 |只看该作者
大师,你问的问题太高深了,自己写链接器至少要求自己对可执行文件的格式有相当的了解,linux的ELF格式我不清楚,只能帮顶,win的PE格式倒是还是稍微有所了解。

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
5 [报告]
发表于 2013-09-22 09:16 |只看该作者
不过虽然不了解linux的ELF格式具体怎么工作的,不过这个东西我想基本上该有的东西应该是要有的。比如PE格式的输入表,负责将会调用到外部dll在程序执行之前先加载进来,并且解析这些将会被使用的外部函数入口地址。如果输入表信息不正确,那么程序一执行就出错,根本到不了第一条指令。不知道你有没有处理过这个东西?
如果实在是找不到问题所在了,我觉得还可以先用ld链接一个合法的文件,然后将ELF格式里面各个部分都分别导出然后与你链接好的文件进行比较,看看到底是哪个部分有问题。

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
6 [报告]
发表于 2013-09-22 10:43 |只看该作者
ld 如此强大, 以至于我不知道为什么需要写一个自已的ld, 先看看ldscript能不能解决你的问题, 如果不行, 上代码~~

论坛徽章:
0
7 [报告]
发表于 2013-09-22 17:37 |只看该作者
本帖最后由 landker 于 2013-09-22 19:44 编辑

我对 *.o 的代码段“起始地址”及“对齐信息” 作了修改(主要是参照单纯使用gld编译链接时的成功信息):

1)将代码段的内容改从 0x1000(file_offset)开始,排完代码段,再到数据段....

2)更改mem_offset(主要是虚拟地址),代码段:0x8048000(不变),数据段:0x8048000 + 0x1000 + 0x910(代码段长度)

3)将每个要链接的 *.o 的大小都整合为16的整数倍,多余的填 nop。最后,整个代码段的长度变为 0x910

即如下:
  1. Elf file type is EXEC (Executable file)
  2. Entry point 0x80480c0
  3. There are 3 program headers, starting at offset 52

  4. Program Headers:
  5.   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  6.   LOAD           0x001000 0x08048000 0x08048000 0x00910 0x00910 R E 0x1000
  7.   LOAD           0x001910 0x08049910 0x08049910 0x00014 0x00014 RW  0x1000
  8.   GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x1000

  9. Section to Segment mapping:
  10.   Segment Sections...
  11.    00     .text
  12.    01     .data
  13.    02     
复制代码
结果:

执行 ./test后,系统进入 jmp $。看上去,问题似乎解决了,但其实还没有,具体如下:

1)为何数据段的起始地址不能是 0x8049000(这个是我之前的设置)?按理来说,代码段的长度才 0x910,少于0x1000,那从0x8049000处开始放置数据段应该是“可以”的,但如果那样做了,在运行程序后,系统会报”已杀死“的错误。只有将它调整为0x8049910(0x8048000 + 0x1000 + 0x910(代码段长度),这个是参考gld的)后,才可以”执行成功“。这是为何?

个人感觉,之前将数据段的起始地址设置为 0x8049000时,似乎是把代码段的信息覆盖了,不知道我的猜测是否正确?但不论我的猜测是否正确,还是想不太明白为何0x8049000这个地址不能作为数据段的起始地址....

2)当我把 start.asm 里的 jmp $ 语句去掉后(这个jmp $ 是作为调试用的),让它执行真正的程序(其实也是一个简单的程序,判断2个整数的大小,然后打印出相应的数字),但得出的结果并非和预期的一样(但如果使用gld,结果是正确的)。

感觉还是和 1)的加载有关.......

各位大师,谁有好的建议?

   

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
8 [报告]
发表于 2013-09-22 19:59 |只看该作者
本帖最后由 captivated 于 2013-09-22 20:11 编辑

首先,LZ用了BFD库没有。
其次,ELF格式标准文档读完烂熟了?
其三,链接重定位要修改指令,对该平台的指令格式完全了解,不会修改出错?

某种程度上,就写链接器本身而言并不算十分困难,算法不难,然后文件操作而已。不过文件格式的细节,指令格式的细节,汇编器的影响,操作系统的动态链接细节等等,写个在现有平台上能用的链接器是很困难的。

ld 不好么。

论坛徽章:
0
9 [报告]
发表于 2013-09-22 20:13 |只看该作者
本帖最后由 landker 于 2013-09-22 20:24 编辑
captivated 发表于 2013-09-22 19:59
首先,LZ用了BFD库没有。


?? BFD库是什么来的?

我一共写了2个小程序,一个用于生成 *.o(test_nasm),一个用于生成可执行文件(test_ld)......

不过,编译第一个小程序(test_nasm)时,曾经碰到这样的提示:”ld: BFD (GNU Binutils for Ubuntu) 2.22 assertion fail ../../bfd/elf.c:1876“。然而,还是编译成功

captivated 发表于 2013-09-22 19:59
其次,ELF格式标准文档读完烂熟了?

.....这个我真的不知道怎么回你才好......



论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
10 [报告]
发表于 2013-09-22 20:29 |只看该作者
回复 9# landker


    BFD库是GNU binutils中用于操纵各种目标文件的库。要写链接器,当然从BFD库入手比较好。不然你怎么链接目标文件的?完全解析ELF格式,得到各.text section, .data section的信息,然后手动叠加section, 重新进行全局地址重定位计算?重定位还要修正指令部的啊。OMG, 这个工作量不是一般的大。我好奇你的链接器怎么写的。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP