Ubuntu18.04下編譯Linux0.12筆記(編譯+調試學習1)

一、下載源代碼
網站:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
注:上面的網站下載速度十分快。官網的代碼下載速度很慢,不知道怎麼搞的。
二、安裝x86的as86和ld86
(查找as86和ld86兩個工具所在的軟件包)輸入

apt-cache search as86 ld86

獲取as86和ld86所在的安裝包名稱。
此時終端可能提示: “bin86 - 16-bit x86 assembler and loader”,說明bin86包含了我們所需要的兩個軟件。

sudo apt install bin86

在這裏插入圖片描述
在bootsect.S中,as86無法識別c語言的註釋,需要在前面加上!註釋。
三、
make---錯誤1:

cpp -nostdinc -Iinclude -traditional boot/bootsect.S -o boot/bootsect.s
as86 -0 -a -o boot/bootsect.o boot/bootsect.s
ld86 -0 -s -o boot/bootsect boot/bootsect.o
cpp -nostdinc -Iinclude -traditional boot/setup.S -o boot/setup.s
as86 -0 -a -o boot/setup.o boot/setup.s
ld86 -0 -s -o boot/setup boot/setup.o
gas -c -o boot/head.o boot/head.s
make: gas: Command not found
Makefile:35: recipe for target 'boot/head.o' failed
make: *** [boot/head.o] Error 127

將AS由 gas 改爲 as , LD由 gld 改爲 ld。

 sed -i "s/gar/ar/g" `grep gar -rl ~/github/linux0.12/`
 sed -i "s/gas/as --32/g" `grep gas -rl ~/github/linux0.12/`
 sed -i "s/gld/ld -m elf_i386/g" `grep gld -rl ~/github/linux0.12/`
 sed -i "s/gcc/gcc -m32/g" `grep gcc -rl ~/github/linux0.12/`
 sed -i "s/.align 2/.align 4/g" `grep ".align\ 2" -rl ~/github/linux0.12/`
 sed -i "s/.align 3/.align 8/g" `grep ".align\ 3" -rl ~/github/linux0.12/`
 sed -i "s/-fcombine-regs//g" `grep "\-fcombine-regs" -rl ~/github/linux0.12`
 sed -i "s/-mstring-insns//g" `grep "\-mstring-insns" -rl ~/github/linux0.12/`

make---錯誤2:

as --32 -c -o boot/head.o boot/head.s
gcc -m32  -Wall -O -fstrength-reduce -fomit-frame-pointer  \
-nostdinc -Iinclude -c -o init/main.o init/main.c
In file included from init/main.c:8:0:
init/main.c:23:29: error: static declaration of ‘fork’ follows non-static declaration
 static inline _syscall0(int,fork)
                             ^
include/unistd.h:151:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:227:5: note: previous declaration of ‘fork’ was here
 int fork(void);
     ^~~~
init/main.c:24:29: error: static declaration of ‘pause’ follows non-static declaration
 static inline _syscall0(int,pause)
                             ^
include/unistd.h:151:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:241:5: note: previous declaration of ‘pause’ was here
 int pause(void);
     ^~~~~
init/main.c:26:29: error: static declaration of ‘sync’ follows non-static declaration
 static inline _syscall0(int,sync)
                             ^
include/unistd.h:151:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:252:5: note: previous declaration of ‘sync’ was here
 int sync(void);
     ^~~~
......

main.c line23/24/25/26把static去掉
make---錯誤3:

init/main.c:179:12: error: static declaration of ‘printf’ follows non-static declaration
 static int printf(const char *fmt, ...)
            ^~~~~~
In file included from include/linux/mm.h:6:0,
                 from include/linux/sched.h:36,
                 from init/main.c:29:
include/linux/kernel.h:7:5: note: previous declaration of ‘printf’ was here
 int printf(const char * fmt, ...);

main.c line179把static去掉?
make---錯誤4:

include/string.h:29:1: error: ‘asm’ operand has impossible constraints
 __asm__("cld\n"

include/string.h:
line34::“S” (src),“D” (dest):“si”,“di”,“ax”);
line50::“S” (src),“D” (dest),“c” (count):“si”,“di”,“ax”,“cx”);
line64::“S” (src),“D” (dest),“a” (0),“c” (0xffffffff):“si”,“di”,“ax”,“cx”);
line84:“si”,“di”,“ax”,“cx”);
line103:"=a" (__res):“D” (cs),“S” (ct):“si”,“di”);
line124:"=a" (__res):“D” (cs),“S” (ct),“c” (count):“si”,“di”,“cx”);
line141:"=a" (__res):“S” (s),“0” ©:“si”);
line157:"=d" (__res):“0” (0),“S” (s),“a” ©:“ax”,“si”);
line181:“ax”,“cx”,“dx”,“di”);
line205:“ax”,“cx”,“dx”,“di”);
line232:“ax”,“cx”,“dx”,“di”);
line259:“cx”,“dx”,“di”,“si”);
line271:"=c" (__res):“D” (s),“a” (0),“0” (0xffffffff):“di”);
line332:“ax”,“cx”,“dx”,“di”);
line342:“cx”,“si”,“di”);
line353:“cx”,“si”,“di”);
line359:“cx”,“si”,“di”);
line375:“si”,“di”,“cx”);
line391:“cx”);
line401:“cx”,“di”);

main.c:
line176:asm(“int $0x80”::“a” (__NR_pause):“ax”);

sched.h:
line248:“dx”)
line260:“dx”)

memory.h:
line45:asm(“cld ; rep ; movsl”::“S” (from),“D” (to),“c” (1024):“cx”,“di”,“si”)

swap.c:
line191: :“di”,“cx”,“dx”);
buffer.c:
line288: :“cx”,“di”,“si”)

namei.c:
line82:“cx”,“di”,“si”);

bitmap.c:
line17::“a” (0),“c” (BLOCK_SIZE/4),“D” ((long) (addr)):“cx”,“di”)
line44:"=c" (__res):“c” (0),“S” (addr):“ax”,“dx”,“si”); \

floppy.c:
line159:“cx”,“di”,“si”)

