assembly | mining代做 | 代做shell | project作业 | lab作业 | oracle | 代做Operating Systems – CSCI 2021 project 5: Binary ELF and Functions

CSCI 2021 project 5: Binary ELF and Functions

assembly | mining代做 | 代做shell | project作业 | lab作业 | oracle | 代做Operating Systems – 该题目是一个常规的shell的练习题目代写, 涉及了assembly/mining/shell/IT/oracle/Operating Systems等代写方面, 这个项目是lab代写的代写题目

lab代写 代写lab

CSCI 2021 project 5: Binary ELF and Functions

CODE DISTRIBUTION: p5-code.zip

AUTOMATED TESTS: Not yet available

CHANGELOG: Empty

Table of Contents
  1. Overview
  2. Download Code and Setup
  3. loadfunc : Finding functions in ELF Files 3.1. ELF File References 3.2. Overall Approach 3.3. ELF Header and Section Header Array 3.4. String Tables, Names, Section Headers 3.5. The .text Section and its Address 3.6. Symbol Table and .strtab 3.7. Printing the Opcodes of the Function 3.8. Behavior in Error Cases 3.9. loadfunc Template 3.10. Grading Criteria for loadfunc 3.11. Automated Tests
  4. OPTIONAL: Engagement Points
  5. Project Submission 5.1. Submit to Gradescope 5.2. Late Policies
1 Overview

This project features a single problem pertaining to the most recent lecture topics, virtual memory and the ELF file format.

loadfunc uses mmap() to parse a binary ELF file to locate the binary opcodes associated with a function in the .text section. Tools that work with object files like the linker associated with the GCC and the program loader must perform similar though more involved tasks involving ELF files. mmap() is very useful for handling binary files and is demonstrated in lab 13.

2 Download Code and Setup

Download the code pack linked at the top of the page. Unzip this which will create a project folder. Create new files in this folder. Ultimately you will re-zip this folder to submit it.

File State Notes
Makefile Provided Build file to compile all programs
loadfunc.c COMPLETE Template to complete
test-input/somefuncs.o Data ELF object file for input to loadfunc
test-input/morefuncs.o Data Several other ELF and non-ELF files provided
test-results/ Testing Directory created by running the test script, it can be deleted safely
testy Testing Test running script
test_loadfunc.org Testing Tests associated with loadfunc Not yet released
3 loadfunc: Finding functions in ELF Files

The Executable and Linkable (ELF) File Format is the Unix standard for binary files with runnable code in them. By default, any executable or .o file produced by Unix compilers such as GCC produce ELF files as evidenced by the file command.

This problem explores the file format of ELF in order to print out the binary bytes associated with functions in the file. ELF files contain a Symbol Table that listed all publicly visible entities in the file. These symbols are for Functions and Global variables in a program. Information on Symbols are stored in the .symtab ELF section short for “Symbol Table”. The standard utility readelf shows human readable versions of ELF files and the -s option specifically prints out the symbol table section. Below is a session which shows the source code for provided program globals then uses readelf to show the symbol table associated with its compiled version.

