Lab_1:練習1——理解經過make生成執行文件的過程

 參考網站:html

https://www.cnblogs.com/chaunceyctx/p/7188779.htmllinux

https://cloud.tencent.com/developer/article/1415004shell

https://www.runoob.com/linux/linux-comm-dd.html緩存

https://www.jianshu.com/p/49c6433fd6d2ide

https://www.cnblogs.com/cyx-b/p/11750020.html工具

 

練習1:理解經過make生成執行文件的過程。(要求在報告中寫出對下述問題的回答)優化

列出本實驗各練習中對應的OS原理的知識點,並說明本實驗中的實現部分如何對應和體現了原理中的基本概念和關鍵知識點。網站

在此練習中,你們須要經過靜態分析代碼來了解:ui

  1. 操做系統鏡像文件ucore.img是如何一步一步生成的?(須要比較詳細地解釋Makefile中每一條相關命令和命令參數的含義,以及說明命令致使的結果)
  2. 一個被系統認爲是符合規範的硬盤主引導扇區的特徵是什麼

1、操做步驟this

一、進入/moocos/ucore_lab/labcodes_answer/lab1_result目錄

cd ./moocos/ucore_lab/labcodes_answer/lab1_result

二、執行make qemu

 

 

Ctrl+C退出

三、make clean

 

清除上次的make命令所產生的object文件(後綴爲「.o」的文件)及可執行文件

 

四、查看Makefile

cat Makefile

  1 PROJ    := challenge
  2 EMPTY    :=
  3 SPACE    := $(EMPTY) $(EMPTY)
  4 SLASH    := /
  5 
  6 V       := @
  7 #need llvm/cang-3.5+
  8 #USELLVM := 1
  9 # try to infer the correct GCCPREFX
 10 ifndef GCCPREFIX
 11 GCCPREFIX := $(shell if i386-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
 12     then echo 'i386-elf-'; \
 13     elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
 14     then echo ''; \
 15     else echo "***" 1>&2; \
 16     echo "*** Error: Couldn't find an i386-elf version of GCC/binutils." 1>&2; \
 17     echo "*** Is the directory with i386-elf-gcc in your PATH?" 1>&2; \
 18     echo "*** If your i386-elf toolchain is installed with a command" 1>&2; \
 19     echo "*** prefix other than 'i386-elf-', set your GCCPREFIX" 1>&2; \
 20     echo "*** environment variable to that prefix and run 'make' again." 1>&2; \
 21     echo "*** To turn off this error, run 'gmake GCCPREFIX= ...'." 1>&2; \
 22     echo "***" 1>&2; exit 1; fi)
 23 endif
 24 
 25 # try to infer the correct QEMU
 26 ifndef QEMU
 27 QEMU := $(shell if which qemu-system-i386 > /dev/null; \
 28     then echo 'qemu-system-i386'; exit; \
 29     elif which i386-elf-qemu > /dev/null; \
 30     then echo 'i386-elf-qemu'; exit; \
 31     elif which qemu > /dev/null; \
 32     then echo 'qemu'; exit; \
 33     else \
 34     echo "***" 1>&2; \
 35     echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \
 36     echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \
 37     echo "***" 1>&2; exit 1; fi)
 38 endif
 39 
 40 # eliminate default suffix rules
 41 .SUFFIXES: .c .S .h
 42 
 43 # delete target files if there is an error (or make is interrupted)
 44 .DELETE_ON_ERROR:
 45 
 46 # define compiler and flags
 47 ifndef  USELLVM
 48 HOSTCC        := gcc
 49 HOSTCFLAGS    := -g -Wall -O2
 50 CC        := $(GCCPREFIX)gcc
 51 CFLAGS    := -march=i686 -fno-builtin -fno-PIC -Wall -ggdb -m32 -gstabs -nostdinc $(DEFS)
 52 CFLAGS    += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
 53 else
 54 HOSTCC        := clang
 55 HOSTCFLAGS    := -g -Wall -O2
 56 CC        := clang
 57 CFLAGS    := -march=i686 -fno-builtin -fno-PIC -Wall -g -m32 -nostdinc $(DEFS)
 58 CFLAGS    += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
 59 endif
 60 
 61 CTYPE    := c S
 62 
 63 LD      := $(GCCPREFIX)ld
 64 LDFLAGS    := -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1)
 65 LDFLAGS    += -nostdlib
 66 
 67 OBJCOPY := $(GCCPREFIX)objcopy
 68 OBJDUMP := $(GCCPREFIX)objdump
 69 
 70 COPY    := cp
 71 MKDIR   := mkdir -p
 72 MV        := mv
 73 RM        := rm -f
 74 AWK        := awk
 75 SED        := sed
 76 SH        := sh
 77 TR        := tr
 78 TOUCH    := touch -c
 79 
 80 OBJDIR    := obj
 81 BINDIR    := bin
 82 
 83 ALLOBJS    :=
 84 ALLDEPS    :=
 85 TARGETS    :=
 86 
 87 include tools/function.mk
 88 
 89 listf_cc = $(call listf,$(1),$(CTYPE))
 90 
 91 # for cc
 92 add_files_cc = $(call add_files,$(1),$(CC),$(CFLAGS) $(3),$(2),$(4))
 93 create_target_cc = $(call create_target,$(1),$(2),$(3),$(CC),$(CFLAGS))
 94 
 95 # for hostcc
 96 add_files_host = $(call add_files,$(1),$(HOSTCC),$(HOSTCFLAGS),$(2),$(3))
 97 create_target_host = $(call create_target,$(1),$(2),$(3),$(HOSTCC),$(HOSTCFLAGS))
 98 
 99 cgtype = $(patsubst %.$(2),%.$(3),$(1))