hd.c:
line65:asm(“cld;rep;insw”::“d” (port),“D” (buf),“c” (nr):“cx”,“di”)
line68:asm(“cld;rep;outsw”::“d” (port),“S” (buf),“c” (nr):“cx”,“si”)

memory.h:
line12:“di”,“si”,“cx”); \

console.c:
line209:“cx”,“di”,“si”);
line220:“cx”,“di”);
line234:“cx”,“di”,“si”);
line249: :“cx”,“di”,“si”);
line270: :“ax”,“cx”,“di”,“si”);
line285 :“ax”,“cx”,“di”,“si”);
line350 :“cx”,“di”);
line381 :“cx”,“di”);
line604 :“ax”);
line1020 :“ax”);

寄存器全刪掉。網上方法(待驗證):

sed -i 's/\(:*.*:*\):.*);$/\1);/g' include/string.h 
sed -i 's/:"dx")/)/g' include/linux/sched.h 
sed -i '55s/\(:*.*:*\):.*)$/\1)/g' mm/memory.c 
sed -i '81s/\(:*.*:*\):.*);$/\1);/g' mm/memory.c 
sed -i '288s/\(:*.*:*\):.*)$/\1)/g' fs/buffer.c 
sed -i '76s/\(:*.*:*\):.*);$/\1);/g' mm/memory.c 
sed -i '17s/\(:*.*:*\):.*)$/\1)/g' fs/bitmap.c 
sed -i '44s/\(:*.*:*\):.*);/\1);/g' fs/bitmap.c 
sed -i '158s/\(:*.*:*\):.*)/\1)/g' kernel/blk_drv/floppy.c 
sed -i '62s/\(:*.*:*\):.*)/\1)/g' kernel/blk_drv/hd.c 
sed -i '65s/\(:*.*:*\):.*)/\1)/g' kernel/blk_drv/hd.c 
sed -i '12s/\(:*.*:*\):.*);/\1);/g' include/asm/memory.h 
sed -i 's/\(:*.*:*\):.*);$/\1);/g' kernel/chr_drv/console.c

注:asm指令
GCC中基本的內聯彙編:asm____volatile(“InstructionList”);

asm(
“movl $1,%eax\r\t”
“xor %ebx,%ebx\r\t”
“int $0x80”
);

帶有C/C++表達式的內聯彙編:

asm volatile(“InstructionList”
:Output
:Input
:Clobber/Modify);

這4個部分都不是必須的,任何一個部分都可以爲空,其規則爲:

1、如果Clobber/Modify 爲空,則其前面的冒號(:)必須省略。

2、如果Output,Input,Clobber/Modify都爲空,Output,Input之前的冒號(:)既可以省略,也可以不省略。

3、如果Input,Clobber/Modify爲空,但Output不爲空,Input前的冒號(:)既可以省略,也可以不省略。

4、如果後面的部分不爲空,而前面的部分爲空,則前面的冒號(:)都必須保留,否則無法說明不爲空的部分究竟是第幾部分。

每一個Input和Output表達式都必須指定自己的操作約束Operation Constraint,這裏將討論在80386平臺上所可能使用的操作約束。

當前的輸入或輸出需要藉助一個寄存器時,需要爲其指定一個寄存器約束,可以直接指定一個寄存器的名字。

常用的寄存器約束的縮寫
約束 意義
r 表示使用一個通用寄存器,由 GCC 在%eax/%ax/%al,%ebx/%bx/%bl,%ecx/%cx/%cl,%edx/%dx/%dl中選取一個GCC認爲合適的。
g 表示使用任意一個寄存器,由GCC在所有的可以使用的寄存器中選取一個GCC認爲合適的。
q 表示使用一個通用寄存器,和約束r的意義相同。
a 表示使用%eax/%ax/%al
b 表示使用%ebx/%bx/%bl
c 表示使用%ecx/%cx/%cl
d 表示使用%edx/%dx/%dl
D 表示使用%edi/%di
S 表示使用%esi/%si
f 表示使用浮點寄存器
t 表示使用第一個浮點寄存器
u 表示使用第二個浮點寄存器

如果一個Input/Output 操作表達式的C/C++表達式表現爲一個內存地址,不想藉助於任何寄存器,則可以使用內存約束。比如:
asm(“lidt%0”:"=m"(__idt_addr));
asm(“lidt%0”::“m”(__idt_addr));

修飾符 輸入/輸出 意義
= O 表示此Output操作表達式是Write-Only的。

  •             O               表示此Output操作表達式是Read-Write的。
    

& O 表示此Output操作表達式獨佔爲其指定的寄存器。
% I 表示此Input 操作表達式中的C/C++表達式可以和下一 個Input操作表達式中的C/C++表達式互換

make---錯誤5:

