zoukankan      html  css  js  c++  java
  • Lab_1:练习1——理解通过make生成执行文件的过程

     参考网站:

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

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

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

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

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

    练习1:理解通过make生成执行文件的过程。(要求在报告中写出对下述问题的回答)

    列出本实验各练习中对应的OS原理的知识点,并说明本实验中的实现部分如何对应和体现了原理中的基本概念和关键知识点。

    在此练习中,大家需要通过静态分析代码来了解:

    1. 操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细地解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
    2. 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么

    一、操作步骤

    1、进入/moocos/ucore_lab/labcodes_answer/lab1_result目录

    cd ./moocos/ucore_lab/labcodes_answer/lab1_result

    2、执行make qemu

    Ctrl+C退出

    3、make clean

    清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件

    4、查看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文件的内容

    5、输入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

    二、问题一的解答

    问题:操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细地解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果)

    答:

    (1)make V=

    1、总体概述

    首先把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

    2、具体分析

    需要生成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 

    三、问题二的解答

     引导扇区的大小为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>
    ");
    11         return -1;
    12     }
    13     if (stat(argv[1], &st) != 0) {
    14         fprintf(stderr, "Error opening file '%s': %s
    ", argv[1], strerror(errno));
    15         return -1;
    16     }
    17     printf("'%s' size: %lld bytes
    ", argv[1], (long long)st.st_size);
    18     if (st.st_size > 510) {
    19         fprintf(stderr, "%lld >> 510!!
    ", (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.
    ", 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.
    ", argv[2], size);
    37         return -1;
    38     }
    39     fclose(ofp);
    40     printf("build 512 bytes boot sector: '%s' success!
    ", argv[2]);
    41     return 0;
    42 }

    35行到38行的代码说明sign.c文件是会作检查的

    if (size != st.st_size) {
            fprintf(stderr, "read '%s' error, size is %d.
    ", argv[1], size);
            return -1;
    }
  • 相关阅读:
    Object类学习
    Thread.State 线程状态
    Thread.UncaughtExceptionHandler
    apply和call的区别
    如何实现border-width:0.5px;
    table固定头部,表格tbody可上下左右滑动
    canvas画布实现手写签名效果
    ES6学习笔记
    for循环中执行setTimeout问题
    javaScript函数提升及作用域
  • 原文地址:https://www.cnblogs.com/cyx-b/p/11750020.html
Copyright © 2011-2022 走看看