【问题标题】:Can't Link together GDT and the IDT无法将 GDT 和 IDT 链接在一起
【发布时间】:2015-12-01 13:46:07
【问题描述】:

我最近开始了 James Molly 的内核开发教程,并且已经实现了 GDT 和 IDT。

当我将高级函数与它们的低级汇编对应项链接在一起时,问题就出现了。

您可以在此处找到代码 Source on Github

这是目录结构

.
|-- arch
|-- boot
| |-- boot.s
| |-- buildboot.sh
| |-- gdt.s
| |-- idt.s
| `-- interrupt.s
|-- build
| |-- boot.s.o
| |-- gdt.o
| |-- gdt.s.o
| |-- idt.o
| |-- idt.s.o
| |-- interrupt.s.o
| |-- io.o
| |-- isr.o
| |-- main.o
| |-- memory.o
| |-- monitor.o
| `-- stdlib.o
|-- doc
| `-- Bug_Log.md
|-- include
| |-- gdt.cc
| |-- gdt.h
| |-- gdt.o
| |-- idt.cc
| |-- idt.h
| |-- idt.o
| |-- io.cc
| |-- io.h
| |-- io.o
| |-- isr.cc
| |-- isr.h
| |-- isr.o
| |-- memory.cc
| |-- memory.h
| |-- memory.o
| |-- monitor.cc
| |-- monitor.h
| |-- monitor.o
| |-- SConstruct
| |-- stdlib.cc
| |-- stdlib.h
| |-- stdlib.o
| `-- system.h
|-- JOSMake.sh
|-- link.ld
|-- main.cc
`-- ReadMe.md

这是 Bash 脚本 JOSmake.sh

    #
# Build File for JOS
#
# To Build
#     bash build.sh
# To Run
#   bash run.sh

# ----------------------------------------------------------------------------------------------
# JOS uses assembly to build the bootsector
# Compile the boot Sectors in boot
echo "==============================================="
echo "-------- Building Boot Sectors ----------------"
cd boot
# Run the Make Script inside the boot directory
bash buildboot.sh
cd ..
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
# Compile the C++ Sources into Respective Objects
# Compile main.cc
echo "==============================================="
echo "--------- Compiling C++ Sources --------------"
g++ -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -o main.o main.cc
mv main.o build
# Run scons to build the Entire Lbrary of C++ Files
cd include
rm *.o
scons
# Move all Object Files into Build Directory
cp *.o ../build
cd ..
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
## When Everything is Finished Link together the Objects into a Kernel File
echo "==============================================="
echo "--------- Linking ----------------"
cd build
# require ld , link.ld
ld  -T '../link.ld' -m elf_i386 -o  kernel.jos *.o
# Clean Up After Build
#rm *.o
echo "==============================================="
# ----------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------
## When Everything is Finished Run the Kernel
qemu-system-i386 -kernel kernel.jos
# -----------------------------------------------------------------------------------------

这里是 buildboot.sh

    # Builds the Boot files for JOS
# require 'nasm'

# Add all the Assembly Files Here
nasm -f elf -o boot.s.o boot.s
nasm -f elf -o gdt.s.o gdt.s
nasm -f elf -o idt.s.o idt.s
nasm -f elf -o interrupt.s.o interrupt.s

# Move the Entire Object Files into the Build Directory
mv *.o ../build

这是我运行脚本时的终端输出

    ===============================================
-------- Building Boot Sectors ----------------
===============================================
===============================================
--------- Compiling C++ Sources --------------
In file included from include/system.h:22:0,
                 from main.cc:6:
include/idt.h:34:13: warning: ‘void init_idt()’ used but never defined
static void init_idt();
             ^
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o gdt.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 gdt.cc
g++ -o idt.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 idt.cc
g++ -o io.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 io.cc
g++ -o isr.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 isr.cc
g++ -o memory.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 memory.cc
g++ -o monitor.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 monitor.cc
g++ -o stdlib.o -c -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 stdlib.cc
scons: done building targets.
===============================================
===============================================
--------- Linking ----------------
gdt.o: In function `init_gdt()':
gdt.cc:(.text+0xb0): undefined reference to `gdt_flush(unsigned int)'
idt.o: In function `init_idt()':
idt.cc:(.text+0x3a): undefined reference to `isr0()'
idt.cc:(.text+0x51): undefined reference to `isr1()'
idt.cc:(.text+0x68): undefined reference to `isr2()'
idt.cc:(.text+0x7f): undefined reference to `isr3()'
idt.cc:(.text+0x96): undefined reference to `isr4()'
idt.cc:(.text+0xad): undefined reference to `isr5()'
idt.cc:(.text+0xc4): undefined reference to `isr6()'
idt.cc:(.text+0xdb): undefined reference to `isr7()'
idt.cc:(.text+0xf2): undefined reference to `isr8()'
idt.cc:(.text+0x109): undefined reference to `isr9()'
idt.cc:(.text+0x120): undefined reference to `isr10()'
idt.cc:(.text+0x137): undefined reference to `isr11()'
idt.cc:(.text+0x14e): undefined reference to `isr12()'
idt.cc:(.text+0x165): undefined reference to `isr13()'
idt.cc:(.text+0x17c): undefined reference to `isr14()'
idt.cc:(.text+0x193): undefined reference to `isr15()'
idt.cc:(.text+0x1aa): undefined reference to `isr16()'
idt.cc:(.text+0x1c1): undefined reference to `isr17()'
idt.cc:(.text+0x1d8): undefined reference to `isr18()'
idt.cc:(.text+0x1ef): undefined reference to `isr19()'
idt.cc:(.text+0x206): undefined reference to `isr20()'
idt.cc:(.text+0x21d): undefined reference to `isr21()'
idt.cc:(.text+0x234): undefined reference to `isr22()'
idt.cc:(.text+0x24b): undefined reference to `isr23()'
idt.cc:(.text+0x262): undefined reference to `isr24()'
idt.cc:(.text+0x279): undefined reference to `isr25()'
idt.cc:(.text+0x290): undefined reference to `isr26()'
idt.cc:(.text+0x2a7): undefined reference to `isr27()'
idt.cc:(.text+0x2be): undefined reference to `isr28()'
idt.cc:(.text+0x2d5): undefined reference to `isr29()'
idt.cc:(.text+0x2ec): undefined reference to `isr30()'
idt.cc:(.text+0x303): undefined reference to `isr31()'
idt.cc:(.text+0x323): undefined reference to `idt_flush(unsigned int)'
interrupt.s.o: In function `isr_common_stub':
interrupt.s:(.text+0x10d): undefined reference to `isr_handler'
main.o: In function `main':
main.cc:(.text+0x17): undefined reference to `init_idt()'
===============================================
qemu: could not load kernel 'kernel.jos': No such file or directory

谁能指出我做错了什么

【问题讨论】:

    标签: operating-system osdev


    【解决方案1】:

    这看起来像是 name mangling 问题。

    您所遵循的指南是用 C 编写的,如果使用 GCC 而不是 G++ 编译,您的 IDT 代码可能可以工作。但是,如果您选择使用 C++,则需要进行一些更改以允许从 C++ 引用汇编程序函数,反之亦然。

    C 和汇编程序中的函数名称直接映射到符号名称,但 C++ 默认情况下会在符号名称中添加一些额外的文本,以包含有关类、命名空间、重载等的信息。

    为确保您的 C++ 代码可以使用正确的符号名称引用汇编器函数,您必须告诉编译器对这些函数使用 C 链接。

    在 C++ 头文件中查找声明在汇编程序中实现的函数的位置,例如:idt.hh 中的 isrN() 函数 .

    将这些声明包装在 C 链接块中,如下所示:

    extern "C" {
    
    extern int isr0();
    extern int isr1();
    // ... and so on for all your ASM functions.
    
    }
    

    对应该可以从汇编器调用的 C++ 函数也这样做。

    【讨论】:

    • 感谢您解决了这个问题,我认为 c 和 c++ 完全不同,但这是我最不希望它完全不同的地方。
    猜你喜欢
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 2022-10-17
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多