ICS PA0

目录

    • 环境配置
    • 工具的使用及相关资源
    • Compling and Running NEMU
      • 配置系统make menuconfig
      • 项目构建make
      • 运行与调试
    • Submit

环境配置

  • Ubuntu安装中的分区不太明白
  • 安装了中文输入法和必要的工具链
  • 虚拟机与主机互联

工具的使用及相关资源

  • vim(vimtutor是vim的一个内置教程)
    主要修改一下配置文件,先进行备份:

$ cp /etc/vim/vimrc ~/.vimrc

然后回到家目录:

$ vi .vimrc

添加如下内容:

set tabstop=4
set softtabstop =4
set cindent
set shiftwidth=4

可以参考讲义里的配置

  • make
    基本的操作如下:

$ vi hello.c
$ gcc hello.c -o hello
$ ./hello

在hello.c所在目录下新建一个文件Makefile,输入以下内容并保存:

hello:hello.c gcc hello.c -o hello # 注意开头的 tab,而不是空格


.PHONY: clean


clean: rm hello # 注意开头的 tab,而不是空格

返回命令行,键入 make,你会发现 make 程序调用了 gcc 进行编译。

若连续多次执行 make,会得到 make: ‘hello’ is up to date. 的提示信息。

其中 .PHONY: clean 这一行的作用是防止同目录下的 clean 文件影响 Makefile 的执行。

  • git
    The workflow above shows how you will use branch in PAs:
    1. before starting a new PA, new a branch pa? and check out to it
    2. coding in the branch pa? (this will introduce lot of modifications)
    3. after finish the PA, merge the branch pa? into master, and check out back to master

Compling and Running NEMU

在nemu/文件夹中,我们需要进行 NEMU 项目中的配置系统和项目构建(更多内容详见 PA1 RTFSC)。

配置系统make menuconfig

执行这一步前,需要先安装 bison 和 flex(根据报错提示安装即可)

NEMU 中的配置系统为于 nemu/tools/kconfig,它来源于 GNU / Linux 项目中的 kconfig。

kconfig 定义了一套简单的语言,开发者可以使用这套语言来编写“配置描述文件”。

在 NEMU 项目中,“配置描述文件”的文件名都为 Kconfig,如 nemu/Kconfig。

当键入 make menuconfig 的时候,背后其实发生了如下事件:

  • 检查 nemu/tools/kconfig/build/mconf 程序是否存在,若不存在,则编译并生成 mconf
  • 检查 nemu/tools/kconfig/build/conf 程序是否存在,若不存在,则编译并生成 conf
  • 运行命令 mconf nemu/Kconfig,此时 mconf 将会解析 nemu/Kconfig 中的描述,以菜单树的形式展示各种配置选项,供开发者进行选择
  • 退出菜单时,mconf 会把开发者选择的结果记录到 nemu/.config 文件中
  • 运行命令 conf --syncconfig nemu/Kconfig,此时 conf 将会解析 nemu/Kconfig 中的描述,并读取选择结果 nemu/.config,结合两者来生成如下文件:
    • 可以被包含到 C 代码中的宏定义 (nemu/include/generated/autoconf.h),这些宏的名称都是形如 CONFIG_xxx 的形式
    • 可以被包含到 Makefile 中的变量定义 (nemu/include/config/auto.conf)
    • ……
+ CC src/memory/paddr.c
+ CXX src/utils/disasm.cc
src/utils/disasm.cc:5:10: fatal error: llvm/Support/TargetRegistry.h: No such file or directory
    5 | #include "llvm/Support/TargetRegistry.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [/home/crx/ics2021/nemu/scripts/build.mk:40: /home/crx/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/disasm.o] Error 1

经过stackoverflow的启发Stackoverflow:llvm/Support/TargetRegistry.h: No such file or directory,知道了是编译(8月31号开始)src/utils/disasm.cc的时候,出现了文件引用失败。这时候用到了一个命令apt-file来寻找这个TargetRegistry.h文件。在这里简单介绍下apt-file 的作用 apt-file。

apt-file:apt-file is a command line tool for searching files in packages for the APT package management system。apt-file 是一个命令行界面的 APT 包搜索工具。当我们在编译源代码时,时有缺少文件的情况发生。此时,通过 apt-file 就可以找出该缺失文件所在的包,然后将缺失的包安装后即可让编译顺利进行了。所以当我们通过执行命令

apt-file search TargetRegistry.h

后,可以发现

ICS PA0_第1张图片
所以可以解决TargetRegistry.h文件缺失问题了:因为当前我们的llvm版本是14,TargetRegistry.h文件在/llvm/MC/下,而不是src/utils/disasm.cc文件的#include “llvm/Support/TargetRegistry.h”

项目构建make