100 objfile = $(call toobj,$(1))
101 asmfile = $(call cgtype,$(call toobj,$(1)),o,asm)
102 outfile = $(call cgtype,$(call toobj,$(1)),o,out)
103 symfile = $(call cgtype,$(call toobj,$(1)),o,sym)
104 
105 # for match pattern
106 match = $(shell echo $(2) | $(AWK) '{for(i=1;i<=NF;i++){if(match("$(1)","^"$$(i)"$$")){exit 1;}}}'; echo $$?)
107 
108 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
109 # include kernel/user
110 
111 INCLUDE    += libs/
112 
113 CFLAGS    += $(addprefix -I,$(INCLUDE))
114 
115 LIBDIR    += libs
116 
117 $(call add_files_cc,$(call listf_cc,$(LIBDIR)),libs,)
118 
119 # -------------------------------------------------------------------
120 # kernel
121 
122 KINCLUDE    += kern/debug/ \
123                kern/driver/ \
124                kern/trap/ \
125                kern/mm/
126 
127 KSRCDIR        += kern/init \
128                kern/libs \
129                kern/debug \
130                kern/driver \
131                kern/trap \
132                kern/mm
133 
134 KCFLAGS        += $(addprefix -I,$(KINCLUDE))
135 
136 $(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
137 
138 KOBJS    = $(call read_packet,kernel libs)
139 
140 # create kernel target
141 kernel = $(call totarget,kernel)
142 
143 $(kernel): tools/kernel.ld
144 
145 $(kernel): $(KOBJS)
146     @echo + ld $@
147     $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
148     @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
149     @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)
150 
151 $(call create_target,kernel)
152 
153 # -------------------------------------------------------------------
154 
155 # create bootblock
156 bootfiles = $(call listf_cc,boot)
157 $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))
158 
159 bootblock = $(call totarget,bootblock)
160 
161 $(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
162     @echo + ld $@
163     $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
164     @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
165     @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
166     @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)
167 
168 $(call create_target,bootblock)
169 
170 # -------------------------------------------------------------------
171 
172 # create 'sign' tools
173 $(call add_files_host,tools/sign.c,sign,sign)
174 $(call create_target_host,sign,sign)
175 
176 # -------------------------------------------------------------------
177 
178 # create ucore.img
179 UCOREIMG    := $(call totarget,ucore.img)
180 
181 $(UCOREIMG): $(kernel) $(bootblock)
182     $(V)dd if=/dev/zero of=$@ count=10000
183     $(V)dd if=$(bootblock) of=$@ conv=notrunc
184     $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
185 
186 $(call create_target,ucore.img)
187 
188 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
189 
190 $(call finish_all)
191 
192 IGNORE_ALLDEPS    = clean \
193                   dist-clean \
194                   grade \
195                   touch \
196                   print-.+ \
197                   handin
198 
199 ifeq ($(call match,$(MAKECMDGOALS),$(IGNORE_ALLDEPS)),0)
200 -include $(ALLDEPS)
201 endif
202 
203 # files for grade script
204 
205 TARGETS: $(TARGETS)
206 
207 .DEFAULT_GOAL := TARGETS
208 
209 .PHONY: qemu qemu-nox debug debug-nox
210 qemu-mon: $(UCOREIMG)
211     $(V)$(QEMU)  -no-reboot -monitor stdio -hda $< -serial null
212 qemu: $(UCOREIMG)
213     $(V)$(QEMU) -no-reboot -parallel stdio -hda $< -serial null
214 log: $(UCOREIMG)
215     $(V)$(QEMU) -no-reboot -d int,cpu_reset  -D q.log -parallel stdio -hda $< -serial null
216 qemu-nox: $(UCOREIMG)
217     $(V)$(QEMU)   -no-reboot -serial mon:stdio -hda $< -nographic
218 TERMINAL        :=gnome-terminal
219 debug: $(UCOREIMG)
220     $(V)$(QEMU) -S -s -parallel stdio -hda $< -serial null &
221     $(V)sleep 2
222     $(V)$(TERMINAL) -e "gdb -q -tui -x tools/gdbinit"
223     
224 debug-nox: $(UCOREIMG)
225     $(V)$(QEMU) -S -s -serial mon:stdio -hda $< -nographic &
226     $(V)sleep 2
227     $(V)$(TERMINAL) -e "gdb -q -x tools/gdbinit"
228 
229 .PHONY: grade touch
230 
231 GRADE_GDB_IN    := .gdb.in
232 GRADE_QEMU_OUT    := .qemu.out
233 HANDIN            := proj$(PROJ)-handin.tar.gz
234 
235 TOUCH_FILES        := kern/trap/trap.c
236 
237 MAKEOPTS        := --quiet --no-print-directory
238 
239 grade:
240     $(V)$(MAKE) $(MAKEOPTS) clean
241     $(V)$(SH) tools/grade.sh
242 
243 touch:
244     $(V)$(foreach f,$(TOUCH_FILES),$(TOUCH) $(f))
245 
246 print-%:
247     @echo $($(shell echo $(patsubst print-%,%,$@) | $(TR) [a-z] [A-Z]))
248 
249 .PHONY: clean dist-clean handin packall tags
250 clean:
251     $(V)$(RM) $(GRADE_GDB_IN) $(GRADE_QEMU_OUT) cscope* tags
252     -$(RM) -r $(OBJDIR) $(BINDIR)
253 
254 dist-clean: clean
255     -$(RM) $(HANDIN)
256 
257 handin: packall
258     @echo Please visit http://learn.tsinghua.edu.cn and upload $(HANDIN). Thanks!
259 
260 packall: clean
261     @$(RM) -f $(HANDIN)
262     @tar -czf $(HANDIN) `find . -type f -o -type d | grep -v '^\.*$$' | grep -vF '$(HANDIN)'`
263 
264 tags:
265     @echo TAGS ALL
266     $(V)rm -f cscope.files cscope.in.out cscope.out cscope.po.out tags
267     $(V)find . -type f -name "*.[chS]" >cscope.files
268     $(V)cscope -bq 
269     $(V)ctags -L cscope.files
Makefile文件的內容

 

