CODE IN C,loader project Background: When you compile a program it produces an OBJECT file. A number of these object files (along with library files) are combined into an EXECUTABLE file by the...

CODE IN C,loader project

Background:


When you compile a program it produces an OBJECT file. A number of these object files (along with library files) are combined into an EXECUTABLE file by the LINKER. It is the linker’s responsibility to combine the objects and resolve as many references as possible and produce an executable format file. The LOADER Is responsible for converting the executable image on disk to a runnable process in memory. This involves the relocation of the program to its starting point in memory as well as any dynamic linking and loading.

Task:

Write a loader that can actually load a Linux executable file and execute it. This will require understanding the executable file format. Use the Hexdump program provided as part of the File System project as the program to load and run. Hint: look a mprotect, and mmap for allocating the memory needed. You will execute it under your own process (no need to fork).

Requirements:

This project must be coded in C, be well documented, and code segments copied must be attributed and must not be complete components of the project. Your program must allocate the memory for and jump to executing the loaded program (don’t forget the arguments). In addition to your source code file, include a short writeup on what you did and how you did it, include diagrams where appropriate.




/**************************************************************************** *hexdump - a program to display a file in hexadecimal and ascii *Such as: *000020: 19 00 00 00 48 00 00 00 5F 5F 50 41 47 45 5A 45 | ....H...__PAGEZE * * Author:Robert Bierman *Date:March 28, 2020 *Source:hexdump.c * * Primary Purpose: *Written as a utility for CSC-415 Operating Systems, File System project * to allow the dumping of the "drive" file for verification of proper * structure and content. * * copyright 2020 Robert Bierman ****************************************************************************/ // Compilation:gcc hexdump.c -o hexdump #include #include #include #include #include #include #include #ifndef uint64_t typedef u_int64_t uint64_t; #endif #ifndef uint32_t typedef u_int32_t uint32_t; #endif #define BUFSIZE 4096//amount read at one time #define BLOCKSIZE 256// number of bytes printed before a blank line #define LBABLOCKSIZE512// display blocks from command line are based on 512 bytes #define VERSION "1.0"// Version // This procedure takes a file name, a starting block and a number of blocks and dumps the // file to stdout. // Output (including the number of blocks) is limited by the length of the file and // partial blocks are counted as a whole block for the header showing how many blocks are // being displayed. // // Checks are done to ensure that blanks are displayed on the last line of the output // if the file only partially uses the last 16 bytes. int processFile (char * filename, uint64_t startBlock, uint64_t numBlocks) { int readbytes; int position = 0; int loops = BUFSIZE / BLOCKSIZE;//number of loops of blocks within one buffer read int offset; int k; uint32_t lbaBlockSize = LBABLOCKSIZE; uint64_t numBytesToStartBlock; uint64_t numBytesToProcess; uint64_t endOfFile; numBytesToProcess = numBlocks * lbaBlockSize; numBytesToStartBlock = startBlock * lbaBlockSize; int fd = open (filename, O_RDONLY);//open the file // Error opening file (common if they don't enter a valid file name) if (fd == -1) { printf ("ERROR: failed to open file '%s'\n", filename); return -2; } endOfFile = lseek(fd, 0, SEEK_END); //will reset seek below if (numBytesToProcess == 0) { numBytesToProcess = endOfFile; //reset numBlocks for the header here numBlocks = ((numBytesToProcess + lbaBlockSize) - 1) / lbaBlockSize; numBlocks = numBlocks - startBlock; } unsigned char * buf = malloc (BUFSIZE);//Allocate the read buffer // Very rare error - something bad if I can not allocate a small buffer if (buf == NULL) { close (fd); printf ("Failed to allocate buffer\n"); return -3; } //Position to the startBlock lseek (fd, numBytesToStartBlock, SEEK_SET); position = numBytesToStartBlock; if (position > endOfFile)//can not start past the end of the filename { printf ("Can not dump file %s, starting at block %llu, past the end of the file.\n\n", filename, (unsigned long long)startBlock); return (-5); } // calculate max blocks we can display from the given start point uint64_t maxBlocks = (((endOfFile - position) + lbaBlockSize) - 1) / lbaBlockSize; if (numBlocks > maxBlocks) numBlocks = maxBlocks; //Proces the file - the do loop goes until we read less bytes than the BUFSIZE printf ("Dumping file %s, starting at block %llu for %llu block%c:\n\n", filename, (unsigned long long)startBlock, (unsigned long long)numBlocks, numBlocks != 1?'s':'\0'); do { if (position >= (numBytesToStartBlock + numBytesToProcess)) goto cleanup; readbytes = read (fd, buf, BUFSIZE);//Read one block offset = 0;//set our offset within the block for (int i = 0; i < loops;="" i++)="" loop="" for="" each="" "block"="" within="" one="" buffer="" read="" {="" for="" (int="" j="0;" j="">< blocksize/16;="" j++)="" loop="" j="" lines="" for="" each="" block="" {="" if="" (position+offset="">= (numBytesToStartBlock + numBytesToProcess)) goto cleanup; // Handle if we are at the end of the file and the line will have less // than 16 bytes associated with it. if (offset + 16 > readbytes) { printf ("%06X: ", offset+position); for (k = 0; k < readbytes="" -="" offset;="" k++)="" {="" printf="" ("%02x="" ",="" buf[offset="" +="" k]);="" }="" for="" (;k="">< 16;="" k++)="" {="" printf="" ("="" ");="" print="" remaining="" of="" the="" hex="" output="" as="" blanks="" to="" fill="" out="" the="" line="" }="" printf="" ("="" |="" ");="" for="" (k="0;" k="">< readbytes="" -="" offset;="" k++)="" {="" printf="" ("%c",="" buf[offset="" +="" k]="">< 32?'.':buf[offset+k]);="" }="" printf("\n");="" }="" else="" {="" if="" a="" full="" line,="" do="" one="" print="" for="" the="" full="" line="" printf="" ("%06x:="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" %02x="" |="" %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",="" offset+position,="" buf[offset="" +="" 0],buf[offset="" +="" 1],buf[offset="" +="" 2],buf[offset="" +="" 3],="" buf[offset="" +="" 4],buf[offset="" +="" 5],buf[offset="" +="" 6],buf[offset="" +="" 7],="" buf[offset="" +="" 8],buf[offset="" +="" 9],buf[offset="" +="" 10],buf[offset="" +="" 11],="" buf[offset="" +="" 12],buf[offset="" +="" 13],buf[offset="" +="" 14],buf[offset="" +="" 15],="" buf[offset="" +="" 0]="">< 32?'.':buf[offset="" +="" 0],="" buf[offset="" +="" 1]="">< 32?'.':buf[offset="" +="" 1],="" buf[offset="" +="" 2]="">< 32?'.':buf[offset="" +="" 2],="" buf[offset="" +="" 3]="">< 32?'.':buf[offset="" +="" 3],="" buf[offset="" +="" 4]="">< 32?'.':buf[offset="" +="" 4],="" buf[offset="" +="" 5]="">< 32?'.':buf[offset="" +="" 5],="" buf[offset="" +="" 6]="">< 32?'.':buf[offset="" +="" 6],="" buf[offset="" +="" 7]="">< 32?'.':buf[offset="" +="" 7],="" buf[offset="" +="" 8]="">< 32?'.':buf[offset="" +="" 8],="" buf[offset="" +="" 9]="">< 32?'.':buf[offset="" +="" 9],="" buf[offset="" +="" 10]="">< 32?'.':buf[offset="" +="" 10],="" buf[offset="" +="" 11]="">< 32?'.':buf[offset="" +="" 11],="" buf[offset="" +="" 12]="">< 32?'.':buf[offset="" +="" 12],="" buf[offset="" +="" 13]="">< 32?'.':buf[offset="" +="" 13],="" buf[offset="" +="" 14]="">< 32?'.':buf[offset="" +="" 14],="" buf[offset="" +="" 15]="">< 32?'.':buf[offset="" +="" 15]);="" }="" up="" the="" offset="" by="" 16="" for="" the="" next="" line="" offset="offset" +="" 16;="" if="" greater="" than="" the="" readbytes="" we="" have="" exhausted="" this="" buffer="" if="" (offset="">= readbytes) break; } //print a blank line between each BLOCK printf("\n"); //if greater than the readbytes we have exhausted this buffer if (offset >= readbytes) break; } //Next buffer, increment the overall position within the file. position = position + readbytes; // If we read the number of bytes requested (BUFSIZE), then we have not hit // the end of file yet, and should try to read more. } while (readbytes == BUFSIZE); cleanup: // clean up free (buf); close (fd); return 0; } // processArguments handles the command line using getopt_long to parse the argv array // // It then sets variable and or dispatches the action necessary based on the parameters. // it handles the multiple calls to processFile by iterating on uncontained parameters int processArguments (int argc, char * argv[]) { int c; int digit_optind = 0; uint64_t count, start; count = 0; start = 0; int retval; char * filename = NULL; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"count",required_argument, 0, 'c'}, //forces to c {"start",required_argument, 0, 's'}, //forces to s {"help",no_argument, 0, 'h'}, {"version",no_argument, 0, 'v'}, {"file",required_argument, 0, 'f'}, {0,0, 0, 0 } }; c = getopt_long(argc, argv, "c:s:f:vh", long_options, &option_index); if (c == -1) break; switch (c) { case 0://It is a long option (all converted so should be none) printf("Unknown option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); exit (-1); case 'c': count = atol(optarg); break; case 's': start = atol(optarg); break; case 'f': filename = optarg; break; case 'h': printf ("USAGE: hexdump --file [--count num512ByteBlocks] [--start start512ByteBlock] [--help] [--version]\n"); exit (0); case 'v': printf("hexdump - Version %s; copyright 2020 Robert Bierman\n\n", VERSION); exit (0); case '?': break; default: printf("Unknown option returned character code 0%o ??\n", c); exit (-1); } } //if a file name is already specified - process it if (filename != NULL) { retval = processFile (filename, start, count); if (retval != 0) return (retval); } //additional files (same arguments) if (optind < argc)="" {="" while="" (optind="">< argc)="" {="" retval="processFile" (argv[optind++],="" start,="" count);="" if="" (retval="" !="0)" return="" (retval);="" }="" }="" return="" 0;="" }="" main="" calls="" process="" arguments="" which="" in="" turn="" calls="" process="" file.="" int="" main="" (int="" argc,="" char="" *="" argv[])="" {="" return="" (processarguments="" (argc,="" argv));="" }="" #include=""> #include #include #include #include #include #include #include #include #include #include #include "fsLow.h" int main (int argc, char *argv[]) { char * filename; uint64_t volumeSize; uint64_t blockSize; int retVal; if (argc > 3) { filename = argv[1]; volumeSize = atoll (argv[2]); blockSize = atoll (argv[3]); } retVal = startPartitionSystem (filename, &volumeSize, &blockSize); printf("Opened %s, Volume Size: %llu; BlockSize: %llu; Return %d\n", filename, (ull_t)volumeSize, (ull_t)blockSize, retVal); char * buf = malloc(blockSize *2); char * buf2 = malloc(blockSize *2); memset (buf, 0, blockSize*2); strcpy (buf, "Now is the time for all good people to come to the aid of their countrymen\n"); strcpy (&buf[blockSize+10], "Four score and seven years ago our fathers brought forth onto this continent a new nation\n"); LBAwrite (buf, 2, 0); LBAwrite (buf, 2, 3); LBAread (buf2, 2, 0); if (memcmp(buf, buf2, blockSize*2)==0) { printf("Read/Write worked\n"); } else printf("FAILURE on Write/Read\n"); free (buf); free(buf2); closePartitionSystem(); return 0; } #include #include #include #include #include #include #include #include #include #include #include #include "fsLow.h" typedef struct partitionInfo { char volumePrefix[sizeof(PART_CAPTION)+2]; uint64_tsignature; uint64_tvolumesize; uint64_tblocksize; uint64_tnumberOfBlocks; char * filename;//Never written - always assigned on start intfd;//Never Written - file descriptor uint64_tsignature2; charvolumeName[]; } partitionInfo_t, * partitionInfo_p; partitionInfo_p partInfop = NULL; int initializePartition (int fd, uint64_t volSize, uint64_t blockSize) { ssize_t writeRet; partitionInfo_p buf = malloc (blockSize); if (buf == NULL) { //abort } strcpy(buf->volumePrefix, PART_CAPTION); buf->signature = PART_SIGNATURE; buf->volumesize = volSize; buf->blocksize = blockSize; buf->numberOfBlocks = volSize / blockSize; buf->signature2 = PART_SIGNATURE2; strcpy(buf->volumeName, "Untitled\n\n"); lseek(fd, 0 , SEEK_SET); writeRet = write(fd, buf, blockSize); if (writeRet != blockSize) { //process error } fsync(fd); uint64_t blkCount = buf->numberOfBlocks; memset (buf, 0, blockSize); //Write one block at the end of the volume to allocate the space lseek (fd, volSize, SEEK_SET); writeRet = write(fd, buf, blockSize); fsync(fd); printf("Created a volume with %llu bytes, broken into %llu blocks of
May 16, 2021
SOLUTION.PDF

Get Answer To This Question

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here