ld -m elf_i386 -r -o kernel.o sched.o sys_call.o traps.o asm.o fork.o panic.o printk.o vsprintf.o sys.o exit.o signal.o mktime.o
traps.o:在函數‘oom’中:
traps.c:(.text+0x49d): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
traps.o:在函數‘get_fs_byte’中:
traps.c:(.text+0x4c9): `get_fs_byte'被多次定義
sched.o:sched.c:(.text+0x141):第一次在此定義
traps.o:在函數‘get_fs_word’中:
traps.c:(.text+0x4d1): `get_fs_word'被多次定義
sched.o:sched.c:(.text+0x149):第一次在此定義
traps.o:在函數‘get_fs_long’中:
traps.c:(.text+0x4da): `get_fs_long'被多次定義
sched.o:sched.c:(.text+0x152):第一次在此定義
traps.o:在函數‘put_fs_byte’中:
traps.c:(.text+0x4e2): `put_fs_byte'被多次定義
sched.o:sched.c:(.text+0x15a):第一次在此定義
traps.o:在函數‘put_fs_word’中:
traps.c:(.text+0x4ee): `put_fs_word'被多次定義
sched.o:sched.c:(.text+0x166):第一次在此定義
traps.o:在函數‘put_fs_long’中:
traps.c:(.text+0x4fb): `put_fs_long'被多次定義
sched.o:sched.c:(.text+0x173):第一次在此定義
traps.o:在函數‘get_fs’中:
traps.c:(.text+0x507): `get_fs'被多次定義
sched.o:sched.c:(.text+0x17f):第一次在此定義
traps.o:在函數‘get_ds’中:
traps.c:(.text+0x50e): `get_ds'被多次定義
sched.o:sched.c:(.text+0x186):第一次在此定義
traps.o:在函數‘set_fs’中:
traps.c:(.text+0x515): `set_fs'被多次定義
sched.o:sched.c:(.text+0x18d):第一次在此定義
fork.o:在函數‘oom’中:
fork.c:(.text+0x0): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
fork.o:在函數‘get_fs_byte’中:
fork.c:(.text+0x2c): `get_fs_byte'被多次定義
sched.o:sched.c:(.text+0x141):第一次在此定義
fork.o:在函數‘get_fs_word’中:
fork.c:(.text+0x34): `get_fs_word'被多次定義
sched.o:sched.c:(.text+0x149):第一次在此定義
fork.o:在函數‘get_fs_long’中:
fork.c:(.text+0x3d): `get_fs_long'被多次定義
sched.o:sched.c:(.text+0x152):第一次在此定義
fork.o:在函數‘put_fs_byte’中:
fork.c:(.text+0x45): `put_fs_byte'被多次定義
sched.o:sched.c:(.text+0x15a):第一次在此定義
fork.o:在函數‘put_fs_word’中:
fork.c:(.text+0x51): `put_fs_word'被多次定義
sched.o:sched.c:(.text+0x166):第一次在此定義
fork.o:在函數‘put_fs_long’中:
fork.c:(.text+0x5e): `put_fs_long'被多次定義
sched.o:sched.c:(.text+0x173):第一次在此定義
fork.o:在函數‘get_fs’中:
fork.c:(.text+0x6a): `get_fs'被多次定義
sched.o:sched.c:(.text+0x17f):第一次在此定義
fork.o:在函數‘get_ds’中:
fork.c:(.text+0x71): `get_ds'被多次定義
sched.o:sched.c:(.text+0x186):第一次在此定義
fork.o:在函數‘set_fs’中:
fork.c:(.text+0x78): `set_fs'被多次定義
sched.o:sched.c:(.text+0x18d):第一次在此定義
panic.o:在函數‘oom’中:
panic.c:(.text+0x0): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
vsprintf.o:在函數‘strcpy’中:
vsprintf.c:(.text+0x265): `strcpy'被多次定義
traps.o:traps.c:(.text+0x182):第一次在此定義
vsprintf.o:在函數‘strncpy’中:
vsprintf.c:(.text+0x27b): `strncpy'被多次定義
traps.o:traps.c:(.text+0x198):第一次在此定義
vsprintf.o:在函數‘strcat’中:
vsprintf.c:(.text+0x29a): `strcat'被多次定義
traps.o:traps.c:(.text+0x1b7):第一次在此定義
vsprintf.o:在函數‘strncat’中:
vsprintf.c:(.text+0x2bd): `strncat'被多次定義
traps.o:traps.c:(.text+0x1da):第一次在此定義
vsprintf.o:在函數‘strcmp’中:
vsprintf.c:(.text+0x2ea): `strcmp'被多次定義
traps.o:traps.c:(.text+0x207):第一次在此定義
vsprintf.o:在函數‘strncmp’中:
vsprintf.c:(.text+0x30d): `strncmp'被多次定義
traps.o:traps.c:(.text+0x22a):第一次在此定義
vsprintf.o:在函數‘strchr’中:
vsprintf.c:(.text+0x337): `strchr'被多次定義
traps.o:traps.c:(.text+0x254):第一次在此定義
vsprintf.o:在函數‘strrchr’中:
vsprintf.c:(.text+0x356): `strrchr'被多次定義
traps.o:traps.c:(.text+0x273):第一次在此定義
vsprintf.o:在函數‘strspn’中:
vsprintf.c:(.text+0x377): `strspn'被多次定義
traps.o:traps.c:(.text+0x294):第一次在此定義
vsprintf.o:在函數‘strcspn’中:
vsprintf.c:(.text+0x3aa): `strcspn'被多次定義
traps.o:traps.c:(.text+0x2c7):第一次在此定義
vsprintf.o:在函數‘strpbrk’中:
vsprintf.c:(.text+0x3df): `strpbrk'被多次定義
traps.o:traps.c:(.text+0x2fc):第一次在此定義
vsprintf.o:在函數‘strstr’中:
vsprintf.c:(.text+0x412): `strstr'被多次定義
traps.o:traps.c:(.text+0x32f):第一次在此定義
vsprintf.o:在函數‘strlen’中:
vsprintf.c:(.text+0x445): `strlen'被多次定義
traps.o:traps.c:(.text+0x362):第一次在此定義
vsprintf.o:在函數‘strtok’中:
vsprintf.c:(.text+0x45e): `strtok'被多次定義
traps.o:traps.c:(.text+0x37b):第一次在此定義
vsprintf.o:在函數‘memcpy’中:
vsprintf.c:(.text+0x4e5): `memcpy'被多次定義
traps.o:traps.c:(.text+0x402):第一次在此定義
vsprintf.o:在函數‘memmove’中:
vsprintf.c:(.text+0x4fb): `memmove'被多次定義
traps.o:traps.c:(.text+0x418):第一次在此定義
vsprintf.o:在函數‘memcmp’中:
vsprintf.c:(.text+0x521): `memcmp'被多次定義
traps.o:traps.c:(.text+0x43e):第一次在此定義
vsprintf.o:在函數‘memchr’中:
vsprintf.c:(.text+0x545): `memchr'被多次定義
traps.o:traps.c:(.text+0x462):第一次在此定義
vsprintf.o:在函數‘memset’中:
vsprintf.c:(.text+0x56c): `memset'被多次定義
traps.o:traps.c:(.text+0x489):第一次在此定義
sys.o:在函數‘oom’中:
sys.c:(.text+0x0): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
sys.o:在函數‘get_fs_byte’中:
sys.c:(.text+0x2c): `get_fs_byte'被多次定義
sched.o:sched.c:(.text+0x141):第一次在此定義
sys.o:在函數‘get_fs_word’中:
sys.c:(.text+0x34): `get_fs_word'被多次定義
sched.o:sched.c:(.text+0x149):第一次在此定義
sys.o:在函數‘get_fs_long’中:
sys.c:(.text+0x3d): `get_fs_long'被多次定義
sched.o:sched.c:(.text+0x152):第一次在此定義
sys.o:在函數‘put_fs_byte’中:
sys.c:(.text+0x45): `put_fs_byte'被多次定義
sched.o:sched.c:(.text+0x15a):第一次在此定義
sys.o:在函數‘put_fs_word’中:
sys.c:(.text+0x51): `put_fs_word'被多次定義
sched.o:sched.c:(.text+0x166):第一次在此定義
sys.o:在函數‘put_fs_long’中:
sys.c:(.text+0x5e): `put_fs_long'被多次定義
sched.o:sched.c:(.text+0x173):第一次在此定義
sys.o:在函數‘get_fs’中:
sys.c:(.text+0x6a): `get_fs'被多次定義
sched.o:sched.c:(.text+0x17f):第一次在此定義
sys.o:在函數‘get_ds’中:
sys.c:(.text+0x71): `get_ds'被多次定義
sched.o:sched.c:(.text+0x186):第一次在此定義
sys.o:在函數‘set_fs’中:
sys.c:(.text+0x78): `set_fs'被多次定義
sched.o:sched.c:(.text+0x18d):第一次在此定義
sys.o:在函數‘strcpy’中:
sys.c:(.text+0x7f): `strcpy'被多次定義
traps.o:traps.c:(.text+0x182):第一次在此定義
sys.o:在函數‘strncpy’中:
sys.c:(.text+0x95): `strncpy'被多次定義
traps.o:traps.c:(.text+0x198):第一次在此定義
sys.o:在函數‘strcat’中:
sys.c:(.text+0xb4): `strcat'被多次定義
traps.o:traps.c:(.text+0x1b7):第一次在此定義
sys.o:在函數‘strncat’中:
sys.c:(.text+0xd7): `strncat'被多次定義
traps.o:traps.c:(.text+0x1da):第一次在此定義
sys.o:在函數‘strcmp’中:
sys.c:(.text+0x104): `strcmp'被多次定義
traps.o:traps.c:(.text+0x207):第一次在此定義
sys.o:在函數‘strncmp’中:
sys.c:(.text+0x127): `strncmp'被多次定義
traps.o:traps.c:(.text+0x22a):第一次在此定義
sys.o:在函數‘strchr’中:
sys.c:(.text+0x151): `strchr'被多次定義
traps.o:traps.c:(.text+0x254):第一次在此定義
sys.o:在函數‘strrchr’中:
sys.c:(.text+0x170): `strrchr'被多次定義
traps.o:traps.c:(.text+0x273):第一次在此定義
sys.o:在函數‘strspn’中:
sys.c:(.text+0x191): `strspn'被多次定義
traps.o:traps.c:(.text+0x294):第一次在此定義
sys.o:在函數‘strcspn’中:
sys.c:(.text+0x1c4): `strcspn'被多次定義
traps.o:traps.c:(.text+0x2c7):第一次在此定義
sys.o:在函數‘strpbrk’中:
sys.c:(.text+0x1f9): `strpbrk'被多次定義
traps.o:traps.c:(.text+0x2fc):第一次在此定義
sys.o:在函數‘strstr’中:
sys.c:(.text+0x22c): `strstr'被多次定義
traps.o:traps.c:(.text+0x32f):第一次在此定義
sys.o:在函數‘strlen’中:
sys.c:(.text+0x25f): `strlen'被多次定義
traps.o:traps.c:(.text+0x362):第一次在此定義
sys.o:在函數‘strtok’中:
sys.c:(.text+0x278): `strtok'被多次定義
traps.o:traps.c:(.text+0x37b):第一次在此定義
sys.o:在函數‘memcpy’中:
sys.c:(.text+0x2ff): `memcpy'被多次定義
traps.o:traps.c:(.text+0x402):第一次在此定義
sys.o:在函數‘memmove’中:
sys.c:(.text+0x315): `memmove'被多次定義
traps.o:traps.c:(.text+0x418):第一次在此定義
sys.o:在函數‘memcmp’中:
sys.c:(.text+0x33b): `memcmp'被多次定義
traps.o:traps.c:(.text+0x43e):第一次在此定義
sys.o:在函數‘memchr’中:
sys.c:(.text+0x35f): `memchr'被多次定義
traps.o:traps.c:(.text+0x462):第一次在此定義
sys.o:在函數‘memset’中:
sys.c:(.text+0x386): `memset'被多次定義
traps.o:traps.c:(.text+0x489):第一次在此定義
exit.o:在函數‘get_fs_byte’中:
exit.c:(.text+0x44): `get_fs_byte'被多次定義
sched.o:sched.c:(.text+0x141):第一次在此定義
exit.o:在函數‘get_fs_word’中:
exit.c:(.text+0x4c): `get_fs_word'被多次定義
sched.o:sched.c:(.text+0x149):第一次在此定義
exit.o:在函數‘get_fs_long’中:
exit.c:(.text+0x55): `get_fs_long'被多次定義
sched.o:sched.c:(.text+0x152):第一次在此定義
exit.o:在函數‘put_fs_byte’中:
exit.c:(.text+0x5d): `put_fs_byte'被多次定義
sched.o:sched.c:(.text+0x15a):第一次在此定義
exit.o:在函數‘put_fs_word’中:
exit.c:(.text+0x69): `put_fs_word'被多次定義
sched.o:sched.c:(.text+0x166):第一次在此定義
exit.o:在函數‘put_fs_long’中:
exit.c:(.text+0x76): `put_fs_long'被多次定義
sched.o:sched.c:(.text+0x173):第一次在此定義
exit.o:在函數‘get_fs’中:
exit.c:(.text+0x82): `get_fs'被多次定義
sched.o:sched.c:(.text+0x17f):第一次在此定義
exit.o:在函數‘get_ds’中:
exit.c:(.text+0x89): `get_ds'被多次定義
sched.o:sched.c:(.text+0x186):第一次在此定義
exit.o:在函數‘set_fs’中:
exit.c:(.text+0x90): `set_fs'被多次定義
sched.o:sched.c:(.text+0x18d):第一次在此定義
exit.o:在函數‘oom’中:
exit.c:(.text+0xc6d): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
signal.o:在函數‘oom’中:
signal.c:(.text+0x0): `oom'被多次定義
sched.o:sched.c:(.text+0x115):第一次在此定義
signal.o:在函數‘get_fs_byte’中:
signal.c:(.text+0x2c): `get_fs_byte'被多次定義
sched.o:sched.c:(.text+0x141):第一次在此定義
signal.o:在函數‘get_fs_word’中:
signal.c:(.text+0x34): `get_fs_word'被多次定義
sched.o:sched.c:(.text+0x149):第一次在此定義
signal.o:在函數‘get_fs_long’中:
signal.c:(.text+0x3d): `get_fs_long'被多次定義
sched.o:sched.c:(.text+0x152):第一次在此定義
signal.o:在函數‘put_fs_byte’中:
signal.c:(.text+0x45): `put_fs_byte'被多次定義
sched.o:sched.c:(.text+0x15a):第一次在此定義
signal.o:在函數‘put_fs_word’中:
signal.c:(.text+0x51): `put_fs_word'被多次定義
sched.o:sched.c:(.text+0x166):第一次在此定義
signal.o:在函數‘put_fs_long’中:
signal.c:(.text+0x5e): `put_fs_long'被多次定義
sched.o:sched.c:(.text+0x173):第一次在此定義
signal.o:在函數‘get_fs’中:
signal.c:(.text+0x6a): `get_fs'被多次定義
sched.o:sched.c:(.text+0x17f):第一次在此定義
signal.o:在函數‘get_ds’中:
signal.c:(.text+0x71): `get_ds'被多次定義
sched.o:sched.c:(.text+0x186):第一次在此定義
signal.o:在函數‘set_fs’中:
signal.c:(.text+0x78): `set_fs'被多次定義
sched.o:sched.c:(.text+0x18d):第一次在此定義
Makefile:32: recipe for target 'kernel.o' failed
make[1]: *** [kernel.o] Error 1
make[1]: 離開目錄“/home/jackhao/github/linux0.12/kernel”
Makefile:75: recipe for target 'kernel/kernel.o' failed
make: *** [kernel/kernel.o] Error 2