五、輸入make V=

 查看make執行的命令

 1 moocos-> make V=
 2 + cc kern/init/init.c
 3 gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
 4 + cc kern/libs/readline.c
 5 gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
 6 + cc kern/libs/stdio.c
 7 gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
 8 + cc kern/debug/kdebug.c
 9 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
10 + cc kern/debug/kmonitor.c
11 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
12 + cc kern/debug/panic.c
13 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
14 + cc kern/driver/clock.c
15 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
16 + cc kern/driver/console.c
17 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
18 + cc kern/driver/intr.c
19 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
20 + cc kern/driver/picirq.c
21 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
22 + cc kern/trap/trap.c
23 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
24 + cc kern/trap/trapentry.S
25 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
26 + cc kern/trap/vectors.S
27 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
28 + cc kern/mm/pmm.c
29 gcc -Ikern/mm/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
30 + cc libs/printfmt.c
31 gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o
32 + cc libs/string.c
33 gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o
34 + ld bin/kernel
35 ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o  obj/libs/printfmt.o obj/libs/string.o
36 + cc boot/bootasm.S
37 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
38 + cc boot/bootmain.c
39 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
40 + cc tools/sign.c
41 gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
42 gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign
43 + ld bin/bootblock
44 ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
45 'obj/bootblock.out' size: 488 bytes
46 build 512 bytes boot sector: 'bin/bootblock' success!
47 dd if=/dev/zero of=bin/ucore.img count=10000
48 10000+0 records in
49 10000+0 records out
50 5120000 bytes (5.1 MB) copied, 0.0601803 s, 85.1 MB/s
51 dd if=bin/bootblock of=bin/ucore.img conv=notrunc
52 1+0 records in
53 1+0 records out
54 512 bytes (512 B) copied, 0.000141238 s, 3.6 MB/s
55 dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
56 146+1 records in
57 146+1 records out
58 74923 bytes (75 kB) copied, 0.00356787 s, 21.0 MB/s

 