liaobei@liaohaijin-vm:~/ics2021/nemu$ make
+ CC src/nemu-main.c
+ CC src/cpu/difftest/dut.c
+ CC src/cpu/cpu-exec.c
+ CC src/monitor/sdb/sdb.c
+ CC src/monitor/sdb/watchpoint.c
+ CC src/monitor/sdb/expr.c
+ CC src/monitor/monitor.c
+ CC src/utils/timer.c
+ CC src/utils/state.c
+ CC src/utils/log.c
+ CC src/utils/rand.c
+ CC src/memory/paddr.c
+ CC src/memory/vaddr.c
+ CC src/isa/riscv32/difftest/dut.c
+ CC src/isa/riscv32/reg.c
+ CC src/isa/riscv32/init.c
+ CC src/isa/riscv32/system/intr.c
+ CC src/isa/riscv32/system/mmu.c
+ CC src/isa/riscv32/instr/decode.c
+ CC src/isa/riscv32/logo.c
+ CC src/device/io/map.c
+ CC src/device/io/mmio.c
+ CC src/device/io/port-io.c
+ CC src/engine/interpreter/init.c
+ CC src/engine/interpreter/hostcall.c
+ CXX src/utils/disasm.cc
+ LD /home/liaobei/ics2021/nemu/build/riscv32-nemu-interpreter

下面是Makefile文件的内容,对其进行解读:

# Sanity check
ifeq ($(wildcard $(NEMU_HOME)/src/nemu-main.c),)
  $(error NEMU_HOME=$(NEMU_HOME) is not a NEMU repo)
endif

# Include variables and rules generated by menuconfig
-include $(NEMU_HOME)/include/config/auto.conf
-include $(NEMU_HOME)/include/config/auto.conf.cmd

remove_quote = $(patsubst "%",%,$(1))

# Extract variabls from menuconfig
GUEST_ISA ?= $(call remove_quote,$(CONFIG_ISA))
ENGINE ?= $(call remove_quote,$(CONFIG_ENGINE))
NAME    = $(GUEST_ISA)-nemu-$(ENGINE)

# Include all filelist.mk to merge file lists
FILELIST_MK = $(shell find ./src -name "filelist.mk")
include $(FILELIST_MK)

# Filter out directories and files in blacklist to obtain the final set of source files
DIRS-BLACKLIST-y += $(DIRS-BLACKLIST)
SRCS-BLACKLIST-y += $(SRCS-BLACKLIST) $(shell find $(DIRS-BLACKLIST-y) -name "*.c")
SRCS-y += $(shell find $(DIRS-y) -name "*.c")
SRCS = $(filter-out $(SRCS-BLACKLIST-y),$(SRCS-y))

# Extract compiler and options from menuconfig
CC = $(call remove_quote,$(CONFIG_CC))
CFLAGS_BUILD += $(call remove_quote,$(CONFIG_CC_OPT))
CFLAGS_BUILD += $(if $(CONFIG_CC_LTO),-flto,)
CFLAGS_BUILD += $(if $(CONFIG_CC_DEBUG),-ggdb3,)
CFLAGS_BUILD += $(if $(CONFIG_CC_ASAN),-fsanitize=address,)
CFLAGS_TRACE += -DITRACE_COND=$(if $(CONFIG_ITRACE_COND),$(call remove_quote,$(CONFIG_ITRACE_COND)),true)
CFLAGS  += $(CFLAGS_BUILD) $(CFLAGS_TRACE) -D__GUEST_ISA__=$(GUEST_ISA)
LDFLAGS += $(CFLAGS_BUILD)

# Include rules for menuconfig
include $(NEMU_HOME)/scripts/config.mk

ifdef CONFIG_TARGET_AM
include $(AM_HOME)/Makefile
LINKAGE += $(ARCHIVES)
else
# Include rules to build NEMU
include $(NEMU_HOME)/scripts/native.mk
endif
  • 与配置系统进行关联
    通过包含nemu/include/config/auto.conf,与kconfig生成的变量进行关联
-include $(NEMU_HOME)/include/config/auto.conf
  • 文件列表
    在nemu/src及其子目录下存在一些名为filelist.mk的文件:
liaobei@liaohaijin-vm:~/ics2021/nemu$ find ./ -name filelist.mk
./src/utils/filelist.mk
./src/filelist.mk
./src/isa/filelist.mk
./src/device/filelist.mk
./src/engine/filelist.mk

它们会根据menuconfig的配置对如下4个变量进行维护:

  • SRCS-y - 参与编译的源文件的候选集合
  • SRCS-BLACKLIST-y - 不参与编译的源文件的黑名单集合
  • DIRS-y -参与编译的目录集合, 该目录下的所有文件都会被加入到SRCS-y中
  • DIRS-BLACKLIST-y - 不参与编译的目录集合,该目录下的所有文件都会被加入到SRCS-BLACKLIST-y中
    Makefile中会包含项目中的所有filelist.mk文件,对上述4个变量的追加定义进行汇总,最终会过滤出在SRCS-y中但不在SRCS-BLACKLIST-y中的源文件,来作为最终参与编译的源文件的集合。
  • 编译和链接
    Makefile的编译规则在nemu/srcripts/build.mk中定义,见# Compilation patterns 后的部分:
.DEFAULT_GOAL = app