segment.h中定義的函數extern inline全部改成static inline的
string.h中定義的函數extern inline全部改成static inline的
mm.h中定義的函數extern inline全部改成static inline的

make---錯誤6:

-c -o file_dev.o file_dev.c
file_dev.c: In function ‘file_read’:
file_dev.c:25:7: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
       ^~
file_dev.c:46:1: error: unsupported size for integer register
 }

上述錯誤需要關閉編譯優化來解決,即
去掉fs的Makefile中gcc編譯參數中的-O,
去掉kernel/chr_drv的Makefile中gcc編譯參數中的-O,
去掉kernel/math的Makefile中gcc編譯參數中的-O,
重新編譯.

make---錯誤7:

exec.c:162:44: error: lvalue required as left operand of assignment
         !(pag = (char *) page[p/PAGE_SIZE] =

exec.c line161->164

				if (!(pag = (char *) page[p/PAGE_SIZE]) &&
				    !(pag = (char *) page[p/PAGE_SIZE] =
				      (unsigned long *) get_free_page())) 
					return 0;

更改爲:

				if ((!page[p/PAGE_SIZE]) &&                                                                                                      
				    !(page[p/PAGE_SIZE] =
				      (unsigned long *) get_free_page()))                                                                                       
				    return 0;                                                                                                                   
				else                                                                                                                            
				    pag = (char *) page[p/PAGE_SIZE];

make---錯誤8:

../../include/ctype.h:32:29: note: in expansion of macro ‘islower’
 #define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp)
                             ^~~~~~~
tty_io.c:370:8: note: in expansion of macro ‘toupper’
      c=toupper(c);
        ^~~~~~~
tty_io.c:381:1: error: unsupported size for integer register
 }