2、問題一的解答

問題:操做系統鏡像文件ucore.img是如何一步一步生成的?(須要比較詳細地解釋Makefile中每一條相關命令和命令參數的含義,以及說明命令致使的結果)

答:

(1)make V=

一、整體概述

首先把C的源代碼編譯爲目標文件(.o文件)

比方說下面這樣:

 

1 + cc kern/init/init.c
2 gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
3 + cc kern/libs/readline.c
4 gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o

 


 

②ld命令將這些目標文件轉變成可執行文件

好比像下面這樣的: 

1 + ld bin/kernel
2 ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o  obj/libs/printfmt.o obj/libs/string.o

 


 

③dd命令把bootloader放到ucore.img.count的虛擬硬盤中

 

 1 dd if=/dev/zero of=bin/ucore.img count=10000
 2 10000+0 records in
 3 10000+0 records out
 4 5120000 bytes (5.1 MB) copied, 0.0601803 s, 85.1 MB/s
 5 dd if=bin/bootblock of=bin/ucore.img conv=notrunc
 6 1+0 records in
 7 1+0 records out
 8 512 bytes (512 B) copied, 0.000141238 s, 3.6 MB/s
 9 dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
10 146+1 records in
11 146+1 records out
12 74923 bytes (75 kB) copied, 0.00356787 s, 21.0 MB/s

 

 

還生成了兩個軟件,一個是bootloader,另外一個是kernel

 

二、具體分析

 

須要生成ucore.img首先須要生成bootblock,

 

而生成bootblock須要先生成bootmain.o和bootasm.o還有sign


 

 

