源码本身都没有问题,同样的代码在另外一个环境编译之后,可以正常调试
nasm -f elf -o lib/kernel/print.o lib/kernel/print.S
#gcc -m32 -I ./lib/kernel -fPIC -c -o kernel/main.o kernel/main.c
gcc -m32 -I ./lib/kernel -c -o kernel/main.o kernel/main.c
ld -m elf_i386 -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o
#ld -m elf_i386 -pie -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o
在bochs上调试到执行该处程序就重置了,kernel.bin程序没有正常拷贝到内存
(0).[17645092] [0x000000000e82] 0008:0000000000000e82 (unk. ctxt): rep movsb byte ptr es:[edi], byte ptr ds:[esi] ; f3a4
Next at t=17645093
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
对比两个不同的linux的操作系统,发现gcc的版本不一致,一个是8.3 ,一个是9.0,有问题的就是8.3
gcc version 8.3.0
在调试汇编的时候发现,会有如下地址
0x08048000
用命令查看
readelf -a kernel/kernel.bin
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0xc0001500
Start of program headers: 52 (bytes into file)
Start of section headers: 9484 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 10
Section header string table index: 9
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .note.gnu.propert NOTE 080480f4 0000f4 00001c 00 A 0 0 4
[ 2] .text PROGBITS c0001500 000500 0001ee 00 AX 0 0 16
[ 3] .rodata PROGBITS c0002000 001000 00000d 00 A 0 0 1
[ 4] .eh_frame PROGBITS c0002010 001010 00003c 00 A 0 0 4
[ 5] .data PROGBITS c0004000 002000 000008 00 WA 0 0 4
[ 6] .comment PROGBITS 00000000 002008 00001f 01 MS 0 0 1
[ 7] .symtab SYMTAB 00000000 002028 000280 10 8 33 4
[ 8] .strtab STRTAB 00000000 0022a8 00020c 00 0 0 1
[ 9] .shstrtab STRTAB 00000000 0024b4 000055 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x00110 0x00110 R 0x1000
LOAD 0x000500 0xc0001500 0xc0001500 0x001ee 0x001ee R E 0x1000
LOAD 0x001000 0xc0002000 0xc0002000 0x0004c 0x0004c R 0x1000
LOAD 0x002000 0xc0004000 0xc0004000 0x00008 0x00008 RW 0x1000
NOTE 0x0000f4 0x080480f4 0x080480f4 0x0001c 0x0001c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Section to Segment mapping:
Segment Sections...
00 .note.gnu.property
01 .text
02 .rodata .eh_frame
03 .data
04 .note.gnu.property
05
在网上查看资料发现可以去除该段,有两种方法,第二种试过,的确可以
strip --remove-section=.note.gnu.property kernel/kernel.bin
objcopy --remove-section .note.gnu.property kernel/kernel.bin
readelf -a kernel/kernel.bin
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0xc0001500
Start of program headers: 52 (bytes into file)
Start of section headers: 9448 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 9
Section header string table index: 8
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS c0001500 000500 0001ee 00 AX 0 0 16
[ 2] .rodata PROGBITS c0002000 001000 00000d 00 A 0 0 1
[ 3] .eh_frame PROGBITS c0002010 001010 00003c 00 A 0 0 4
[ 4] .data PROGBITS c0004000 002000 000008 00 WA 0 0 4
[ 5] .comment PROGBITS 00000000 002008 00001f 01 MS 0 0 1
[ 6] .symtab SYMTAB 00000000 002028 000270 10 7 32 4
[ 7] .strtab STRTAB 00000000 002298 00020c 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 0024a4 000042 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x000f4 0x000f4 R 0x1000
LOAD 0x000500 0xc0001500 0xc0001500 0x001ee 0x001ee R E 0x1000
LOAD 0x001000 0xc0002000 0xc0002000 0x0004c 0x0004c R 0x1000
LOAD 0x002000 0xc0004000 0xc0004000 0x00008 0x00008 RW 0x1000
NOTE 0x000000 0x00000000 0x00000000 0x00000 0x00000 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
Section to Segment mapping:
Segment Sections...
00
01 .text
02 .rodata .eh_frame
03 .data
04
05
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
再运行可以正常运行成功
还有另外一种方法,在编译选项中增加-fPIC
nasm -f elf -o lib/kernel/print.o lib/kernel/print.S
gcc -m32 -I ./lib/kernel -fPIC -c -o kernel/main.o kernel/main.c
ld -m elf_i386 -pie -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o
ELF 头:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
类别: ELF32
数据: 2 补码,小端序 (little endian)
版本: 1 (current)
OS/ABI: UNIX - System V
ABI 版本: 0
类型: DYN (共享目标文件)
系统架构: Intel 80386
版本: 0x1
入口点地址: 0xc0001500
程序头起点: 52 (bytes into file)
Start of section headers: 9764 (bytes into file)
标志: 0x0
本头的大小: 52 (字节)
程序头大小: 32 (字节)
Number of program headers: 9
节头大小: 40 (字节)
节头数量: 17
字符串表索引节头: 16
节头:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS c0001500 000500 0001fe 00 AX 0 0 16
[ 2] .interp PROGBITS 00000154 000154 000013 00 A 0 0 1
[ 3] .hash HASH 00000168 000168 000010 04 A 5 0 4
[ 4] .gnu.hash GNU_HASH 00000178 000178 000018 04 A 5 0 4
[ 5] .dynsym DYNSYM 00000190 000190 000010 10 A 6 1 4
[ 6] .dynstr STRTAB 000001a0 0001a0 000001 00 A 0 0 1
[ 7] .rel.dyn REL 000001a4 0001a4 000018 08 A 5 0 4
[ 8] .rodata PROGBITS c0002000 001000 00000d 00 A 0 0 1
[ 9] .eh_frame PROGBITS c0002010 001010 000054 00 A 0 0 4
[10] .dynamic DYNAMIC c0003f68 001f68 000098 08 WA 6 0 4
[11] .got.plt PROGBITS c0004000 002000 00000c 04 WA 0 0 4
[12] .data PROGBITS c000400c 00200c 000008 00 WA 0 0 4
[13] .comment PROGBITS 00000000 002014 00001f 01 MS 0 0 1
[14] .symtab SYMTAB 00000000 002034 000330 10 15 43 4
[15] .strtab STRTAB 00000000 002364 000241 00 0 0 1
[16] .shstrtab STRTAB 00000000 0025a5 00007f 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
程序头:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00120 0x00120 R 0x4
INTERP 0x000154 0x00000154 0x00000154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /usr/lib/libc.so.1]
LOAD 0x000000 0x00000000 0x00000000 0x001bc 0x001bc R 0x1000
LOAD 0x000500 0xc0001500 0xc0001500 0x001fe 0x001fe R E 0x1000
LOAD 0x001000 0xc0002000 0xc0002000 0x00064 0x00064 R 0x1000
LOAD 0x001f68 0xc0003f68 0xc0003f68 0x000ac 0x000ac RW 0x1000
DYNAMIC 0x001f68 0xc0003f68 0xc0003f68 0x00098 0x00098 RW 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
GNU_RELRO 0x001f68 0xc0003f68 0xc0003f68 0x00098 0x00098 R 0x1
Section to Segment mapping:
段节...
00
01 .interp
02 .interp .hash .gnu.hash .dynsym .dynstr .rel.dyn
03 .text
04 .rodata .eh_frame
05 .dynamic .got.plt .data
06 .dynamic
07
08 .dynamic
Dynamic section at offset 0x1f68 contains 15 entries:
标记 类型 名称/值
0x00000004 (HASH) 0x168
0x6ffffef5 (GNU_HASH) 0x178
0x00000005 (STRTAB) 0x1a0
0x00000006 (SYMTAB) 0x190
0x0000000a (STRSZ) 1 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000011 (REL) 0x1a4
0x00000012 (RELSZ) 24 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x00000016 (TEXTREL) 0x0
0x0000001e (FLAGS) TEXTREL
0x6ffffffb (FLAGS_1) 标志: PIE
0x6ffffffa (RELCOUNT) 3
0x00000000 (NULL) 0x0
重定位节 '.rel.dyn' at offset 0x1a4 contains 3 entries:
偏移量 信息 类型 符号值 符号名称
c00016ae 00000008 R_386_RELATIVE
c00016d8 00000008 R_386_RELATIVE
c00016f3 00000008 R_386_RELATIVE
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
汇编代码调试完了,调试C代码,需要用到GDB
重新编译bochs
./configure --prefix=/home/king/bochs_gdb/ --enable-disasm --enable-iodebug --with-x11 --with-x --enable-gdb-stub
在配置文件中增加该配置:
gdbstub:enable=1,port=1234,text_base=0,data_base=0,bss_base=0
gcc 必须以-g编译C源码,当使用ld链接时,去掉-s选项 ,查看是否二进制带有debug信息
file build/kernel.bin
build/kernel.bin: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, with debug_info, not stripped
调试步骤
打开两个终端,在第一个终端中运行Bochs:
$:bochs -f bochsrc
在第二个终端中运行GDB:
$:gdb ./src/kernel.bin
进入gdb命令行,在gdb命令行中输入命令:
break main(在main函数开始处下断点)
target remote localhost:1234(连接到Bochs)