> gcc -c code.c
> file code.o
code.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
> gcc program.c
> file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU
> cd test-input/
> file somefuncs.o
somefuncs.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), with debug_info, not stripped
> cat somefuncs.c
int return_five(){
return 5;
}
int global_int = 2;
int my_pow(int base, int exp){
int pow=1;
for(int i=0; i<exp; i++){

A number entries in the symbol table are omitted for clarity: only those associated with data in the program are shown.

Note the following about the symbol table.

Functions are identified with Type FUNC and have the following attributes:
Size corresponds to how many bytes the function's binary Opcodes occupy
Ndx is the ELF file section in which the function exists; in this case it is Section 13 which is likely the .text section
Value is the starting address of the function
Global Variables are identified with Type OBJECT
Size corresponds to how many bytes the global variable occupies.
String arrays have Size equal to their length, int globals have Size=4 and double globals have Size=
Ndx is the ELF file section in which the global variable's value is stored. In this case, all global variables are in Section 23 which is likely the .data section where initialized global
data is stored.
Value is the (approximate) virtual address of the global variable when a program is loaded into the memory; it relates to the (approximate) virtual address of where the ELF .data
section gets loaded when a program starts running

The goal of the problem is to construct a program called loadfunc which allows one to print out the binary bytes associated with a named function. Finding this data is a crucial step for linking, loading, and disassembling code such as what is done via the objdump utility. A demonstration of loadfunc is below which illustrates several aspects of the loadfunc.

1. It detects whether the file is a proper ELF file and bails out if not.
2. It locates the .text and .symtab sections of the ELF file and shows information on them.
3. It searches the symbol table for the function named on the command line.
4. It detects if the symbol is actually a function or something else and errors out if not a function.
5. If the function is found, it will print out all opcodes associated with the function.
pow *= base;
}
return pow;
}
char an_array[] = "abcde";
void triple(int *xp){
*xp = *xp * 3;
return;
}
> readelf -s somefuncs.o
Symbol table '.symtab' contains 18 entries:
Num: Value Size Type Bind Vis Ndx Name
...
13: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 return_five
14: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 global_int
15: 000000000000000b 53 FUNC GLOBAL DEFAULT 1 my_pow
16: 0000000000000004 6 OBJECT GLOBAL DEFAULT 2 an_array
17: 0000000000000040 29 FUNC GLOBAL DEFAULT 1 triple
>
> make loadfunc # build loadfunc
gcc -Wall -Werror -g -Og -o loadfunc loadfunc.c
> ./loadfunc # show usage for loadfunc
usage: ./loadfunc [-d] <file> <funcname>
> ./loadfunc test-input/somefuncs.o return_five # call loadfunc on object file, find function 'return_five'
.text section # info on the .text section in the file
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section # info on the symbol table in the file
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘return_five’ # found symbol/function, show info
  • 13 symbol index
  • 0x0 value
  • 11 size
  • 1 section index
  • 0 offset in .text of start of function Bytes of function ‘return_five’ # iterate through printing function bytes 8 per line 0: 55 48 89 e5 b8 05 00 00 8: 00 5d c
> ./loadfunc test-input/gettysburg.txt return_five # run on a text file
ERROR: Magic bytes wrong, this is not an ELF file # can't parse as it isn't an ELF file
> ./loadfunc test-input/somefuncs.o not_there # look for a symbol that doesn't exist
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries ERROR: Function ‘not_there’ not found # reports symbol not found
> ./loadfunc test-input/somefuncs.o global_int # test on something that isn't a function
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries
3.1 ELF File References

It is recommended to do some reading on the structure of the ELF format as it will assist in coming to grips with this problem. As you encounter parts of the below walk-through of how to find and print the symbol table, refer to the following resources.

Diagrams shown below provide some information about the basics of what is provided in each portion of the file and how some of the records relate to each other.
Manual Pages: The manual page on ELF (found online or by typing man elf in any terminal) gives excellent coverage of the structs and values in the file format. Essentially the entire
format is covered here though there may be a few ambiguities.
Wikipedia: A good overview of the file format and has some extensive tables on the structs/values that comprise it.
 oracle Docs: A somewhat more detailed and hyper-linked version of the manual pages.

Note that we will use the 64-bit ELF format only which means most of the C types for variables should mention ELF64_xxx in them though use of 32-bit integers may still apply via uint32_t.

3.2 Overall Approach

ELF files are divided into sections. Our main interest is to identify the .symtab (Symbol Table) and .text (Executable Code) sections. This is done in several steps.

1. Parse the File Header to identify the positions of the Section Header Array and Section Header String Table
2. Search the Section Header Array and associated string table to find the sections named .symtab which is the symbol table, .strtab which contains the string names of the symbol table,
and .text which contains the binary  assembly code. Note the position in the file of these three sections.
3. Iterate through the Symbol Table section which is an array of structs. Use the fields present there along with the associated string names in .strtab to check each symbol for the symbol of
interest.
4. Once the symbol is found in .symtab, its value from .symtab is used to compute the offset within the .text section. This is where the function symbol's opcodes are stored.