說明:
ld:ld命令是二進制工具集GNU Binutils的一員,是GNU連接器,用於將目標文件與庫連接爲可執行程序或庫文件
dd:用指定大小的塊拷貝一個文件,並在拷貝的同時進行指定的轉換。
-b <input-format>:指定目標代碼輸入文件的格式
-Bstatic:只使用靜態庫
-Bdynamic:只使用動態庫
-Bsymbolic:把引用捆綁到共享庫中的全局符號
-c <MRI-commandfile>,--mri-script=<MRI-commandfile>:爲與MRI連接器兼容,ld接受由MRI命令語言編寫的腳本文件
--cref:建立跨引用表
-d,-dc,-dp:即便指定了可重定位的輸出文件(使用-r),也會爲公共符號分配空間。腳本命令「FORCE_COMMON_ALLOCATION」具備相同的效果
-defsym:在輸出文件中建立指定的全局符號
-demangle:在錯誤消息中還原符號名稱
-e <entry>:使用指定的符號做爲程序的初始執行點
-E,--export-dynamic:對於ELF格式文件,建立動態連接的可執行文件時,把全部符號添加到動態符號表
-f <name>,--auxiliary=<name>:對於ELF格式共享對象,設置 DT_AUXILIARY 名稱
-F <name>,--filter=<name>:對於ELF格式共享對象,設置 DT_FILTER 名稱。這告訴動態連接器,正在建立的共享對象的符號表應該用做共享對象名稱的符號表的篩選器。
-g:被忽略。用於提供和其餘工具的兼容性
-h:對於ELF格式共享對象,設置 DT_SONAME 名稱
-I<file>,--dynamic-linker=<file>:指定動態連接器。這僅在生成動態連接的ELF可執行文件時纔有意義。默認的動態連接器一般是正確的,除非您知道正在作什麼,不然不要使用該選項。
-l <namespec>,--library=<namespec>:把指定的庫文件添加到要連接的文件清單
-L <searchdir>,--library-path=searchdir:把指定的路徑添加添加到搜索庫的目錄清單
-M,--print-map:顯示連接映射,用於診斷目的
-Map=<mapfile>:    將連接映射輸出到指定的文件
-m <emulation>:    模擬指定的連接器
-N,--omagic:    指定讀取/寫入文本和數據段
-n,--nmagic:    關閉節的頁面對齊,並禁用對共享庫的連接。若是輸出格式支持Unix樣式的幻數,則將輸出標記爲"NMAGIC"
-noinhibit-exec:生成輸出文件,即便出現非致命連接錯誤。一般,若是連接器在連接過程當中遇到錯誤,它將不會生成輸出文件。
-no-keep-memory:ld一般在內存中緩存輸入文件的符號表來優化內存使用速度。此選項告訴ld不要緩存符號表。當連接大型可執行文件時,若是ld耗盡內存空間,則可能須要使用該選項
-O <level>:對於非零的優化等級,ld將優化輸出。此操做會比較耗時,應該在生成最終的結果時使用。
-o <output>,--output=<output>:指定輸出文件的名稱
-oformat=<output-format>:指定輸出文件的二進制格式
-R <filename>,--just-symbols=<filename>:從指定的文件讀取符號名稱和地址
-r,--relocatable:生成可重定位的輸出(稱爲部分鏈接)
-rpath=<dir>:把指定的目錄添加到運行時庫搜索路徑
-rpath-link=<dir>:指定搜索運行時共享庫的目錄
-S,--strip-debug:忽略來自輸出文件的調試器符號信息
-s,--strip-all:忽略來自輸出文件的全部符號信息
-shared,-Bshareable:建立共享庫
-split-by-file[=size]:爲每一個目標文件在輸出文件中建立額外的段大小達到size。size默認爲1
-split-by-reloc[=count]:按照指定的長度在輸出文件中建立額外的段
--section-start=<sectionname>=<org>:在輸出文件中指定的地址定位指定的段
-T <scriptfile>,--script=<scriptfile>:使用scriptfile做爲連接器腳本。此腳本將替換ld的默認連接器腳本(而不是添加到其中),所以腳本必須指定輸出文件所需的全部內容。若是當前目錄中不存在腳本文件,「ld」會在-L選項指定的目錄中查找
-Ttext=<org>:使用指定的地址做爲文本段的起始點
-Tdata=<org>:使用指定的地址做爲數據段的起始點
-Tbss=<org>:使用指定的地址做爲bss段的起始點
-t,--trace:在處理輸入文件時顯示它們的名稱
-u <symbol>,--undefined=<symbol>:強制指定符號在輸出文件中做爲未定義符號
-v,-V,--version:顯示ld版本號
-warn-common:當一個通用符號和另外一個通用符號結合時發出警告
-warn-constructors:若是沒有使用任何全局構造器,則發出警告
-warn-once:對於每一個未定義的符號只發出一次警告
-warn-section-align:若是爲了對齊而改動了輸出段地址,則發出警告
--whole-archive:對於指定的存檔文件,在存檔中包含全部文件
-X,--discard-locals:刪除全部本地臨時符號
-x,--discard-al:刪除全部本地符號
ld命令用法
Linux dd命令用於讀取、轉換並輸出數據。
dd可從標準輸入或文件中讀取數據,根據指定的格式來轉換數據,再輸出到文件、設備或標準輸出。
參數說明:
if=文件名:輸入文件名,默認爲標準輸入。即指定源文件。 
of=文件名:輸出文件名,默認爲標準輸出。即指定目的文件。 
ibs=bytes:一次讀入bytes個字節,即指定一個塊大小爲bytes個字節。
obs=bytes:一次輸出bytes個字節,即指定一個塊大小爲bytes個字節。
bs=bytes:同時設置讀入/輸出的塊大小爲bytes個字節。
cbs=bytes:一次轉換bytes個字節,即指定轉換緩衝區大小。 
skip=blocks:從輸入文件開頭跳過blocks個塊後再開始複製。 
seek=blocks:從輸出文件開頭跳過blocks個塊後再開始複製。 
count=blocks:僅拷貝blocks個塊,塊大小等於ibs指定的字節數。 
conv=<關鍵字>,關鍵字能夠有如下11種: 
conversion:用指定的參數轉換文件。
ascii:轉換ebcdic爲ascii
ebcdic:轉換ascii爲ebcdic
ibm:轉換ascii爲alternate ebcdic
block:把每一行轉換爲長度爲cbs,不足部分用空格填充
unblock:使每一行的長度都爲cbs,不足部分用空格填充
lcase:把大寫字符轉換爲小寫字符
ucase:把小寫字符轉換爲大寫字符
swab:交換輸入的每對字節
noerror:出錯時不中止
notrunc:不截短輸出文件
sync:將每一個輸入塊填充到ibs個字節,不足部分用空(NUL)字符補齊。
--help:顯示幫助信息
--version:顯示版本信息
dd命令用法

 

  

 

