init commit of lab1_challenge2
This commit is contained in:
parent
6df8c85479
commit
3a24bfe6e6
|
@ -4,8 +4,9 @@ Copyright License
|
|||
The PKE software is:
|
||||
|
||||
Copyright (c) 2021, Zhiyuan Shao (zyshao@hust.edu.cn),
|
||||
Yi Gui (gy163email@163.com),
|
||||
Yan Jiao (773709579@qq.com),
|
||||
Ziming Yuan (1223962053@qq.com),
|
||||
Yixin Song (yixinsong@hust.edu.cn),
|
||||
Boyang Li (liboyang_hust@163.com),
|
||||
Huazhong University of Science and Technology
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
|
2
Makefile
2
Makefile
|
@ -71,7 +71,7 @@ USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS)))
|
|||
|
||||
|
||||
|
||||
USER_TARGET := $(OBJ_DIR)/app_long_loop
|
||||
USER_TARGET := $(OBJ_DIR)/app_errorline
|
||||
#------------------------targets------------------------
|
||||
$(OBJ_DIR):
|
||||
@-mkdir -p $(OBJ_DIR)
|
||||
|
|
146
kernel/elf.c
146
kernel/elf.c
|
@ -44,7 +44,151 @@ elf_status elf_init(elf_ctx *ctx, void *info) {
|
|||
|
||||
return EL_OK;
|
||||
}
|
||||
|
||||
// leb128 (little-endian base 128) is a variable-length
|
||||
// compression algoritm in DWARF
|
||||
void read_uleb128(uint64 *out, char **off) {
|
||||
uint64 value = 0; int shift = 0; uint8 b;
|
||||
for (;;) {
|
||||
b = *(uint8 *)(*off); (*off)++;
|
||||
value |= ((uint64)b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
if ((b & 0x80) == 0) break;
|
||||
}
|
||||
if (out) *out = value;
|
||||
}
|
||||
void read_sleb128(int64 *out, char **off) {
|
||||
int64 value = 0; int shift = 0; uint8 b;
|
||||
for (;;) {
|
||||
b = *(uint8 *)(*off); (*off)++;
|
||||
value |= ((uint64_t)b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
if ((b & 0x80) == 0) break;
|
||||
}
|
||||
if (shift < 64 && (b & 0x40)) value |= -(1 << shift);
|
||||
if (out) *out = value;
|
||||
}
|
||||
// Since reading below types through pointer cast requires aligned address,
|
||||
// so we can only read them byte by byte
|
||||
void read_uint64(uint64 *out, char **off) {
|
||||
*out = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*out |= (uint64)(**off) << (i << 3); (*off)++;
|
||||
}
|
||||
}
|
||||
void read_uint32(uint32 *out, char **off) {
|
||||
*out = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
*out |= (uint32)(**off) << (i << 3); (*off)++;
|
||||
}
|
||||
}
|
||||
void read_uint16(uint16 *out, char **off) {
|
||||
*out = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
*out |= (uint16)(**off) << (i << 3); (*off)++;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* analyzis the data in the debug_line section
|
||||
*
|
||||
* the function needs 3 parameters: elf context, data in the debug_line section
|
||||
* and length of debug_line section
|
||||
*
|
||||
* make 3 arrays:
|
||||
* "process->dir" stores all directory paths of code files
|
||||
* "process->file" stores all code file names of code files and their directory path index of array "dir"
|
||||
* "process->line" stores all relationships map instruction addresses to code line numbers
|
||||
* and their code file name index of array "file"
|
||||
*/
|
||||
void make_addr_line(elf_ctx *ctx, char *debug_line, uint64 length) {
|
||||
process *p = ((elf_info *)ctx->info)->p;
|
||||
p->debugline = debug_line;
|
||||
// directory name char pointer array
|
||||
p->dir = (char **)((((uint64)debug_line + length + 7) >> 3) << 3); int dir_ind = 0, dir_base;
|
||||
// file name char pointer array
|
||||
p->file = (code_file *)(p->dir + 64); int file_ind = 0, file_base;
|
||||
// table array
|
||||
p->line = (addr_line *)(p->file + 64); p->line_ind = 0;
|
||||
char *off = debug_line;
|
||||
while (off < debug_line + length) { // iterate each compilation unit(CU)
|
||||
debug_header *dh = (debug_header *)off; off += sizeof(debug_header);
|
||||
dir_base = dir_ind; file_base = file_ind;
|
||||
// get directory name char pointer in this CU
|
||||
while (*off != 0) {
|
||||
p->dir[dir_ind++] = off; while (*off != 0) off++; off++;
|
||||
}
|
||||
off++;
|
||||
// get file name char pointer in this CU
|
||||
while (*off != 0) {
|
||||
p->file[file_ind].file = off; while (*off != 0) off++; off++;
|
||||
uint64 dir; read_uleb128(&dir, &off);
|
||||
p->file[file_ind++].dir = dir - 1 + dir_base;
|
||||
read_uleb128(NULL, &off); read_uleb128(NULL, &off);
|
||||
}
|
||||
off++; addr_line regs; regs.addr = 0; regs.file = 1; regs.line = 1;
|
||||
// simulate the state machine op code
|
||||
for (;;) {
|
||||
uint8 op = *(off++);
|
||||
switch (op) {
|
||||
case 0: // Extended Opcodes
|
||||
read_uleb128(NULL, &off); op = *(off++);
|
||||
switch (op) {
|
||||
case 1: // DW_LNE_end_sequence
|
||||
if (p->line_ind > 0 && p->line[p->line_ind - 1].addr == regs.addr) p->line_ind--;
|
||||
p->line[p->line_ind] = regs; p->line[p->line_ind].file += file_base - 1;
|
||||
p->line_ind++; goto endop;
|
||||
case 2: // DW_LNE_set_address
|
||||
read_uint64(®s.addr, &off); break;
|
||||
// ignore DW_LNE_define_file
|
||||
case 4: // DW_LNE_set_discriminator
|
||||
read_uleb128(NULL, &off); break;
|
||||
}
|
||||
break;
|
||||
case 1: // DW_LNS_copy
|
||||
if (p->line_ind > 0 && p->line[p->line_ind - 1].addr == regs.addr) p->line_ind--;
|
||||
p->line[p->line_ind] = regs; p->line[p->line_ind].file += file_base - 1;
|
||||
p->line_ind++; break;
|
||||
case 2: { // DW_LNS_advance_pc
|
||||
uint64 delta; read_uleb128(&delta, &off);
|
||||
regs.addr += delta * dh->min_instruction_length;
|
||||
break;
|
||||
}
|
||||
case 3: { // DW_LNS_advance_line
|
||||
int64 delta; read_sleb128(&delta, &off);
|
||||
regs.line += delta; break; } case 4: // DW_LNS_set_file
|
||||
read_uleb128(®s.file, &off); break;
|
||||
case 5: // DW_LNS_set_column
|
||||
read_uleb128(NULL, &off); break;
|
||||
case 6: // DW_LNS_negate_stmt
|
||||
case 7: // DW_LNS_set_basic_block
|
||||
break;
|
||||
case 8: { // DW_LNS_const_add_pc
|
||||
int adjust = 255 - dh->opcode_base;
|
||||
int delta = (adjust / dh->line_range) * dh->min_instruction_length;
|
||||
regs.addr += delta; break;
|
||||
}
|
||||
case 9: { // DW_LNS_fixed_advanced_pc
|
||||
uint16 delta; read_uint16(&delta, &off);
|
||||
regs.addr += delta;
|
||||
break;
|
||||
}
|
||||
// ignore 10, 11 and 12
|
||||
default: { // Special Opcodes
|
||||
int adjust = op - dh->opcode_base;
|
||||
int addr_delta = (adjust / dh->line_range) * dh->min_instruction_length;
|
||||
int line_delta = dh->line_base + (adjust % dh->line_range);
|
||||
regs.addr += addr_delta;
|
||||
regs.line += line_delta;
|
||||
if (p->line_ind > 0 && p->line[p->line_ind - 1].addr == regs.addr) p->line_ind--;
|
||||
p->line[p->line_ind] = regs; p->line[p->line_ind].file += file_base - 1;
|
||||
p->line_ind++; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
endop:;
|
||||
}
|
||||
// for (int i = 0; i < p->line_ind; i++)
|
||||
// sprint("%p %d %d\n", p->line[i].addr, p->line[i].line, p->line[i].file);
|
||||
}
|
||||
//
|
||||
// load the elf segments to memory regions as we are in Bare mode in lab1
|
||||
//
|
||||
|
|
27
kernel/elf.h
27
kernel/elf.h
|
@ -37,6 +37,33 @@ typedef struct elf_prog_header_t {
|
|||
uint64 align; /* Segment alignment */
|
||||
} elf_prog_header;
|
||||
|
||||
// elf section header
|
||||
typedef struct elf_sect_header_t{
|
||||
uint32 name;
|
||||
uint32 type;
|
||||
uint64 flags;
|
||||
uint64 addr;
|
||||
uint64 offset;
|
||||
uint64 size;
|
||||
uint32 link;
|
||||
uint32 info;
|
||||
uint64 addralign;
|
||||
uint64 entsize;
|
||||
} elf_sect_header;
|
||||
|
||||
// compilation units header (in debug line section)
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32 length;
|
||||
uint16 version;
|
||||
uint32 header_length;
|
||||
uint8 min_instruction_length;
|
||||
uint8 default_is_stmt;
|
||||
int8 line_base;
|
||||
uint8 line_range;
|
||||
uint8 opcode_base;
|
||||
uint8 std_opcode_lengths[12];
|
||||
} debug_header;
|
||||
|
||||
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
|
||||
#define ELF_PROG_LOAD 1
|
||||
|
||||
|
|
|
@ -15,12 +15,22 @@ typedef struct trapframe {
|
|||
/* offset:264 */ uint64 epc;
|
||||
}trapframe;
|
||||
|
||||
// code file struct, including directory index and file name char pointer
|
||||
typedef struct {
|
||||
uint64 dir; char *file;
|
||||
} code_file;
|
||||
// address-line number-file name table
|
||||
typedef struct {
|
||||
uint64 addr, line, file;
|
||||
} addr_line;
|
||||
|
||||
// the extremely simple definition of process, used for begining labs of PKE
|
||||
typedef struct process {
|
||||
// pointing to the stack used in trap handling.
|
||||
uint64 kstack;
|
||||
// trapframe storing the context of a (User mode) process.
|
||||
trapframe* trapframe;
|
||||
char *debugline; char **dir; code_file *file; addr_line *line; int line_ind;
|
||||
}process;
|
||||
|
||||
void switch_to(process*);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Below is the given application for lab1_challenge2 (same as lab1_2).
|
||||
* This app attempts to issue M-mode instruction in U-mode, and consequently raises an exception.
|
||||
*/
|
||||
|
||||
#include "user_lib.h"
|
||||
#include "util/types.h"
|
||||
|
||||
int main(void) {
|
||||
printu("Going to hack the system by running privilege instructions.\n");
|
||||
// we are now in U(user)-mode, but the "csrw" instruction requires M-mode privilege.
|
||||
// Attempting to execute such instruction will raise illegal instruction exception.
|
||||
asm volatile("csrw sscratch, 0");
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Below is the given application for lab1_3.
|
||||
* This app performs a long loop, during which, timers are
|
||||
* generated and pop messages to our screen.
|
||||
*/
|
||||
|
||||
#include "user_lib.h"
|
||||
#include "util/types.h"
|
||||
|
||||
int main(void) {
|
||||
printu("Hello world!\n");
|
||||
int i;
|
||||
for (i = 0; i < 100000000; ++i) {
|
||||
if (i % 5000000 == 0) printu("wait %d\n", i);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue