0%

OS_Lab1_实验报告

OS_Lab1_实验报告

前置信息

Lab1对于Lab0的跳跃对我来说有点大,因此需要利用AI掌握一些前置信息。

ELF

首先是要了解ELF,先看一段ELF代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* This file defines standard ELF types, structures, and macros.
Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ian Lance Taylor <ian@cygnus.com>.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

#ifndef _ELF_H
#define _ELF_H

#include <stdint.h>

/* ELF defination file from GNU C Library. We simplefied this
* file for our lab, removing definations about ELF64, structs and
* enums which we don't care.
*/

/* Type for a 16-bit quantity. */
typedef uint16_t Elf32_Half;

/* Types for signed and unsigned 32-bit quantities. */
typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;

/* Types for signed and unsigned 64-bit quantities. */
typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;

/* Type of addresses. */
typedef uint32_t Elf32_Addr;

/* Type of file offsets. */
typedef uint32_t Elf32_Off;

/* Type for section indices, which are 16-bit quantities. */
typedef uint16_t Elf32_Section;

/* Type of symbol indices. */
typedef uint32_t Elf32_Symndx;

/* Lab 1 Key Code "readelf-struct-def" */

/* The ELF file header. This appears at the start of every ELF file. */

#define EI_NIDENT (16)

typedef struct {
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;

/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
may have. */

#define EI_MAG0 0 /* File identification byte 0 index */
#define ELFMAG0 0x7f /* Magic number byte 0 */

#define EI_MAG1 1 /* File identification byte 1 index */
#define ELFMAG1 'E' /* Magic number byte 1 */

#define EI_MAG2 2 /* File identification byte 2 index */
#define ELFMAG2 'L' /* Magic number byte 2 */

#define EI_MAG3 3 /* File identification byte 3 index */
#define ELFMAG3 'F' /* Magic number byte 3 */

/* Section segment header. */
typedef struct {
Elf32_Word sh_name; /* Section name */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section addr */
Elf32_Off sh_offset; /* Section offset */
Elf32_Word sh_size; /* Section size */
Elf32_Word sh_link; /* Section link */
Elf32_Word sh_info; /* Section extra info */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Section entry size */
} Elf32_Shdr;

/* Program segment header. */

typedef struct {
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
/* End of Key Code "readelf-struct-def" */

/* Legal values for p_type (segment type). */

#define PT_NULL 0 /* Program header table entry unused */
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define PT_INTERP 3 /* Program interpreter */
#define PT_NOTE 4 /* Auxiliary information */
#define PT_SHLIB 5 /* Reserved */
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_NUM 7 /* Number of defined types. */
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_HIOS 0x6fffffff /* End of OS-specific */
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
#define PT_HIPROC 0x7fffffff /* End of processor-specific */

/* Legal values for p_flags (segment flags). */

#define PF_X (1 << 0) /* Segment is executable */
#define PF_W (1 << 1) /* Segment is writable */
#define PF_R (1 << 2) /* Segment is readable */
#define PF_MASKPROC 0xf0000000 /* Processor-specific */

#endif /* elf.h */

这是一段C语言代码,指导书的注释非常详实,这段代码主要定义了几个结构体,有Elf32_Ehdr,Elf32_Phdr,Elf32_Shdr。

Ehdr(ELF header):

e_ident:主要用来识别是不是ELF文件

e_machine:目标架构,是给x86跑的还是ARM跑的

e_version:ELF的版本号,通常为1

e_entry:程序入口虚拟地址,操作系统把程序加载到内存后,CPU 第一条执行的指令就在这个地址(通常对应代码里的_start函数,而不是main)。

e_phoff:程序头表偏移量 e_shoff:节头表偏移量 e_flags:特定标志位,一般为0

e_ehsize:Elf32_Ehdr结构体本身的字节数 e_phentsize:程序头表中,每一个表项的大小

e_phnum:程序头表里有几个表项(程序被分成了几个Segment) e_shentsize:节头表中每一个表项的大小

e_shnum:节头表有几个表项(文件被分成了几个Section) e_shstrndx:节名字符串表的索引,如.text,.main存放的位置

Shdr(Section header):

sh_name:节的名称索引 sh_type:节的类型 sh_flags:节的权限标志,是否可写,是否需要在内存中分配空间

sh_addr:虚拟地址,如果这个节在程序运行时需要放到内存里,这里就是它期望被加载到的内存地址。如果不加载到内存(比如调试信息),这里就是 0。

sh_offset:文件内偏移量,这个节的实际数据(比如一堆机器指令)在当前文件里的起始位置。

sh_size:这个节占了多少个字节 sh_link:关联节的索引 sh_info:附加信息

sh_addralign:对齐方式,要求这个节在内存里的起始地址必须是某个数的整数倍

sh_entsize:表项大小,如果这个节里面存的是一张表(比如符号表,里面全是固定大小的条目),这里记录每个条目有多大;如果是一般代码/数据,这里为 0。

Phdr(Program header):

p_type:段的类型,最重要的是 PT_LOAD (1),意思是这个段必须被搬进内存里。其他的还有 PT_DYNAMIC(动态链接信息)等。

p_offset:文件内偏移量 p_vaddr_虚拟内存地址,操作系统应该把这个段的数据复制到内存中的哪个虚拟地址。

p_paddr:物理内存地址 p_filesz:文件大小,这个段在文件里占据了多少字节 p_memsz:内存大小,这个段在内存里需要占据多少字节

p_flags:段的访问权限 p_align:内存页对齐要求,规定这个段在内存中的起始地址 p_vaddr 和文件里的 p_offset 必须对齐到一个页面大小的整数倍(通常是 0x1000,即 4096 字节)。这方便操作系统利用内存页机制进行映射。