1 + ld bin/kernel
2 ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o  obj/libs/printfmt.o obj/libs/string.o

 

ld將.o文件整合成可執行文件kernel,而這些.o文件是Makefile文件經過命令使用gcc把有關kernel的.c文件編譯生成


 

1 + ld bin/bootblock
2 ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
3 'obj/bootblock.out' size: 488 bytes
4 build 512 bytes boot sector: 'bin/bootblock' success!

同理ld也將.o文件整合成可執行文件bootblock,大小爲488字節,但仍是放入512字節扇區中,可是,而這些.o文件也是Makefile文件經過命令使用gcc把有關bootloader的.c文件編譯生成


 

1  dd if=/dev/zero of=bin/ucore.img count=10000
2 10000+0 records in
3 10000+0 records out
4 5120000 bytes (5.1 MB) copied, 0.0601803 s, 85.1 MB/s

建立10000塊扇區,每一個扇區512字節,製成ucore.img虛擬磁盤


 

 

1 dd if=bin/bootblock of=bin/ucore.img conv=notrunc
2 1+0 records in
3 1+0 records out
4 512 bytes (512 B) copied, 0.000141238 s, 3.6 MB/s

將bootblock存到ucore.img虛擬磁盤的第一塊


 

 

1 dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
2 146+1 records in
3 146+1 records out
4 74923 bytes (75 kB) copied, 0.00356787 s, 21.0 MB/s

將kernel存到ucore.img虛擬磁盤的第二塊及以後幾塊,注意seek1,最終ucore.img虛擬磁盤製做完成


 

(2)Makefile

 Makefile文件中,能夠看到對應的生成ucore.img的過程及相應語句以下:

注:Makefile文件在~/moocos/ucore_lab/labcodes_answer/lab1_result中

  打開方式爲cat Makefile等

  Makefile中的M必定要大寫

Makefile中生成ucore.img的代碼爲

1 # create ucore.img
2 UCOREIMG    := $(call totarget,ucore.img)
3 
4 $(UCOREIMG): $(kernel) $(bootblock)
5     $(V)dd if=/dev/zero of=$@ count=10000
6     $(V)dd if=$(bootblock) of=$@ conv=notrunc
7     $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
8 
9 $(call create_target,ucore.img)

逐條分析:

$(kernel):生成kernel。須要如下兩步

  編譯kern/目錄下的C程序,生成kernel須要的.o文件

 

    $(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS)) 

  實際執行的命令爲:

 

 1 + cc kern/init/init.c
 2 gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
 3 + cc kern/libs/stdio.c
 4 gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
 5 + cc kern/libs/readline.c
 6 gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
 7 + cc kern/debug/panic.c
 8 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
 9 + cc kern/debug/kdebug.c