Since this is a binary file with a considerable amount of jumping and casting to structs, it makes sense to use mmap() to map the entire file into virtual memory. It is a requirement to use mmap() for this problem. Refer to lecture notes, textbook, and lab materials for details on how to set up a memory map and clean it up once finished. In particular Lab 13 uses mmap() to parse binary files in a way that is directly relevant to the present program.

3.3 ELF Header and Section Header Array

The initial bytes in an ELF file always have a fixed structure which is the ELF64_Ehdr type. Of primary interest are the following

1. Identification bytes and types in the field e_ident[]. These initial bytes identify the file as ELF format or not. If they match the expected values, proceed. If incorrect, consult the later
section on Error Conditions on what error message to print.
2. The Section Header Array byte position in the field e_shoff. The Section Header Array is like a table of contents for a book giving positions of most other sections in the file. It usually
occurs near the end of the file.
3. The index of the Section Header String Table in field e_shstrndx. This integer gives an index into the Section Header Array where a string table can be found containing the names of
headers.

The following diagram shows the layout of these first few important parts of an ELF file.

Found Function 'global_int'
  • 14 symbol index
  • 0x0 value
  • 4 size
  • 2 section index # not the .text section so error out ERROR: ‘global_int’ in section 2, not in .text section 1
> ./loadfunc test-input/somefuncs.o my_pow # print info on another function in the file
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘my_pow’
  • 15 symbol index
  • 0xb value
  • 53 size
  • 1 section index
  • 11 offset in .text of start of function Bytes of function ‘my_pow’ 0: 55 48 89 e5 89 7d ec 89 8: 75 e8 c7 45 f8 01 00 00 10: 00 c7 45 fc 00 00 00 00 18: eb 0e 8b 45 f8 0f af 45 20: ec 89 45 f8 83 45 fc 01 28: 8b 45 fc 3b 45 e8 7c ea 30: 8b 45 f8 5d c
Figure 1: ELF File Header with Section Header Array and Section Header String Table.
3.4 String Tables, Names, Section Headers

To keep the sizes of structures fixed while still allowing variable length names for things, all the names that are stored in ELF files are in string tables. You can see one of these laid in the middle purple section of the diagram above starting at byte offset 1000. It is simply a sequence of multiple null-terminated strings laid out adjacent to one another in the file.

When a name is required, a field will give an offset into a specific string table. For example, each entry of the Section Header Array has an sh_name field which is an offset into the .shstrtab (the sh is for “section header”).. The offset indicates how far from the start of the string table to find the require name.

The .shstrtab section begins at byte 1000 so all name positions are 1000 + sh_name
The 0th .text section has sh_name = 0; the string .text\0 appears at position 1000.
The 1th .symtab section has sh_name = 6; the string .symtab\0 appears at byte position 1006.
The 4th .data section has sh_name = 32; the string .bss\0 appears at byte position 1032.

The Section Header Array is an array of Elf64_Shdr structs. By iterating over this array, fishing out the names from .shstrtab, and exa mining names using strcmp(), the positions for the two desired sections, .symtab and .strtab can be obtained via the associated sh_offset field.

Note that one will need to also determine length of the Section Header Array from the ELF File Header field e_shnum.

Also, on finding the Symbol Table section, note its size in bytes from the sh_size field. This will allow you to determine the number of symbol table entries.

3.5 The .text Section and its Address

In addition to identifying the .symtab and .strtab sections in the section header, identify and track the location of the .text section as this is where the opcodes for a function are stored. The .text section is copied directly into memory when a program is loaded. The section header struct field sh_addr is the requested location for some sections to be loaded. Often it is 0x0 for the .text section but not always. Record the value for sh_addr in your program as it is used to calculate the location of variable values from the symbol table.

Once the location of the .text section is located, print out some data about it in the following format.

3.6 Symbol Table and .strtab

Similar to the Section Header Array, the Symbol Table is comprised of an array of Elf64_Sym structs. Each of these structs has a st_name field giving an offset into the .symtab section where a symbol’s name resides. The following diagram shows this relationship.

