Lab_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

练习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 [email protected]
147     $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o [email protected] $(KOBJS)
148     @$(OBJDUMP) -S [email protected] > $(call asmfile,kernel)
149     @$(OBJDUMP) -t [email protected] | $(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 [email protected]
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 [email protected] count=10000
183     $(V)dd if=$(bootblock) [email protected] conv=notrunc
184     $(V)dd if=$(kernel) [email protected] 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-%,%,[email protected]) | $(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)总体概述

①首先把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虚拟磁盘制作完成



三、问题二的解答

引导扇区的大小为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;
}

原文地址:https://www.cnblogs.com/cyx-b/p/11750020.html

时间: 2024-10-13 07:54:06

Lab_1:练习一——理解通过make生成执行文件的过程的相关文章

分析linux下如何运行一个执行文件

本文只为整理思路,供自己日后参考.现在就从从一个执行文件a.out的运行开始,自上而下地分析linux是如何运行一个执行文件的. 1.首先,需要了解一下a.out这个目标文件.a.out在linux下是ELF(Executable Linkable Format)文件格式,该目标文件由一个文件头.代码段.数据段(已初始化).从定位信息区.符号表及符号名字字符串构成,如下左图所示,经过链接后生成执行文件如下右图所示,需要说明的是1).bss段在目标文件和执行文件中并不占用文件的空间,但是它在加载时

通过iTunes生成ipa文件,安装后还是老版本的问题.

今天测试人员安装新版本生成的ipa文件,发现功能还是老版本的功能. 经过查找,产生的原因: 在生成ipa文件的过程中.xcode的iOS Device的一定要选择真机. 只有真机,才能在真机运行后,在工程的Products文件夹下生成新的.app文件. 之前出现这类问题,肯定是因为新的.app文件没有生成,而去生成ipa文件导致的. 提醒:xcode的模拟器和真机运行的是两套不同的api.

带您理解SQLSERVER是如何执行一个查询的

原文地址:http://www.cnblogs.com/lyhabc/p/3367274.html 看这篇文章之前,阁下可以先看一下下面的文章 SQLSERVER独特的任务调度算法"SQLOS" SQL Server SQLOS 的任务调度[转] 翻译自: http://rusanu.com/2013/08/01/understanding-how-sql-server-executes-a-query/ http://www.codeproject.com/Articles/6303

为准确生成执行计划更新统计信息-analyze与dbms_stats

如果我们想让CBO利用合理利用数据的统计信息,正确判断执行任何SQL查询时的最快途径,需要及时的使用analyze命令或者dbms_stats重新统计数据的统计信息. 例如索引跳跃式扫描(INDEX SKIP SCAN)例子中,如果不对表EMPLOYEE 及索引收集一下统计信息,就不是INDEX SKIP SCAN策略了. 分析统计信息 analyze table 一般可以指定分析: 表,所有字段,所有索引字段,所有索引. 若不指定则全部都分析. ---table统计信息 analyze tab

WF4.0以上使用代码完整自定义动态生成执行工作流Xaml文件

给大家分享一下,如何完全使用代码自定义的创建生成工作流文件(用代码创建Xaml文件),并且动态加载运行所生成的工作流. 工作流生成后 在Xaml文件里的主要节点如下: 输入输出参数 <x:Members> <x:Property Name="Item" Type="InArgument(qm:RuleModel)" /> <x:Property Name="Result" Type="OutArgument

Sphinx/Coreseek 4.1 执行 buildconf.sh 报错,无法生成configure文件

参考的网址: http://blog.csdn.net/jcjc918/article/details/39032689 错误现象: 执行 buildconf.sh 报错,无法生成configure文件 报错的代码 automake: warnings are treated as errors /usr/share/automake-1.13/am/library.am: warning: 'libstemmer.a': linking libraries using a non-POSIX

深入理解JVM_java代码的执行机制01

本章学习重点: 1.Jvm: 如何将java代码编译为class文件. 如何装载class文件及如何执行class文件. jvm如何进行内存分配和回收. jvm多线程:线程资源同步机制和线程之间交互的机制. 3.1 java代码的执行机制 java源码编译机制. 1.三个步骤: 分析和输入到符号表(Parse and Enter) Parse过程所做的为词法和语法分析. 词法分析:将代码字符串转变为Token序列. 语法分析:根据语法由Token序列生成抽象语法树. Enter过程为将符合好输入

通过重新生成执行计划解决绑定变量执行计划偏差导致SQL执行时间过长

基本要素(时间.用户.问题) 用户11g环境下有段SQL语句在程序中执行效率非常差,但是在plsql中执行却很快,通过查看执行计划,发现使用了不同的索引导致,程序中执行的如下: PLSQL中执行的效果如下: 可以看到差别,使用门诊费用记录_IX_登记时间索引是在plsql中的执行计划,使用门诊费用记录_UQ_NO的是程序中的执行计划,两者SQL是完全相同的,唯一却别就是前者使用了绑定变量,后者是直接带参数值执行. 问题分析 问题很明显,由于绑定变量生成的执行计划与实际有偏差,11g本来有个绑定变

VS2010 打包生成exe文件后 执行安装文件出现 TODO:&amp;lt;文件说明&amp;gt;已停止工作并已关闭

一.VS2010 打包生成exe文件后  执行安装文件出现  TODO:<文件说明>已停止工作并已关闭 TODO: <文件说明>已停止工作 原因: 打包的时候在文件系统中建立了空目录,那么该空的目录就不会被载入进去,导致程序执行用到该目录的时候就会出现了该问题. 解决方法: 如建立了文件Calibration 那么先随便载入一个文件(如:3.csv)文件进去  不让它为空即可了 二.打包经常使用设置: 1.设置软件的安装文件夹 能够直接改动的faultLocation  如:E:\