10 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
11 + cc kern/debug/kmonitor.c
12 gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
13 + cc kern/driver/clock.c
14 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
15 + cc kern/driver/console.c
16 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
17 + cc kern/driver/picirq.c
18 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
19 + cc kern/driver/intr.c
20 gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
21 + cc kern/trap/trap.c
22 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
23 + cc kern/trap/vectors.S
24 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
25 + cc kern/trap/trapentry.S
26 gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
27 + cc kern/mm/pmm.c
28 gcc -Ikern/mm/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
29 + cc libs/string.c
30 gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o
31 + cc libs/printfmt.c
32 gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o

   連接這些.o文件,生成kernel

 

 1 # create kernel target
 2 kernel = $(call totarget,kernel)
 3 
 4 $(kernel): tools/kernel.ld
 5 
 6 $(kernel): $(KOBJS)
 7     @echo + ld $@
 8     $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
 9     @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
10     @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)
11 
12 $(call create_target,kernel)

  執行的實際命令爲:

1 + ld bin/kernel
2 ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o  obj/libs/string.o obj/libs/printfmt.o

$(bootblock)生成binblock。須要如下三步:

  生成bootmain.o和bootasm.o

 1 bootfiles = $(call listf_cc,boot) 2 $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc)) 

  執行的實際命令爲

 

1 + cc boot/bootasm.S
2 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o         obj/boot/bootasm.o
3 + cc boot/bootmain.c
4 gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o

 

  編譯tools/sign.c,生成sign.o

# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign)

  執行的實際命令爲

 

+ cc tools/sign.c
gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign

  連接以上的.o文件

bootblock = $(call totarget,bootblock)

$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
    @echo + ld $@
    $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
    @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
    @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
    @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

$(call create_target,bootblock)

  執行的實際命令爲

+ ld bin/bootblock
ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o

$(V)dd if=/dev/zero of=$@ count=10000:生成一個有10000個塊的文件,每一個塊默認512字節,用0填充。

  執行的實際命令爲

 

dd if=/dev/zero of=bin/ucore.img count=10000

$(V)dd if=$(bootblock) of=$@ conv=notrunc:把bootblock中的內容寫到第一個塊。

  執行的實際命令爲

dd if=bin/bootblock of=bin/ucore.img conv=notrunc

$(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc:從第二個塊開始寫kernel中的內容。

  執行的實際命令爲

dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc

  

 

3、問題二的解答

 引導扇區的大小爲512字節,最後兩個字節爲標誌性結束字節0x55,0xAA,作完這樣的檢查才能認爲是符合規範的磁盤主引導扇區。

查看sign.c文件的代碼

 1 #include <stdio.h>
 2 #include <errno.h>
 3 #include <string.h>
 4 #include <sys/stat.h>
 5 
 6 int
 7 main(int argc, char *argv[]) {
 8     struct stat st;
 9     if (argc != 3) {
10         fprintf(stderr, "Usage: <input filename> <output filename>\n");
11         return -1;
12     }
13     if (stat(argv[1], &st) != 0) {
14         fprintf(stderr, "Error opening file '%s': %s\n", argv[1], strerror(errno));
15         return -1;
16     }
17     printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
18     if (st.st_size > 510) {
19         fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
20         return -1;
21     }
22     char buf[512];
23     memset(buf, 0, sizeof(buf));
24     FILE *ifp = fopen(argv[1], "rb");
25     int size = fread(buf, 1, st.st_size, ifp);
26     if (size != st.st_size) {
27         fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
28         return -1;
29     }
30     fclose(ifp);
31     buf[510] = 0x55;
32     buf[511] = 0xAA;
33     FILE *ofp = fopen(argv[2], "wb+");
34     size = fwrite(buf, 1, 512, ofp);
35     if (size != 512) {
36         fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);
37         return -1;
38     }
39     fclose(ofp);
40     printf("build 512 bytes boot sector: '%s' success!\n", argv[2]);
41     return 0;
42 }

35行到38行的代碼說明sign.c文件是會做檢查的

if (size != st.st_size) {
        fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
        return -1;
}
相關文章
相關標籤/搜索