.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x2000 preferred virtual address for .text
Figure 2: ELF Symbol Table, associated String Table, and locations of function symbols in .text section. The entry location of symbol my_pow is bolded along with the location of its name
"mypow" and location of its opcodes in the .text section.

Print out data on the symbol table in the format given below. Note that this data does not correspond to the diagram which is much simpler.

loadfunc will print the opcodes of one function described in the symbol table. To that end, one must iterate through the array of Symbol Table Elf64_Sym structs searching for the name of the symbol to be changed. In the above diagram, my_pow is of interest and is found midway through the table at index 15. On finding the requested symbol, print out data about it in the following format.

The st_size in this case corresponds to the number of bytes of opcodes associated with the function in the .text section.
The "value" in the st_value field is the preferred load address for the function though loaders/ Operating Systems often select other addresses for everything in the .text section.
The section index st_shndx field gives the ELF section in which this symbol is stored. In this case, it is section 1 which is the index of the .text section where opcodes are stored.
The location of my_pow's opcodes in the .text section is computed by calculating its address as an offset from the address of the .text section:
.text will load at 0x2000 in the output above
my_pow is at address 0x200b
The opcodes of my_pow is therefore offset 0x200b - 0x2000 = 0xb = 11 from the start of the .data section
Add 11 to the offset of .text from the beginning of the file (found in earlier when locating the .text section) to get the address of opcodes for my_pow

If the function symbol that is requested is not found in the symbol table, refer to the Error Conditions section for the appropriate error message to print.

3.7 Printing the Opcodes of the Function

Treat the address for the function opcodes above as though it were a char * array though many values will not be in the ASCII range. These are arbitrary bytes that are best printed in hexadecimal and we will favor printing them in columns of 8. The final required output of loadfunc looks like the following.

.symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries
Found Function 'my_pow'
  • 15 symbol index
  • 0x200b value
  • 53 size
  • 1 section index
  • 11 offset in .text of start of function
The left column is printed in decimal, 4 characters wide, right adjusted. Use a format specifier of %4d for this.
Each byte of the opcodes is printed in hexadecimal format with leading 0s in a space of 2 characters. Use a format specifier of %02hhx for this.
3.8 Behavior in Error Cases

The following errors can occur during execution of loadfunc and should result in the given error messages being printed.

Wrong Magic Bytes

loadfunc should check these “magic bytes” (first elements of e_ident[] in header). If they match the expected values, proceed but if they are incorrect, print the following example message

Missing Symbol Tables

During the search for the symbol table, it is possible that it is not found. Such objects are usually executables that have been “stripped” of a symbol table. After iterating through all sections in the Section Header array and finding that no entry has the .symtab name print the message in the example below.

Symbol Not Found

Any function name that is not found in the symbol table should result in the following final error message.

Symbol Not in .text Section

Some symbols are not in the .text section because they are not functions. For example OBJECT symbols like global_int are in the .data section so should not be treated as opcodes. In these cases, print out the section they are in as per the error message format below.

3.9 loadfunc Template

A basic template for loadfunc.c is provided in the code pack which outlines the structure of the code along with some printing formats to make the output match examples. Follow this outline closely to make sure that your code complies with tests when the become available.

3.10 Grading Criteria for loadfunc grading

Both binary and shell tests can be run with make test

Weight Criteria
Automated Tests
20 Passing automated tests run via make test, tests in test_loadfunc.org
Manual Inspection
5 Correctly sets up a memory map using open(), fstat(), mmap()
Creates a memory map of the requested file in read + write mode
Bytes of function 'my_pow'
0: 55 48 89 e5 89 7d ec 89
8: 75 e8 c7 45 f8 01 00 00
10: 00 c7 45 fc 00 00 00 00
18: eb 0e 8b 45 f8 0f af 45
20: ec 89 45 f8 83 45 fc 01
28: 8b 45 fc 3b 45 e8 7c ea
30: 8b 45 f8 5d c
> ./loadfunc test-input/gettysburg.txt return_five # run on a text file
ERROR: Magic bytes wrong, this is not an ELF file # can't parse as it isn't an ELF file
> ./loadfunc test-input/naked_globals main
ERROR: Couldn't find symbol table
> ./loadfunc test-input/somefuncs.o not_there # look for a symbol that doesn't exist
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries ERROR: Function ‘not_there’ not found # reports symbol not found
> ./loadfunc test-input/somefuncs.o global_int # test on something that isn't a function
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘global_int’
  • 14 symbol index
  • 0x0 value
  • 4 size
  • 2 section index # not the .text section so error out ERROR: ‘global_int’ in section 2, not in .text section 1
