commit 09bc033bb5d39ba1bb6dc9f59626740772c2c5a8 Author: GentleCold <1952173800@qq.com> Date: Fri Sep 9 19:08:27 2022 +0800 feat: finish data_lab diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d07ce9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +cmake-build-debug +build +.idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8ba4430 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.16) +project(CsappLearning C) + +set(CMAKE_C_STANDARD 11) + +set(BUILD_PATH ${CMAKE_SOURCE_DIR}/build) # 自定义路径变量 +set(LAB_PATH ${CMAKE_SOURCE_DIR}/labs) + +set(EXECUTABLE_OUTPUT_PATH ${BUILD_PATH}) # EXE +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PATH}) # LIB + +add_executable(TestQuiz quiz/test_quiz.c) + +if(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug")) + add_definitions(-DDEBUG) +endif() \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4a0417e --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# CsappLearning + +这是一个本人学习 csapp 的 learning 库 + +其中包括: +* labs - csapp 的各项来自官网的 lab +* quiz - csapp 的部分练习与课堂作业 +* csapp.txt - 由本人 E-note 项目生成的笔记 + +各 lab 得分 +* Datalab - 62 / 62 + * 项目目录下运行 ```./labs/data_lab/driver.pl -u GentleCold``` + +注: +* 本人运行环境: WINDOWS10 - WSL2 +* 各 lab 由其自带的 Makefile 编译 + * ~~但为了保证 linux 环境,使用 cmake 调用 make 编译~~ + * cmake 调用失败,使用 wsl shell 手动 make +* quiz 由本人编写的 CMakeLists 编译 +* 所有 lab 尽可能的不参考他人代码,参考处会有 //TODO 标记 \ No newline at end of file diff --git a/labs/attack_lab/README.txt b/labs/attack_lab/README.txt new file mode 100644 index 0000000..8a49506 --- /dev/null +++ b/labs/attack_lab/README.txt @@ -0,0 +1,28 @@ +This file contains materials for one instance of the attacklab. + +Files: + + ctarget + +Linux binary with code-injection vulnerability. To be used for phases +1-3 of the assignment. + + rtarget + +Linux binary with return-oriented programming vulnerability. To be +used for phases 4-5 of the assignment. + + cookie.txt + +Text file containing 4-byte signature required for this lab instance. + + farm.c + +Source code for gadget farm present in this instance of rtarget. You +can compile (use flag -Og) and disassemble it to look for gadgets. + + hex2raw + +Utility program to generate byte sequences. See documentation in lab +handout. + diff --git a/labs/attack_lab/cookie.txt b/labs/attack_lab/cookie.txt new file mode 100644 index 0000000..3f780a4 --- /dev/null +++ b/labs/attack_lab/cookie.txt @@ -0,0 +1 @@ +0x59b997fa diff --git a/labs/attack_lab/ctarget b/labs/attack_lab/ctarget new file mode 100644 index 0000000..b5cb728 Binary files /dev/null and b/labs/attack_lab/ctarget differ diff --git a/labs/attack_lab/farm.c b/labs/attack_lab/farm.c new file mode 100644 index 0000000..25293c9 --- /dev/null +++ b/labs/attack_lab/farm.c @@ -0,0 +1,223 @@ +/* This function marks the start of the farm */ +int start_farm() +{ + return 1; +} + +unsigned getval_142() +{ + return 2425387259U; +} + +unsigned addval_273(unsigned x) +{ + return x + 3284633928U; +} + +unsigned addval_219(unsigned x) +{ + return x + 2421715793U; +} + +void setval_237(unsigned *p) +{ + *p = 3351742792U; +} + +void setval_424(unsigned *p) +{ + *p = 2455290452U; +} + +void setval_470(unsigned *p) +{ + *p = 3347925091U; +} + +void setval_426(unsigned *p) +{ + *p = 2428995912U; +} + +unsigned getval_280() +{ + return 3281016873U; +} + +/* This function marks the middle of the farm */ +int mid_farm() +{ + return 1; +} + +/* Add two arguments */ +long add_xy(long x, long y) +{ + return x+y; +} + +unsigned getval_481() +{ + return 2428668252U; +} + +void setval_296(unsigned *p) +{ + *p = 2425409945U; +} + +unsigned addval_113(unsigned x) +{ + return x + 3380137609U; +} + +unsigned addval_490(unsigned x) +{ + return x + 3676361101U; +} + +unsigned getval_226() +{ + return 3225997705U; +} + +void setval_384(unsigned *p) +{ + *p = 3229929857U; +} + +unsigned addval_190(unsigned x) +{ + return x + 3767093313U; +} + +void setval_276(unsigned *p) +{ + *p = 3372794504U; +} + +unsigned addval_436(unsigned x) +{ + return x + 2425409161U; +} + +unsigned getval_345() +{ + return 3252717896U; +} + +unsigned addval_479(unsigned x) +{ + return x + 3372270217U; +} + +unsigned addval_187(unsigned x) +{ + return x + 3224948361U; +} + +void setval_248(unsigned *p) +{ + *p = 3674787457U; +} + +unsigned getval_159() +{ + return 3375944073U; +} + +unsigned addval_110(unsigned x) +{ + return x + 3286272456U; +} + +unsigned addval_487(unsigned x) +{ + return x + 3229926025U; +} + +unsigned addval_201(unsigned x) +{ + return x + 3353381192U; +} + +unsigned getval_272() +{ + return 3523793305U; +} + +unsigned getval_155() +{ + return 3385115273U; +} + +void setval_299(unsigned *p) +{ + *p = 2447411528U; +} + +unsigned addval_404(unsigned x) +{ + return x + 3281178249U; +} + +unsigned getval_311() +{ + return 3674788233U; +} + +void setval_167(unsigned *p) +{ + *p = 3281113481U; +} + +void setval_328(unsigned *p) +{ + *p = 3526935169U; +} + +void setval_450(unsigned *p) +{ + *p = 3372797449U; +} + +unsigned addval_358(unsigned x) +{ + return x + 2430634248U; +} + +unsigned addval_124(unsigned x) +{ + return x + 1019724425U; +} + +unsigned getval_169() +{ + return 3223375496U; +} + +void setval_181(unsigned *p) +{ + *p = 3269495112U; +} + +unsigned addval_184(unsigned x) +{ + return x + 3529556617U; +} + +unsigned getval_472() +{ + return 3525365389U; +} + +void setval_350(unsigned *p) +{ + *p = 2430634312U; +} + +/* This function marks the end of the farm */ +int end_farm() +{ + return 1; +} diff --git a/labs/attack_lab/hex2raw b/labs/attack_lab/hex2raw new file mode 100644 index 0000000..cef0950 Binary files /dev/null and b/labs/attack_lab/hex2raw differ diff --git a/labs/attack_lab/rtarget b/labs/attack_lab/rtarget new file mode 100644 index 0000000..806500a Binary files /dev/null and b/labs/attack_lab/rtarget differ diff --git a/labs/cache_lab/Makefile b/labs/cache_lab/Makefile new file mode 100644 index 0000000..1712d8c --- /dev/null +++ b/labs/cache_lab/Makefile @@ -0,0 +1,33 @@ +# +# Student makefile for Cache Lab +# Note: requires a 64-bit x86-64 system +# +CC = gcc +CFLAGS = -g -Wall -Werror -std=c99 -m64 + +all: csim test-trans tracegen + # Generate a handin tar file each time you compile + -tar -cvf ${USER}-handin.tar csim.c trans.c + +csim: csim.c cachelab.c cachelab.h + $(CC) $(CFLAGS) -o csim csim.c cachelab.c -lm + +test-trans: test-trans.c trans.o cachelab.c cachelab.h + $(CC) $(CFLAGS) -o test-trans test-trans.c cachelab.c trans.o + +tracegen: tracegen.c trans.o cachelab.c + $(CC) $(CFLAGS) -O0 -o tracegen tracegen.c trans.o cachelab.c + +trans.o: trans.c + $(CC) $(CFLAGS) -O0 -c trans.c + +# +# Clean the src dirctory +# +clean: + rm -rf *.o + rm -f *.tar + rm -f csim + rm -f test-trans tracegen + rm -f trace.all trace.f* + rm -f .csim_results .marker diff --git a/labs/cache_lab/README b/labs/cache_lab/README new file mode 100644 index 0000000..5af6f01 --- /dev/null +++ b/labs/cache_lab/README @@ -0,0 +1,39 @@ +This is the handout directory for the CS:APP Cache Lab. + +************************ +Running the autograders: +************************ + +Before running the autograders, compile your code: + linux> make + +Check the correctness of your simulator: + linux> ./test-csim + +Check the correctness and performance of your transpose functions: + linux> ./test-trans -M 32 -N 32 + linux> ./test-trans -M 64 -N 64 + linux> ./test-trans -M 61 -N 67 + +Check everything at once (this is the program that your instructor runs): + linux> ./driver.py + +****** +Files: +****** + +# You will modifying and handing in these two files +csim.c Your cache simulator +trans.c Your transpose function + +# Tools for evaluating your simulator and transpose function +Makefile Builds the simulator and tools +README This file +driver.py* The driver program, runs test-csim and test-trans +cachelab.c Required helper functions +cachelab.h Required header file +csim-ref* The executable reference cache simulator +test-csim* Tests your cache simulator +test-trans.c Tests your transpose function +tracegen.c Helper program used by test-trans +traces/ Trace files used by test-csim.c diff --git a/labs/cache_lab/cachelab.c b/labs/cache_lab/cachelab.c new file mode 100644 index 0000000..85ac5e4 --- /dev/null +++ b/labs/cache_lab/cachelab.c @@ -0,0 +1,83 @@ +/* + * cachelab.c - Cache Lab helper functions + */ +#include +#include +#include +#include "cachelab.h" +#include + +trans_func_t func_list[MAX_TRANS_FUNCS]; +int func_counter = 0; + +/* + * printSummary - Summarize the cache simulation statistics. Student cache simulators + * must call this function in order to be properly autograded. + */ +void printSummary(int hits, int misses, int evictions) +{ + printf("hits:%d misses:%d evictions:%d\n", hits, misses, evictions); + FILE* output_fp = fopen(".csim_results", "w"); + assert(output_fp); + fprintf(output_fp, "%d %d %d\n", hits, misses, evictions); + fclose(output_fp); +} + +/* + * initMatrix - Initialize the given matrix + */ +void initMatrix(int M, int N, int A[N][M], int B[M][N]) +{ + int i, j; + srand(time(NULL)); + for (i = 0; i < N; i++){ + for (j = 0; j < M; j++){ + // A[i][j] = i+j; /* The matrix created this way is symmetric */ + A[i][j]=rand(); + B[j][i]=rand(); + } + } +} + +void randMatrix(int M, int N, int A[N][M]) { + int i, j; + srand(time(NULL)); + for (i = 0; i < N; i++){ + for (j = 0; j < M; j++){ + // A[i][j] = i+j; /* The matrix created this way is symmetric */ + A[i][j]=rand(); + } + } +} + +/* + * correctTrans - baseline transpose function used to evaluate correctness + */ +void correctTrans(int M, int N, int A[N][M], int B[M][N]) +{ + int i, j, tmp; + for (i = 0; i < N; i++){ + for (j = 0; j < M; j++){ + tmp = A[i][j]; + B[j][i] = tmp; + } + } +} + + + +/* + * registerTransFunction - Add the given trans function into your list + * of functions to be tested + */ +void registerTransFunction(void (*trans)(int M, int N, int[N][M], int[M][N]), + char* desc) +{ + func_list[func_counter].func_ptr = trans; + func_list[func_counter].description = desc; + func_list[func_counter].correct = 0; + func_list[func_counter].num_hits = 0; + func_list[func_counter].num_misses = 0; + func_list[func_counter].num_evictions =0; + func_counter++; +} diff --git a/labs/cache_lab/cachelab.h b/labs/cache_lab/cachelab.h new file mode 100644 index 0000000..02f7730 --- /dev/null +++ b/labs/cache_lab/cachelab.h @@ -0,0 +1,37 @@ +/* + * cachelab.h - Prototypes for Cache Lab helper functions + */ + +#ifndef CACHELAB_TOOLS_H +#define CACHELAB_TOOLS_H + +#define MAX_TRANS_FUNCS 100 + +typedef struct trans_func{ + void (*func_ptr)(int M,int N,int[N][M],int[M][N]); + char* description; + char correct; + unsigned int num_hits; + unsigned int num_misses; + unsigned int num_evictions; +} trans_func_t; + +/* + * printSummary - This function provides a standard way for your cache + * simulator * to display its final hit and miss statistics + */ +void printSummary(int hits, /* number of hits */ + int misses, /* number of misses */ + int evictions); /* number of evictions */ + +/* Fill the matrix with data */ +void initMatrix(int M, int N, int A[N][M], int B[M][N]); + +/* The baseline trans function that produces correct results. */ +void correctTrans(int M, int N, int A[N][M], int B[M][N]); + +/* Add the given function to the function list */ +void registerTransFunction( + void (*trans)(int M,int N,int[N][M],int[M][N]), char* desc); + +#endif /* CACHELAB_TOOLS_H */ diff --git a/labs/cache_lab/csim b/labs/cache_lab/csim new file mode 100644 index 0000000..d2a6d59 Binary files /dev/null and b/labs/cache_lab/csim differ diff --git a/labs/cache_lab/csim-ref b/labs/cache_lab/csim-ref new file mode 100644 index 0000000..994a78b Binary files /dev/null and b/labs/cache_lab/csim-ref differ diff --git a/labs/cache_lab/csim.c b/labs/cache_lab/csim.c new file mode 100644 index 0000000..44fdd4b --- /dev/null +++ b/labs/cache_lab/csim.c @@ -0,0 +1,7 @@ +#include "cachelab.h" + +int main() +{ + printSummary(0, 0, 0); + return 0; +} diff --git a/labs/cache_lab/csim.exe b/labs/cache_lab/csim.exe new file mode 100644 index 0000000..334cab6 Binary files /dev/null and b/labs/cache_lab/csim.exe differ diff --git a/labs/cache_lab/driver.py b/labs/cache_lab/driver.py new file mode 100644 index 0000000..f39bd9f --- /dev/null +++ b/labs/cache_lab/driver.py @@ -0,0 +1,138 @@ +#!/usr//bin/python +# +# driver.py - The driver tests the correctness of the student's cache +# simulator and the correctness and performance of their transpose +# function. It uses ./test-csim to check the correctness of the +# simulator and it runs ./test-trans on three different sized +# matrices (32x32, 64x64, and 61x67) to test the correctness and +# performance of the transpose function. +# +import subprocess; +import re; +import os; +import sys; +import optparse; + +# +# computeMissScore - compute the score depending on the number of +# cache misses +# +def computeMissScore(miss, lower, upper, full_score): + if miss <= lower: + return full_score + if miss >= upper: + return 0 + + score = (miss - lower) * 1.0 + range = (upper- lower) * 1.0 + return round((1 - score / range) * full_score, 1) + +# +# main - Main function +# +def main(): + + # Configure maxscores here + maxscore= {}; + maxscore['csim'] = 27 + maxscore['transc'] = 1 + maxscore['trans32'] = 8 + maxscore['trans64'] = 8 + maxscore['trans61'] = 10 + + # Parse the command line arguments + p = optparse.OptionParser() + p.add_option("-A", action="store_true", dest="autograde", + help="emit autoresult string for Autolab"); + opts, args = p.parse_args() + autograde = opts.autograde + + # Check the correctness of the cache simulator + print "Part A: Testing cache simulator" + print "Running ./test-csim" + p = subprocess.Popen("./test-csim", + shell=True, stdout=subprocess.PIPE) + stdout_data = p.communicate()[0] + + # Emit the output from test-csim + stdout_data = re.split('\n', stdout_data) + for line in stdout_data: + if re.match("TEST_CSIM_RESULTS", line): + resultsim = re.findall(r'(\d+)', line) + else: + print "%s" % (line) + + # Check the correctness and performance of the transpose function + # 32x32 transpose + print "Part B: Testing transpose function" + print "Running ./test-trans -M 32 -N 32" + p = subprocess.Popen("./test-trans -M 32 -N 32 | grep TEST_TRANS_RESULTS", + shell=True, stdout=subprocess.PIPE) + stdout_data = p.communicate()[0] + result32 = re.findall(r'(\d+)', stdout_data) + + # 64x64 transpose + print "Running ./test-trans -M 64 -N 64" + p = subprocess.Popen("./test-trans -M 64 -N 64 | grep TEST_TRANS_RESULTS", + shell=True, stdout=subprocess.PIPE) + stdout_data = p.communicate()[0] + result64 = re.findall(r'(\d+)', stdout_data) + + # 61x67 transpose + print "Running ./test-trans -M 61 -N 67" + p = subprocess.Popen("./test-trans -M 61 -N 67 | grep TEST_TRANS_RESULTS", + shell=True, stdout=subprocess.PIPE) + stdout_data = p.communicate()[0] + result61 = re.findall(r'(\d+)', stdout_data) + + # Compute the scores for each step + csim_cscore = map(int, resultsim[0:1]) + trans_cscore = int(result32[0]) * int(result64[0]) * int(result61[0]); + miss32 = int(result32[1]) + miss64 = int(result64[1]) + miss61 = int(result61[1]) + trans32_score = computeMissScore(miss32, 300, 600, maxscore['trans32']) * int(result32[0]) + trans64_score = computeMissScore(miss64, 1300, 2000, maxscore['trans64']) * int(result64[0]) + trans61_score = computeMissScore(miss61, 2000, 3000, maxscore['trans61']) * int(result61[0]) + total_score = csim_cscore[0] + trans32_score + trans64_score + trans61_score + + # Summarize the results + print "\nCache Lab summary:" + print "%-22s%8s%10s%12s" % ("", "Points", "Max pts", "Misses") + print "%-22s%8.1f%10d" % ("Csim correctness", csim_cscore[0], + maxscore['csim']) + + misses = str(miss32) + if miss32 == 2**31-1 : + misses = "invalid" + print "%-22s%8.1f%10d%12s" % ("Trans perf 32x32", trans32_score, + maxscore['trans32'], misses) + + misses = str(miss64) + if miss64 == 2**31-1 : + misses = "invalid" + print "%-22s%8.1f%10d%12s" % ("Trans perf 64x64", trans64_score, + maxscore['trans64'], misses) + + misses = str(miss61) + if miss61 == 2**31-1 : + misses = "invalid" + print "%-22s%8.1f%10d%12s" % ("Trans perf 61x67", trans61_score, + maxscore['trans61'], misses) + + print "%22s%8.1f%10d" % ("Total points", total_score, + maxscore['csim'] + + maxscore['trans32'] + + maxscore['trans64'] + + maxscore['trans61']) + + # Emit autoresult string for Autolab if called with -A option + if autograde: + autoresult="%.1f:%d:%d:%d" % (total_score, miss32, miss64, miss61) + print "\nAUTORESULT_STRING=%s" % autoresult + + +# execute main only if called as a script +if __name__ == "__main__": + main() + diff --git a/labs/cache_lab/gentle-handin.tar b/labs/cache_lab/gentle-handin.tar new file mode 100644 index 0000000..3b31a5c Binary files /dev/null and b/labs/cache_lab/gentle-handin.tar differ diff --git a/labs/cache_lab/test-csim b/labs/cache_lab/test-csim new file mode 100644 index 0000000..09fbc05 Binary files /dev/null and b/labs/cache_lab/test-csim differ diff --git a/labs/cache_lab/test-trans b/labs/cache_lab/test-trans new file mode 100644 index 0000000..df8bde1 Binary files /dev/null and b/labs/cache_lab/test-trans differ diff --git a/labs/cache_lab/test-trans.c b/labs/cache_lab/test-trans.c new file mode 100644 index 0000000..a5adfce --- /dev/null +++ b/labs/cache_lab/test-trans.c @@ -0,0 +1,261 @@ +/* + * test-trans.c - Checks the correctness and performance of all of the + * student's transpose functions and records the results for their + * official submitted version as well. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cachelab.h" +#include // fir WEXITSTATUS +#include // for INT_MAX + +/* Maximum array dimension */ +#define MAXN 256 + +/* The description string for the transpose_submit() function that the + student submits for credit */ +#define SUBMIT_DESCRIPTION "Transpose submission" + +/* External function defined in trans.c */ +extern void registerFunctions(); + +/* External variables defined in cachelab-tools.c */ +extern trans_func_t func_list[MAX_TRANS_FUNCS]; +extern int func_counter; + +/* Globals set on the command line */ +static int M = 0; +static int N = 0; + +/* The correctness and performance for the submitted transpose function */ +struct results { + int funcid; + int correct; + int misses; +}; +static struct results results = {-1, 0, INT_MAX}; + +/* + * eval_perf - Evaluate the performance of the registered transpose functions + */ +void eval_perf(unsigned int s, unsigned int E, unsigned int b) +{ + int i,flag; + unsigned int len, hits, misses, evictions; + unsigned long long int marker_start, marker_end, addr; + char buf[1000], cmd[255]; + char filename[128]; + + registerFunctions(); + + /* Open the complete trace file */ + FILE* full_trace_fp; + FILE* part_trace_fp; + + /* Evaluate the performance of each registered transpose function */ + + for (i=0; i trace.tmp", M, N,i); + flag=WEXITSTATUS(system(cmd)); + if (0!=flag) { + printf("Validation error at function %d! Run ./tracegen -M %d -N %d -F %d for details.\nSkipping performance evaluation for this function.\n",flag-1,M,N,i); + continue; + } + + /* Get the start and end marker addresses */ + FILE* marker_fp = fopen(".marker", "r"); + assert(marker_fp); + fscanf(marker_fp, "%llx %llx", &marker_start, &marker_end); + fclose(marker_fp); + + + func_list[i].correct=1; + + /* Save the correctness of the transpose submission */ + if (results.funcid == i ) { + results.correct = 1; + } + + full_trace_fp = fopen("trace.tmp", "r"); + assert(full_trace_fp); + + + /* Filtered trace for each transpose function goes in a separate file */ + sprintf(filename, "trace.f%d", i); + part_trace_fp = fopen(filename, "w"); + assert(part_trace_fp); + + /* Locate trace corresponding to the trans function */ + flag = 0; + while (fgets(buf, 1000, full_trace_fp) != NULL) { + + /* We are only interested in memory access instructions */ + if (buf[0]==' ' && buf[2]==' ' && + (buf[1]=='S' || buf[1]=='M' || buf[1]=='L' )) { + sscanf(buf+3, "%llx,%u", &addr, &len); + + /* If start marker found, set flag */ + if (addr == marker_start) + flag = 1; + + /* Valgrind creates many spurious accesses to the + stack that have nothing to do with the students + code. At the moment, we are ignoring all stack + accesses by using the simple filter of recording + accesses to only the low 32-bit portion of the + address space. At some point it would be nice to + try to do more informed filtering so that would + eliminate the valgrind stack references while + include the student stack references. */ + if (flag && addr < 0xffffffff) { + fputs(buf, part_trace_fp); + } + + /* if end marker found, close trace file */ + if (addr == marker_end) { + flag = 0; + fclose(part_trace_fp); + break; + } + } + } + fclose(full_trace_fp); + + /* Run the reference simulator */ + printf("Step 2: Evaluating performance (s=%d, E=%d, b=%d)\n", s, E, b); + char cmd[255]; + sprintf(cmd, "./csim-ref -s %u -E %u -b %u -t trace.f%d > /dev/null", + s, E, b, i); + system(cmd); + + /* Collect results from the reference simulator */ + FILE* in_fp = fopen(".csim_results","r"); + assert(in_fp); + fscanf(in_fp, "%u %u %u", &hits, &misses, &evictions); + fclose(in_fp); + func_list[i].num_hits = hits; + func_list[i].num_misses = misses; + func_list[i].num_evictions = evictions; + printf("func %u (%s): hits:%u, misses:%u, evictions:%u\n", + i, func_list[i].description, hits, misses, evictions); + + /* If it is transpose_submit(), record number of misses */ + if (results.funcid == i) { + results.misses = misses; + } + } + +} + +/* + * usage - Print usage info + */ +void usage(char *argv[]){ + printf("Usage: %s [-h] -M -N \n", argv[0]); + printf("Options:\n"); + printf(" -h Print this help message.\n"); + printf(" -M Number of matrix rows (max %d)\n", MAXN); + printf(" -N Number of matrix columns (max %d)\n", MAXN); + printf("Example: %s -M 8 -N 8\n", argv[0]); +} + +/* + * sigsegv_handler - SIGSEGV handler + */ +void sigsegv_handler(int signum){ + printf("Error: Segmentation Fault.\n"); + printf("TEST_TRANS_RESULTS=0:0\n"); + fflush(stdout); + exit(1); +} + +/* + * sigalrm_handler - SIGALRM handler + */ +void sigalrm_handler(int signum){ + printf("Error: Program timed out.\n"); + printf("TEST_TRANS_RESULTS=0:0\n"); + fflush(stdout); + exit(1); +} + +/* + * main - Main routine + */ +int main(int argc, char* argv[]) +{ + char c; + + while ((c = getopt(argc,argv,"M:N:h")) != -1) { + switch(c) { + case 'M': + M = atoi(optarg); + break; + case 'N': + N = atoi(optarg); + break; + case 'h': + usage(argv); + exit(0); + default: + usage(argv); + exit(1); + } + } + + if (M == 0 || N == 0) { + printf("Error: Missing required argument\n"); + usage(argv); + exit(1); + } + + if (M > MAXN || N > MAXN) { + printf("Error: M or N exceeds %d\n", MAXN); + usage(argv); + exit(1); + } + + /* Install SIGSEGV and SIGALRM handlers */ + if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { + fprintf(stderr, "Unable to install SIGALRM handler\n"); + exit(1); + } + + if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) { + fprintf(stderr, "Unable to install SIGALRM handler\n"); + exit(1); + } + + /* Time out and give up after a while */ + alarm(120); + + /* Check the performance of the student's transpose function */ + eval_perf(5, 1, 5); + + /* Emit the results for this particular test */ + if (results.funcid == -1) { + printf("\nError: We could not find your transpose_submit() function\n"); + printf("Error: Please ensure that description field is exactly \"%s\"\n", + SUBMIT_DESCRIPTION); + printf("\nTEST_TRANS_RESULTS=0:0\n"); + } + else { + printf("\nSummary for official submission (func %d): correctness=%d misses=%d\n", + results.funcid, results.correct, results.misses); + printf("\nTEST_TRANS_RESULTS=%d:%d\n", results.correct, results.misses); + } + return 0; +} diff --git a/labs/cache_lab/tracegen b/labs/cache_lab/tracegen new file mode 100644 index 0000000..33650f6 Binary files /dev/null and b/labs/cache_lab/tracegen differ diff --git a/labs/cache_lab/tracegen.c b/labs/cache_lab/tracegen.c new file mode 100644 index 0000000..33d3d21 --- /dev/null +++ b/labs/cache_lab/tracegen.c @@ -0,0 +1,107 @@ +/* + * tracegen.c - Running the binary tracegen with valgrind produces + * a memory trace of all of the registered transpose functions. + * + * The beginning and end of each registered transpose function's trace + * is indicated by reading from "marker" addresses. These two marker + * addresses are recorded in file for later use. + */ + +#include +#include +#include +#include +#include +#include "cachelab.h" +#include + +/* External variables declared in cachelab.c */ +extern trans_func_t func_list[MAX_TRANS_FUNCS]; +extern int func_counter; + +/* External function from trans.c */ +extern void registerFunctions(); + +/* Markers used to bound trace regions of interest */ +volatile char MARKER_START, MARKER_END; + +static int A[256][256]; +static int B[256][256]; +static int M; +static int N; + + +int validate(int fn,int M, int N, int A[N][M], int B[M][N]) { + int C[M][N]; + memset(C,0,sizeof(C)); + correctTrans(M,N,A,C); + for(int i=0;i +#include "cachelab.h" + +int is_transpose(int M, int N, int A[N][M], int B[M][N]); + +/* + * transpose_submit - This is the solution transpose function that you + * will be graded on for Part B of the assignment. Do not change + * the description string "Transpose submission", as the driver + * searches for that string to identify the transpose function to + * be graded. + */ +char transpose_submit_desc[] = "Transpose submission"; +void transpose_submit(int M, int N, int A[N][M], int B[M][N]) +{ +} + +/* + * You can define additional transpose functions below. We've defined + * a simple one below to help you get started. + */ + +/* + * trans - A simple baseline transpose function, not optimized for the cache. + */ +char trans_desc[] = "Simple row-wise scan transpose"; +void trans(int M, int N, int A[N][M], int B[M][N]) +{ + int i, j, tmp; + + for (i = 0; i < N; i++) { + for (j = 0; j < M; j++) { + tmp = A[i][j]; + B[j][i] = tmp; + } + } + +} + +/* + * registerFunctions - This function registers your transpose + * functions with the driver. At runtime, the driver will + * evaluate each of the registered functions and summarize their + * performance. This is a handy way to experiment with different + * transpose strategies. + */ +void registerFunctions() +{ + /* Register your solution function */ + registerTransFunction(transpose_submit, transpose_submit_desc); + + /* Register any additional transpose functions */ + registerTransFunction(trans, trans_desc); + +} + +/* + * is_transpose - This helper function checks if B is the transpose of + * A. You can check the correctness of your transpose by calling + * it before returning from the transpose function. + */ +int is_transpose(int M, int N, int A[N][M], int B[M][N]) +{ + int i, j; + + for (i = 0; i < N; i++) { + for (j = 0; j < M; ++j) { + if (A[i][j] != B[j][i]) { + return 0; + } + } + } + return 1; +} + diff --git a/labs/cache_lab/trans.o b/labs/cache_lab/trans.o new file mode 100644 index 0000000..cd3674c Binary files /dev/null and b/labs/cache_lab/trans.o differ diff --git a/labs/data_lab/Driverhdrs.pm b/labs/data_lab/Driverhdrs.pm new file mode 100644 index 0000000..ecf5e2a --- /dev/null +++ b/labs/data_lab/Driverhdrs.pm @@ -0,0 +1,12 @@ +# +# This file contains configuration variables for drivers. +# It was generated by genhdrs.pl. Do not modify it. +# +package Driverhdrs; + +$LAB = "datalab"; +$SERVER_NAME = "changeme.ics.cs.cmu.edu"; +$SERVER_PORT = 8081; +$COURSE_NAME = "csapp"; +$AUTOGRADE_TIMEOUT = 0; +1; diff --git a/labs/data_lab/Driverlib.pm b/labs/data_lab/Driverlib.pm new file mode 100644 index 0000000..d7f7da1 --- /dev/null +++ b/labs/data_lab/Driverlib.pm @@ -0,0 +1,138 @@ +############################################################### +# Driverlib.pm - A package of helper functions for Perl drivers +# +# Copyright (c) 2005 David R. O'Hallaron, All rights reserved. +############################################################### + +package Driverlib; + +use Socket; + +# Autogenerated header file with lab-specific constants +use lib "."; +use Driverhdrs; + +require Exporter; +@ISA = qw(Exporter); +@EXPORT = qw( + driver_post + ); + +use strict; + +##### +# Public functions +# + +# +# driver_post - This is the routine that a driver calls when +# it needs to transmit an autoresult string to the result server. +# +sub driver_post ($$) { + my $userid = shift; # User id for this submission + my $result = shift; # Autoresult string + my $autograded = shift; # Set if called by an autograder + + # Echo the autoresult string to stdout if the driver was called + # by an autograder + if ($autograded) { + print "\n"; + print "AUTORESULT_STRING=$result\n"; + return; + } + + # If the driver was called with a specific userid, then submit + # the autoresult string to the result server over the Internet. + if ($userid) { + my $status = submitr($Driverhdrs::SERVER_NAME, + $Driverhdrs::SERVER_PORT, + $Driverhdrs::COURSE_NAME, + $userid, + $Driverhdrs::LAB, + $result); + + # Print the status of the transfer + if (!($status =~ /OK/)) { + print "$status\n"; + print "Did not send autoresult string to the result server.\n"; + exit(1); + } + print "Success: Sent autoresult string for $userid to the result server.\n"; + } +} + + +##### +# Private functions +# + +# +# submitr - Sends an autoresult string to the result server +# +sub submitr ($$$$$$) { + my $hostname = shift; + my $port = shift; + my $course = shift; + my $userid = shift; + my $lab = shift; + my $result = shift; + + my $internet_addr; + my $enc_result; + my $paddr; + my $line; + my $http_version; + my $errcode; + my $errmsg; + + # Establish the connection to the server + socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); + $internet_addr = inet_aton($hostname) + or die "Could not convert $hostname to an internet address: $!\n"; + $paddr = sockaddr_in($port, $internet_addr); + connect(SERVER, $paddr) + or die "Could not connect to $hostname:$port:$!\n"; + + select((select(SERVER), $| = 1)[0]); # enable command buffering + + # Send HTTP request to server + $enc_result = url_encode($result); + print SERVER "GET /$course/submitr.pl/?userid=$userid&lab=$lab&result=$enc_result&submit=submit HTTP/1.0\r\n\r\n"; + + # Get first HTTP response line + $line = ; + chomp($line); + ($http_version, $errcode, $errmsg) = split(/\s+/, $line); + if ($errcode != 200) { + return "Error: HTTP request failed with error $errcode: $errmsg"; + } + + # Read the remaining HTTP response header lines + while ($line = ) { + if ($line =~ /^\r\n/) { + last; + } + } + + # Read and return the response from the result server + $line = ; + chomp($line); + + close SERVER; + return $line; + +} + +# +# url_encode - Encode text string so it can be included in URI of GET request +# +sub url_encode ($) { + my $value = shift; + + $value =~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg; + return $value; +} + +# Always end a module with a 1 so that it returns TRUE +1; + diff --git a/labs/data_lab/Makefile b/labs/data_lab/Makefile new file mode 100644 index 0000000..1ef6fcf --- /dev/null +++ b/labs/data_lab/Makefile @@ -0,0 +1,26 @@ +# +# Makefile that builds btest and other helper programs for the CS:APP data lab +# +CC = gcc +CFLAGS = -O -Wall -m32 +LIBS = -lm + +all: btest fshow ishow + +btest: btest.c bits.c decl.c tests.c btest.h bits.h + $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c + +fshow: fshow.c + $(CC) $(CFLAGS) -o fshow fshow.c + +ishow: ishow.c + $(CC) $(CFLAGS) -o ishow ishow.c + +# Forces a recompile. Used by the driver program. +btestexplicit: + $(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c + +clean: + rm -f *.o btest fshow ishow *~ + + diff --git a/labs/data_lab/README b/labs/data_lab/README new file mode 100644 index 0000000..e73d37f --- /dev/null +++ b/labs/data_lab/README @@ -0,0 +1,140 @@ +*********************** +The CS:APP Data Lab +Directions to Students +*********************** + +Your goal is to modify your copy of bits.c so that it passes all the +tests in btest without violating any of the coding guidelines. + + +********* +0. Files: +********* + +Makefile - Makes btest, fshow, and ishow +README - This file +bits.c - The file you will be modifying and handing in +bits.h - Header file +btest.c - The main btest program + btest.h - Used to build btest + decl.c - Used to build btest + tests.c - Used to build btest + tests-header.c- Used to build btest +dlc* - Rule checking compiler binary (data lab compiler) +driver.pl* - Driver program that uses btest and dlc to autograde bits.c +Driverhdrs.pm - Header file for optional "Beat the Prof" contest +fshow.c - Utility for examining floating-point representations +ishow.c - Utility for examining integer representations + +*********************************************************** +1. Modifying bits.c and checking it for compliance with dlc +*********************************************************** + +IMPORTANT: Carefully read the instructions in the bits.c file before +you start. These give the coding rules that you will need to follow if +you want full credit. + +Use the dlc compiler (./dlc) to automatically check your version of +bits.c for compliance with the coding guidelines: + + unix> ./dlc bits.c + +dlc returns silently if there are no problems with your code. +Otherwise it prints messages that flag any problems. Running dlc with +the -e switch: + + unix> ./dlc -e bits.c + +causes dlc to print counts of the number of operators used by each function. + +Once you have a legal solution, you can test it for correctness using +the ./btest program. + +********************* +2. Testing with btest +********************* + +The Makefile in this directory compiles your version of bits.c with +additional code to create a program (or test harness) named btest. + +To compile and run the btest program, type: + + unix> make btest + unix> ./btest [optional cmd line args] + +You will need to recompile btest each time you change your bits.c +program. When moving from one platform to another, you will want to +get rid of the old version of btest and generate a new one. Use the +commands: + + unix> make clean + unix> make btest + +Btest tests your code for correctness by running millions of test +cases on each function. It tests wide swaths around well known corner +cases such as Tmin and zero for integer puzzles, and zero, inf, and +the boundary between denormalized and normalized numbers for floating +point puzzles. When btest detects an error in one of your functions, +it prints out the test that failed, the incorrect result, and the +expected result, and then terminates the testing for that function. + +Here are the command line options for btest: + + unix> ./btest -h + Usage: ./btest [-hg] [-r ] [-f [-1|-2|-3 ]*] [-T