init commit of lab1_challenge2

lab1_challenge2_errorline
Zhiyuan Shao 3 years ago
parent 9c8cbfaa3b
commit d47e4b23e5

@ -4,8 +4,9 @@ Copyright License
The PKE software is: The PKE software is:
Copyright (c) 2021, Zhiyuan Shao (zyshao@hust.edu.cn), Copyright (c) 2021, Zhiyuan Shao (zyshao@hust.edu.cn),
Yi Gui (gy163email@163.com), Ziming Yuan (1223962053@qq.com),
Yan Jiao (773709579@qq.com), Yixin Song (yixinsong@hust.edu.cn),
Boyang Li (liboyang_hust@163.com),
Huazhong University of Science and Technology Huazhong University of Science and Technology
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining

@ -20,7 +20,7 @@ ifneq (,)
mabi := -mabi=$(if $(is_32bit),ilp32,lp64) mabi := -mabi=$(if $(is_32bit),ilp32,lp64)
endif endif
CFLAGS := -Wall -Werror -fno-builtin -nostdlib -D__NO_INLINE__ -mcmodel=medany -g -Og -std=gnu99 -Wno-unused -Wno-attributes -fno-delete-null-pointer-checks -fno-PIE $(march) CFLAGS := -Wall -Werror -gdwarf-3 -fno-builtin -nostdlib -D__NO_INLINE__ -mcmodel=medany -g -Og -std=gnu99 -Wno-unused -Wno-attributes -fno-delete-null-pointer-checks -fno-PIE $(march)
COMPILE := $(CC) -MMD -MP $(CFLAGS) $(SPROJS_INCLUDE) COMPILE := $(CC) -MMD -MP $(CFLAGS) $(SPROJS_INCLUDE)
#--------------------- utils ----------------------- #--------------------- utils -----------------------
@ -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------------------------ #------------------------targets------------------------
$(OBJ_DIR): $(OBJ_DIR):
@-mkdir -p $(OBJ_DIR) @-mkdir -p $(OBJ_DIR)

@ -47,6 +47,153 @@ elf_status elf_init(elf_ctx *ctx, void *info) {
return EL_OK; 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 // load the elf segments to memory regions as we are in Bare mode in lab1
// //

@ -37,6 +37,33 @@ typedef struct elf_prog_header_t {
uint64 align; /* Segment alignment */ uint64 align; /* Segment alignment */
} elf_prog_header; } 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_MAGIC 0x464C457FU // "\x7FELF" in little endian
#define ELF_PROG_LOAD 1 #define ELF_PROG_LOAD 1

@ -15,12 +15,25 @@ typedef struct trapframe_t {
/* offset:264 */ uint64 epc; /* offset:264 */ uint64 epc;
}trapframe; }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 // the extremely simple definition of process, used for begining labs of PKE
typedef struct process_t { typedef struct process_t {
// pointing to the stack used in trap handling. // pointing to the stack used in trap handling.
uint64 kstack; uint64 kstack;
// trapframe storing the context of a (User mode) process. // trapframe storing the context of a (User mode) process.
trapframe* trapframe; trapframe* trapframe;
// added @lab1_challenge2
char *debugline; char **dir; code_file *file; addr_line *line; int line_ind;
}process; }process;
void switch_to(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…
Cancel
Save