Weight Criteria
Correct unmap and close of file description at end of execution
5 Sets a pointer to the ELF File Header properly
Checks identifying bytes for sequence {0x7f,'E','L','F'}
Properly extracts the Section Header Array offset, length, string table index
5 Sets up pointers to Section Header Array and associate Section Header String Table
Loops over Section Header Array for sections named .symtab / .strtab / .text
Properly uses SH String Table to look at names of each section while searching
Extracts offsets and sizes of .symtab / .strtab / .text sections, location of the address for .text
5 Iterates over the symbol table to locate the named function symbol
Clear cases for finding the requested symbol or failure to find symbol in the table
Calculation done to find the position of a symbol value in the .text section
5 Properly iterates over opcodes associated with a function
Printing done using specified formats
5 Clean, readable code
Good indentation
Good selection of variable names
50 Problem Total
3.11 Automated Tests

Automated tests will be released in a few days. Instructions on what to expect from typing make test will be posted here after their release.

4 OPTIONAL: Engagement Points

One interesting aspect of dealing with functions in Binaries is that in some cases they can be run after being located. To arrange for this, several things need to be true.

1. The memory into which the function is loaded must be marked with Executable permission.
2. The types of the functions must be known (e.g. takes no arguments, returns an integer).
3. The functions must either use no global variables/other functions or be patched with addresses for these things.

It is not hard to arrange for the (1) and (2) above while (3) is much trickier.

To earn additional engagement points, execute the function that is identified when running loadfunc. Three examples from the somfuncs.o sample file are given here.

# runs return_five: takes no arguments and returns an int
> ./loadfunc test-input/somefuncs.o return_five "void->int"
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘return_five’
  • 13 symbol index
  • 0x0 value
  • 11 size
  • 1 section index
  • 0 offset in .text of start of function Bytes of function ‘return_five’ 0: 55 48 89 e5 b8 05 00 00 8: 00 5d c running void->int function returned: 5 # shows return value after running
# run my_pow: takes 2 integers, returns an integer
> ./loadfunc test-input/somefuncs.o my_pow "(int,int)->int" 2 10
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘my_pow’
  • 15 symbol index
  • 0xb value
  • 53 size
  • 1 section index
  • 11 offset in .text of start of function Bytes of function ‘my_pow’ 0: 55 48 89 e5 89 7d ec 89 8: 75 e8 c7 45 f8 01 00 00 10: 00 c7 45 fc 00 00 00 00 18: eb 0e 8b 45 f8 0f af 45 20: ec 89 45 f8 83 45 fc 01 28: 8b 45 fc 3b 45 e8 7c ea 30: 8b 45 f8 5d c running int,int->int function with arguments (2,10) returned: 1024 # shows return value after running

Below are some notes on how to complete this portion of the project.

Functions Must Be Executable

In order to execute instructions, they must have the “execute” (x) permission associated with the memory page on which they are loaded. This means requires that when you mmap() the file with the function opcodes in them, you must pass an option to make the mapped memory executable. Do some research such as through the manual page (man mmap) or on the internet to find such an option to pass to mmap().

Types of functions Supported

There are 3 types of functions that are supported. These are indicated on the command line via an option along some additional arguments to the loadfunc.

1. void->int: the funciton found takes no arguments and returns an integer. Call the function and print out its return value produce following output with X substituted for the return value.
2. (int,int)->int: the function found takes two integers and returns an integer. In this case 2 additional integer arguments are provided on the command line. Call the function with the 2
arguments and print its return value. Produce the following output with X,Y as the arguments provided on the command line and Z the return value of the function.
3. int*->void: the function takes a pointer to an integer and returns nothing but changes the integer pointed to. In this case 1 additional integer argument is provided on the command line. An
integer is set to this argument and its address is passed to the function. Print the following outpu with X substituted for the initial value for the argument and Y its value after calling the
function.