make---錯誤9:

gcc -m32 -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions  -nostdinc -I../include \
-c -o malloc.o malloc.c
malloc.c: In function ‘malloc’:
malloc.c:156:46: error: lvalue required as left operand of assignment
   bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
                                              ^
Makefile:24: recipe for target 'malloc.o' failed

malloc.c:

bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();

更改爲:

		cp = get_free_page();
		bdesc->page = bdesc->freeptr = (void *) cp;

make---錯誤10:

(cd lib; make)
make[1]: 進入目錄“/home/jackhao/github/linux0.12/lib”
gcc -m32 -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions  -nostdinc -I../include \
-c -o malloc.o malloc.c
malloc.c: In function ‘malloc’:
malloc.c:157:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
   cp = get_free_page();
      ^
malloc.c: In function ‘free_s’:
malloc.c:215:21: warning: ‘prev’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   if ((prev && (prev->next != bdesc)) ||
                 ~~~~^~~~~~
ar rcs lib.a ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o execve.o wait.o string.o malloc.o
sync
make[1]: 離開目錄“/home/jackhao/github/linux0.12/lib”
ld -m elf_i386 -s -x -M boot/head.o init/main.o \
kernel/kernel.o mm/mm.o fs/fs.o \
kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \
kernel/math/math.a \
lib/lib.a \
-o tools/system > System.map
kernel/blk_drv/blk_drv.a(hd.o):在函數‘unlock_buffer’中:
hd.c:(.text+0x919): `unlock_buffer'被多次定義
kernel/blk_drv/blk_drv.a(floppy.o):floppy.c:(.text+0x7c3):第一次在此定義
kernel/blk_drv/blk_drv.a(hd.o):在函數‘end_request’中:
hd.c:(.text+0x95d): `end_request'被多次定義
kernel/blk_drv/blk_drv.a(floppy.o):floppy.c:(.text+0x807):第一次在此定義
kernel/blk_drv/blk_drv.a(ramdisk.o):在函數‘unlock_buffer’中:
ramdisk.c:(.text+0x28e): `unlock_buffer'被多次定義
kernel/blk_drv/blk_drv.a(floppy.o):floppy.c:(.text+0x7c3):第一次在此定義
kernel/blk_drv/blk_drv.a(ramdisk.o):在函數‘end_request’中:
ramdisk.c:(.text+0x2d2): `end_request'被多次定義
kernel/blk_drv/blk_drv.a(floppy.o):floppy.c:(.text+0x807):第一次在此定義

blk.h頭文件
extern inline更改爲static inline
kernel/blk_drv/blk_drv.a(hd.o):在函數‘unlock_buffer’中:
hd.c:(.text+0x95d): `end_request’被多次定義

在函數里加上頭文件衛士
#ifndef
#define
func();
#endif

ld: 警告: 無法找到項目符號 _start; 缺省爲 00000000080480b8
boot/head.o:在函數‘startup_32’中:

這是因爲ld在將所有目標文件鏈接起來時,不知道程序的入口點在哪裏。由內核的啓動過程知其從head.s中開始執行,因此給head.s的 .text 段添加一句 .globl startup_32,然後給 ./Makefile 中的ld加上選項 -e startup_32 以指定入口點。

另外注意,僅指定入口點的標號還不夠,後續使用tools/build構建Image仍會出錯,因爲此時程序入口點的地址仍是0x8048098(見上方出錯信息的最後一行),而在tools/build.c中處理system模塊時,認定的合法入口點地址爲0x0:
因此還需添加 -Ttext 0 選項使startup_32標號對應的地址爲0x0(更詳細的說明見ld的手冊,另有一個討論見這裏)。

boot/head.o:在函數‘startup_32’中:
(.text+0x10):對‘_stack_start’未定義的引用
(.text+0x2e):對‘_stack_start’未定義的引用
boot/head.o:在函數‘after_page_tables’中:
(.text+0x540c):對‘_main’未定義的引用
boot/head.o:在函數‘ignore_int’中:
(.text+0x5440):對‘_printk’未定義的引用
init/main.o:在函數‘init’中:
main.c:(.text+0x282):對‘puts’未定義的引用
kernel/kernel.o:在函數‘schedule’中:
(.text+0x3f3):對‘_current’未定義的引用
(.text+0x400):對‘_current’未定義的引用
(.text+0x40a):對‘_last_task_used_math’未定義的引用
(.text+0x428):對‘__stack_chk_fail_local’未定義的引用
kernel/kernel.o:在函數‘sched_init’中:
(.text+0x9d3):對‘gdt’未定義的引用
(.text+0xa98):對‘idt’未定義的引用
(.text+0xaa3):對‘timer_interrupt’未定義的引用
(.text+0xace):對‘system_call’未定義的引用
kernel/kernel.o:在函數‘reschedule’中:
sys_call.o:(.text+0xaf6):對‘_schedule’未定義的引用
kernel/kernel.o:在函數‘_system_call’中:
(.text+0xb16):對‘_NR_syscalls’未定義的引用
(.text+0xb1f):對‘_sys_call_table’未定義的引用
(.text+0xb25):對‘_current’未定義的引用
kernel/kernel.o:在函數‘ret_from_sys_call’中:
sys_call.o:(.text+0xb35):對‘_current’未定義的引用
sys_call.o:(.text+0xb3b):對‘_task’未定義的引用
sys_call.o:(.text+0xb6c):對‘_do_signal’未定義的引用
kernel/kernel.o:在函數‘_coprocessor_error’中:
(.text+0xba4):對‘_math_error’未定義的引用
kernel/kernel.o:在函數‘_device_not_available’中:
(.text+0xbd3):對‘_math_state_restore’未定義的引用
(.text+0xbdd):對‘_math_emulate’未定義的引用
kernel/kernel.o:在函數‘_timer_interrupt’中:
(.text+0xc04):對‘_jiffies’未定義的引用
(.text+0xc15):對‘_do_timer’未定義的引用
kernel/kernel.o:在函數‘_sys_execve’中:
(.text+0xc2a):對‘_do_execve’未定義的引用
kernel/kernel.o:在函數‘_sys_fork’中:
(.text+0xc35):對‘_find_empty_process’未定義的引用
(.text+0xc44):對‘_copy_process’未定義的引用
kernel/kernel.o:在函數‘_hd_interrupt’中:
(.text+0xc6f):對‘_hd_timeout’未定義的引用
(.text+0xc75):對‘_do_hd’未定義的引用
(.text+0xc7e):對‘_unexpected_hd_interrupt’未定義的引用
kernel/kernel.o:在函數‘_floppy_interrupt’中:
(.text+0xcad):對‘_do_floppy’未定義的引用
(.text+0xcb6):對‘_unexpected_floppy_interrupt’未定義的引用
kernel/kernel.o:在函數‘trap_init’中:
(.text+0x1144):對‘idt’未定義的引用
(.text+0x114f):對‘divide_error’未定義的引用
(.text+0x1161):對‘debug’未定義的引用
(.text+0x1174):對‘nmi’未定義的引用
(.text+0x1187):對‘int3’未定義的引用
(.text+0x119a):對‘overflow’未定義的引用
(.text+0x11ad):對‘bounds’未定義的引用
(.text+0x11c0):對‘invalid_op’未定義的引用
(.text+0x11d3):對‘device_not_available’未定義的引用
(.text+0x11e6):對‘double_fault’未定義的引用
(.text+0x11f9):對‘coprocessor_segment_overrun’未定義的引用
(.text+0x120c):對‘invalid_TSS’未定義的引用
(.text+0x121f):對‘segment_not_present’未定義的引用
(.text+0x1232):對‘stack_segment’未定義的引用
(.text+0x1245):對‘general_protection’未定義的引用
(.text+0x1258):對‘page_fault’未定義的引用
(.text+0x126b):對‘reserved’未定義的引用
(.text+0x127e):對‘coprocessor_error’未定義的引用
(.text+0x1297):對‘alignment_check’未定義的引用
(.text+0x12bc):對‘reserved’未定義的引用
(.text+0x12d5):對‘idt’未定義的引用
(.text+0x12e0):對‘irq13’未定義的引用
(.text+0x131f):對‘parallel_interrupt’未定義的引用
kernel/kernel.o:在函數‘_divide_error’中:
(.text+0x133c):對‘_do_divide_error’未定義的引用
kernel/kernel.o:在函數‘_debug’中:
(.text+0x1371):對‘_do_int3’未定義的引用
kernel/kernel.o:在函數‘_nmi’中:
(.text+0x1378):對‘_do_nmi’未定義的引用
kernel/kernel.o:在函數‘_int3’中:
(.text+0x137f):對‘_do_int3’未定義的引用
kernel/kernel.o:在函數‘_overflow’中:
(.text+0x1386):對‘_do_overflow’未定義的引用
kernel/kernel.o:在函數‘_bounds’中:
(.text+0x138d):對‘_do_bounds’未定義的引用
kernel/kernel.o:在函數‘_invalid_op’中:
(.text+0x1394):對‘_do_invalid_op’未定義的引用
kernel/kernel.o:在函數‘_coprocessor_segment_overrun’中:
(.text+0x139b):對‘_do_coprocessor_segment_overrun’未定義的引用
kernel/kernel.o:在函數‘_reserved’中:
(.text+0x13a2):對‘_do_reserved’未定義的引用
kernel/kernel.o:在函數‘_double_fault’中:
(.text+0x13be):對‘_do_double_fault’未定義的引用
kernel/kernel.o:在函數‘_invalid_TSS’中:
(.text+0x13f5):對‘_do_invalid_TSS’未定義的引用
kernel/kernel.o:在函數‘_segment_not_present’中:
(.text+0x13fc):對‘_do_segment_not_present’未定義的引用
kernel/kernel.o:在函數‘_stack_segment’中:
(.text+0x1403):對‘_do_stack_segment’未定義的引用
kernel/kernel.o:在函數‘_general_protection’中:
(.text+0x140a):對‘_do_general_protection’未定義的引用
kernel/kernel.o:在函數‘_alignment_check’中:
(.text+0x1411):對‘_do_alignment_check’未定義的引用
kernel/kernel.o:在函數‘copy_process’中:
(.text+0x17e2):對‘gdt’未定義的引用
kernel/kernel.o:在函數‘number’中:
vsprintf.c:(.text+0x1bf5):對‘__stack_chk_fail_local’未定義的引用
kernel/kernel.o:在函數‘sys_getrusage’中:
(.text+0x29c0):對‘__stack_chk_fail_local’未定義的引用
kernel/kernel.o:在函數‘sys_sigaction’中:
(.text+0x3b83):對‘__stack_chk_fail_local’未定義的引用
kernel/kernel.o:(.data.rel+0x3ec):對‘pg_dir’未定義的引用
kernel/kernel.o:(.data.rel+0x1028):對‘sys_fork’未定義的引用
kernel/kernel.o:(.data.rel+0x104c):對‘sys_execve’未定義的引用
mm/mm.o:在函數‘do_no_page’中:
(.text+0xa0b):對‘__stack_chk_fail_local’未定義的引用
mm/mm.o:在函數‘show_mem’中:
(.text+0xb0c):對‘pg_dir’未定義的引用
mm/mm.o:在函數‘swap_out’中:
(.text+0xda7):對‘pg_dir’未定義的引用
(.text+0xdbf):對‘pg_dir’未定義的引用
(.text+0xdf5):對‘pg_dir’未定義的引用
mm/mm.o:在函數‘_page_fault’中:
(.text+0x1231):對‘_do_no_page’未定義的引用
(.text+0x1238):對‘_do_wp_page’未定義的引用
fs/fs.o:在函數‘sys_open’中:
(.text+0x5a6):對‘__stack_chk_fail_local’未定義的引用
fs/fs.o:在函數‘bread_page’中:
(.text+0x1c87):對‘__stack_chk_fail_local’未定義的引用
fs/fs.o:在函數‘cp_stat’中:
stat.c:(.text+0x2fca):對‘__stack_chk_fail_local’未定義的引用
fs/fs.o:在函數‘do_execve’中:
(.text+0x434c):對‘__stack_chk_fail_local’未定義的引用
fs/fs.o:在函數‘sys_pipe’中:
(.text+0x494f):對‘__stack_chk_fail_local’未定義的引用
fs/fs.o:namei.c:(.text+0x536e): 跟着更多未定義的參考到 __stack_chk_fail_local
kernel/blk_drv/blk_drv.a(floppy.o):在函數‘setup_DMA’中:
floppy.c:(.text+0x24):對‘tmp_floppy_area’未定義的引用
kernel/blk_drv/blk_drv.a(floppy.o):在函數‘rw_interrupt’中:
floppy.c:(.text+0xd82):對‘tmp_floppy_area’未定義的引用
kernel/blk_drv/blk_drv.a(floppy.o):在函數‘floppy_init’中:
floppy.c:(.text+0xebe):對‘idt’未定義的引用
floppy.c:(.text+0xec4):對‘floppy_interrupt’未定義的引用
kernel/blk_drv/blk_drv.a(hd.o):在函數‘hd_init’中:
hd.c:(.text+0xea6):對‘idt’未定義的引用
hd.c:(.text+0xeac):對‘hd_interrupt’未定義的引用
kernel/chr_drv/chr_drv.a(console.o):在函數‘scrup’中:
console.c:(.text+0x41b):對‘_video_num_columns’未定義的引用
console.c:(.text+0x694):對‘_video_num_columns’未定義的引用
console.c:(.text+0x797):對‘_video_num_columns’未定義的引用
kernel/chr_drv/chr_drv.a(console.o):在函數‘scrdown’中:
console.c:(.text+0x911):對‘_video_num_columns’未定義的引用
console.c:(.text+0xa1b):對‘_video_num_columns’未定義的引用
kernel/chr_drv/chr_drv.a(console.o):在函數‘con_init’中:
console.c:(.text+0x3aea):對‘idt’未定義的引用
console.c:(.text+0x3af6):對‘idt’未定義的引用
console.c:(.text+0x3b02):對‘keyboard_interrupt’未定義的引用
kernel/chr_drv/chr_drv.a(serial.o):在函數‘rs_init’中:
serial.c:(.text+0x92):對‘idt’未定義的引用
serial.c:(.text+0x9e):對‘idt’未定義的引用
serial.c:(.text+0xaa):對‘rs1_interrupt’未定義的引用
serial.c:(.text+0xc2):對‘idt’未定義的引用
serial.c:(.text+0xce):對‘idt’未定義的引用
serial.c:(.text+0xda):對‘rs2_interrupt’未定義的引用
kernel/chr_drv/chr_drv.a(tty_ioctl.o):在函數‘get_termio’中:
tty_ioctl.c:(.text+0x35c):對‘__stack_chk_fail_local’未定義的引用
kernel/chr_drv/chr_drv.a(tty_ioctl.o):在函數‘set_termio’中:

Makefile:58: recipe for target 'tools/system' failed
make: *** [tools/system] Error 1

head.s中的_開頭的變量和函數,去掉_
sys_call.s中的_開頭的變量和函數,去掉_
asm.s中的_開頭的變量和函數,去掉_

tty_ioctl.c:(.text+0x4c5):對‘__stack_chk_fail_local’未定義的引用

在所有Makefile文件中gcc編譯選項CFLAGS後添加-fno-stack-protector

make---錯誤11:

init/main.o:在函數‘init’中:
main.c:(.text+0x27b):對‘puts’未定義的引用
kernel/kernel.o:在函數‘trap_init’中:
(.text+0x1163):對‘int3’未定義的引用
fs/fs.o:在函數‘check_disk_change’中:
(.text+0x20ba):對‘invalidate_buffers’未定義的引用
kernel/chr_drv/chr_drv.a(console.o):在函數‘con_init’中:
console.c:(.text+0x3b02):對‘keyboard_interrupt’未定義的引用
kernel/chr_drv/chr_drv.a(serial.o):在函數‘rs_init’中:
serial.c:(.text+0xaa):對‘rs1_interrupt’未定義的引用
serial.c:(.text+0xda):對‘rs2_interrupt’未定義的引用
Makefile:58: recipe for target 'tools/system' failed
make: *** [tools/system] Error 1

buffer.c:
line84:void inline invalidate_buffers(int dev)去掉inline,變成
void invalidate_buffers(int dev)
我不知道原因,但這麼改就對了

注:讓終端錯誤提示變英文方法

如果希望終端顯示英文,可以設置系統變量

export LC_ALL=C
若希望恢復爲本地語言,則

unset LC_ALL

make---錯誤12:

init/main.o:在函數‘init’中:
main.c:(.text+0x27b):對‘puts’未定義的引用

還沒找到原因,我在main.c裏定義了一個void puts(){}空函數;

make---錯誤13:

gcc -m32  -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector \
-o tools/build tools/build.c
In file included from tools/build.c:25:0:
/usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory
 #include <bits/libc-header-start.h>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Makefile:51: recipe for target 'tools/build' failed
make: *** [tools/build] Error 1

百度搜索答案:

可以嘗試輸入sudoapt-get install gcc-multilib即可,其實主要是gcc安裝環境沒有安裝完善。我在網上找了很多方式,沒想到是這個,記錄下。

make---錯誤14:

gcc -m32  -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector \
-o tools/build tools/build.c
tools/build.c: In function 'main':
tools/build.c:78:17: warning: implicit declaration of function 'MAJOR' [-Wimplicit-function-declaration]
    major_root = MAJOR(sb.st_rdev);
                 ^~~~~
tools/build.c:79:17: warning: implicit declaration of function 'MINOR'; did you mean '_IOR'? [-Wimplicit-function-declaration]
    minor_root = MINOR(sb.st_rdev);
                 ^~~~~
                 _IOR
/tmp/ccsWmdx0.o: In function `main':
build.c:(.text+0xed): undefined reference to `MAJOR'
build.c:(.text+0x107): undefined reference to `MINOR'
build.c:(.text+0x1a5): undefined reference to `MAJOR'
build.c:(.text+0x1bf): undefined reference to `MINOR'
collect2: error: ld returned 1 exit status
Makefile:51: recipe for target 'tools/build' failed
make: *** [tools/build] Error 1

build.c中包含的是標準庫的頭文件 /usr/include/linux/fs.h ,但是這個頭文件裏並沒有實現MAJOR和MINOR宏。解決方法很簡單,從include/linux/fs.h中把這兩個宏複製到build.c中即可:

#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)

make---錯誤15:

gcc -m32  -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector \
-o tools/build tools/build.c
tools/build boot/bootsect boot/setup tools/system /dev/hd6 \
	/dev/hd2 > Image
/dev/hd6: No such file or directory
Couldn't stat root device.
Makefile:43: recipe for target 'Image' failed
make: *** [Image] Error 1

這段報錯的代碼在build.c的line79處,可以自行閱讀理解。

ROOT_DEV=etc/hd6
SWAP_DEV=etc/hd2

修改爲

ROOT_DEV=
SWAP_DEV=
或
ROOT_DEV= FLOPPY
SWAP_DEV=

make---錯誤16:

gcc -m32  -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector \
-o tools/build tools/build.c
tools/build boot/bootsect boot/setup tools/system  \
	 > Image
Root device is (3, 6)
Swap device is (0, 0)
Boot sector 512 bytes.
Setup is 1372 bytes.
Non-GCC header of 'system'
Makefile:43: recipe for target 'Image' failed
make: *** [Image] Error 1

把build.c中的

if (((long *) buf)[5] != 0)
	die("Non-GCC header of 'system'");
	---------------------
if (i > SYS_SIZE*16)
	die("System is too big");

註釋掉

以上就是全部錯誤,然後編譯成功。但是這個系統應該是不能用的。因爲最後的軟盤設置等沒弄明白。但是編譯目標文件有了。我可以試試GBD調試了。花了兩三個星期=。=真的有點累啊。

以下附上參考鏈接:
https://www.cnblogs.com/welhzh/p/4521196.html
https://www.cnblogs.com/hummersofdie/p/3645218.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章