init commit of lab1_challenge2

This commit is contained in:
Zhiyuan Shao 2021-08-18 10:41:51 +08:00
parent 6df8c85479
commit 3a24bfe6e6
7 changed files with 202 additions and 24 deletions

View File

@ -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

View File

@ -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)

View File

@ -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(&regs.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(&regs.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
//

View File

@ -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

View File

@ -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*);

16
user/app_errorline.c Normal file
View File

@ -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);
}

View File

@ -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;
}