Set up a series of cases that check whether a 4th argument to loadfunc is present and if so, match it with one of the above types and take appropriate actions.

Casting to Functions

Printing out the opcodes as bytes is relatively easy: one calculates a pointer to its location and iterates over the bytes as an array. In contrast, if that location is to treated as a Function instead, then some tricky casting is required.

Consult the Tutorial on Function Pointers for the course to gain some insight on this. In that tutorial, one was commonly casting a function of one type to another as in

cmp_t compare_func = (cmp_t) intcmp;

where compare_func is a variable that points to a function and intcmp is an existing function with a slightly different type. The tutorial demonstrates the syntax on how to set up the cmp_t using a typdef to allow for this kind of casting.

This general approach can be used to caste arbitrary locations to a function type as well so that with the correct typedefs code like the following can be made to work:

Automated Tests for Engagement Points

When automated tests are released, there will be a separate set of tests that evaluate the correctness of the function running portion of the code which will earn up to 3 Engagement Points.

5 Project Submission
5.1 Submit to Gradescope
1. In a terminal, change to your project code directory and type make zip which will create a zip file of your code. A session should look like this:
# run triple: takes an integer pointer and returns nothing
> ./loadfunc test-input/somefuncs.o triple "int*->void" 33
.text section
  • 1 section index
  • 64 bytes offset from start of file
  • 0x0 preferred virtual address for .text .symtab section
  • 16 section index
  • 1072 bytes offset from start of file
  • 432 bytes total size
  • 24 bytes per entry
  • 18 entries Found Function ‘triple’
  • 17 symbol index
  • 0x40 value
  • 29 size
  • 1 section index
  • 64 offset in .text of start of function Bytes of function ‘triple’ 0: 55 48 89 e5 48 89 7d f 8: 48 8b 45 f8 8b 10 89 d 10: 01 c0 01 c2 48 8b 45 f 18: 89 10 90 5d c running int->void function, arg points to 33 arg is now: 99 # shows value poited to be int before/after function call
running void->int function
returned: X
running int,int->int function with arguments (X,Y)
returned: Z
running int*->void function, arg points to 33
arg is now: 99
char *funcaddr = ...;
...;
int_int_int_t func = (int_int_int_t) funcaddr;
...;
int ret = func(arg1,arg2);
2. Log into Gradescope and locate and click Project 5' which will open up submission
3. Click on the 'Drag and Drop' text which will open a file selection dialog; locate and choose your p5-code.zip file
4. This will show the contents of the Zip file and should include your C source files along with testing files and directories.
5. Click 'Upload' which will show progress uploading files. It may take a few seconds before this dialog closes to indicate that the upload is successful. Note: there is a limit of 256 files per
upload; normal submissions are not likely to have problems with this but you may want to make sure that nothing has gone wrong such as infinite loops creating many files or incredibly large
files.
6. Once files have successfully uploaded, the Autograder will begin running the command line tests and recording results. These are the same tests that are run via make test.
7. When the tests have completed, results will be displayed summarizing scores along with output for each batch of tests.
8. Refer to the Submission instructions for P1 for details and pictures.
5.2 Late Policies

You may wish to review the policy on late project submission which will cost you late tokens to submit late or credit if you run out of tokens. No projects will be accepted more than 48 hours after the deadline.

https://www-users.cs.umn.edu/~kauffman/2021/syllabus.html

Author: Chris Kauffman ([email protected]) Date: 2020-04-29 Wed 00:

> cd Desktop/2021/p5-code # location of project code
> ls
Makefile loadfunc.c test-input/
...
> make zip # create a zip file using Makefile target
rm -f p5-code.zip
cd .. && zip "p5-code/p5-code.zip" -r "p5-code"
adding: p5-code/ (stored 0%)
adding: p5-code/loadfunc.c (deflated 72%)
adding: p5-code/Makefile (deflated 59%)
...
Zip created in p5-code.zip
> ls p5-code.zip
p5-code.zip