# Add necessary options if the target is a shared library
ifeq ($(SHARE),1)
SO = -so
CFLAGS  += -fPIC
LDFLAGS += -rdynamic -shared -fPIC
endif

WORK_DIR  = $(shell pwd)
BUILD_DIR = $(WORK_DIR)/build

INC_PATH := $(WORK_DIR)/include $(INC_PATH)
OBJ_DIR  = $(BUILD_DIR)/obj-$(NAME)$(SO)
BINARY   = $(BUILD_DIR)/$(NAME)$(SO)

# Compilation flags
ifeq ($(CC),clang)
CXX := clang++
else
CXX := g++
endif
LD := $(CXX)
INCLUDES = $(addprefix -I, $(INC_PATH))
CFLAGS  := -O2 -MMD -Wall -Werror $(INCLUDES) $(CFLAGS)
LDFLAGS := -O2 $(LDFLAGS)

OBJS = $(SRCS:%.c=$(OBJ_DIR)/%.o) $(CXXSRC:%.cc=$(OBJ_DIR)/%.o)

# Compilation patterns
$(OBJ_DIR)/%.o: %.c
	@echo + CC $<
	@mkdir -p $(dir $@)
	@$(CC) $(CFLAGS) -c -o $@ $<
	$(call call_fixdep, $(@:.o=.d), $@)

$(OBJ_DIR)/%.o: %.cc
	@echo + CXX $<
	@mkdir -p $(dir $@)
	@$(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
	$(call call_fixdep, $(@:.o=.d), $@)

# Depencies
-include $(OBJS:.o=.d)

# Some convenient rules

.PHONY: app clean

app: $(BINARY)

$(BINARY): $(OBJS) $(ARCHIVES)
	@echo + LD $@
	@$(LD) -o $@ $(OBJS) $(LDFLAGS) $(ARCHIVES) $(LIBS)

clean:
	-rm -rf $(BUILD_DIR)

$@表示所有参数列表,$<表示第一个依赖文件,call_fixdep的调用用于生成更合理的依赖关系(先忽略)。
可以通过输入make -nB让make程序以“只输出命令但不执行”的方式强制构建目标。
截取整理好的一段输出分析:

gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/nemu-main.o src/nemu-main.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/cpu/difftest/dut.o src/cpu/difftest/dut.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/cpu/cpu-exec.o src/cpu/cpu-exec.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/sdb.o src/monitor/sdb/sdb.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/watchpoint.o src/monitor/sdb/watchpoint.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/expr.o src/monitor/sdb/expr.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/monitor.o src/monitor/monitor.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/timer.o src/utils/timer.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/state.o src/utils/state.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/log.o src/utils/log.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/rand.o src/utils/rand.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/memory/paddr.o src/memory/paddr.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/memory/vaddr.o src/memory/vaddr.c
gcc -O2 -MMD -Wall -Werror -I/home/liaobei/ics2021/nemu/include -I/home/liaobei/ics2021/nemu/src/isa/riscv32/include -I/home/liaobei/ics2021/nemu/src/engine/interpreter -O2  -ggdb3  -DITRACE_COND=true -D__GUEST_ISA__=riscv32 -c -o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/difftest/dut.o src/isa/riscv32/difftest/dut.c

对比可知,我们可以知道,$<为src/nemu-main.c,$@为/home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/nemu-main.o,$(CC)为gcc等,这些Makefile中的变量,在/include/config/auto.conf定义了。

可以根据上述输出结果和 Makefile 反推 $(CFLAGS) 的值是如何形成的。

编译之后是一系列 git 操作,规则在 nemu/scripts/git.mk 中定义。下面是输出:

git add /home/liaobei/ics2021/nemu/.. -A --ignore-errors
while (test -e .git/index.lock); do sleep 0.1; done
sync


最后是链接操作:

g++ -o /home/liaobei/ics2021/nemu/build/riscv32-nemu-interpreter /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/nemu-main.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/cpu/difftest/dut.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/cpu/cpu-exec.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/sdb.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/watchpoint.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/sdb/expr.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/monitor/monitor.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/timer.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/state.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/log.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/rand.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/memory/paddr.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/memory/vaddr.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/difftest/dut.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/reg.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/init.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/system/intr.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/system/mmu.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/instr/decode.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/isa/riscv32/logo.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/device/io/map.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/device/io/mmio.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/device/io/port-io.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/engine/interpreter/init.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/engine/interpreter/hostcall.o /home/liaobei/ics2021/nemu/build/obj-riscv32-nemu-interpreter/src/utils/disasm.o -O2 -O2  -ggdb3   -lLLVM-14 -lreadline -ldl -pie

运行与调试

To run NEMU, type

make run

To debug NEMU with gdb, type

make gdb

Submit

需要有足够的耐心,对于不清楚的知识和看不懂的源码像Makefile的内容,不断进行RTFM和STFW,要有信心一定有工具能帮助我们更好的理解代码。

你可能感兴趣的:(计算机系统基础,ICS,PA0)