CS520
Spring 2018
Laboratory 5
Friday February 23
The lab must be submitted prior to 12noon on Sunday February 25.


The goal for this lab is to read a file and confirm that it is a 64-bit, little-endian ELF file containing RISC-V instructions. The file will be given as the only command-line argument to the program.

I recommend that to simplify the program you first open the file and read the whole program into a malloc-ed buffer. A simple way to do this is to read the file twice using getc. The first time you can discard the bytes that are read because you are just counting the number of bytes in the file. Once you know how long the file is, then malloc the buffer. And then read the file a second time into the buffer. (If you cannot open the file, print this error message to stderr on its own line, "cannot open", and follow it with the name of the file given on the command line.

Next you want to check the first 16 bytes in the file, which contains the identification information for the file. The first four bytes should contain the ELF "magic" numbers: 0x7F, 0x45, 0x4C and 0x46. If this check fails print the error message "Not an ELF" to stderr on its own line and exit the program.

Now check two more bytes of the identication information. The fifth byte should be 0x02, indicating that it is a 64-bit file. The sixth byte should be 0x01, indicating that it is a little endian file. For each of these checks that fail, print a specific error message to stderr. The error messages should be of the following form: "Not a 64-bit file", or "Not in little endian". These errors should be printed on their own line. If either check fails, exit the program.

Now that you have confirmed that the file is a 64-bit, little-endian ELF file, check the rest of the ELF header. Here is a C struct that describes the ELF header:

typedef struct {
  uint8_t  e_ident[16];
  uint16_t e_type;
  uint16_t e_machine;
  uint32_t e_version;
  uint64_t e_entry;
  uint64_t e_phoff;
  uint64_t e_shoff;
  uint32_t e_flags;
  uint16_t e_ehsize;
  uint16_t e_phentsize;
  uint16_t e_phnum;
  uint16_t e_shentsize;
  uint16_t e_shnum;
  uint16_t e_shstrndx;
} Elf64_Ehdr;
(Note that the identification information is the first 16 bytes in this struct.) Confirm that the e_type field is either 0x0001 or 0x0002, indicating a relocatable object file or an executable file. Confirm that the e_machine field is 0x00f3, indicating the RISC-V. For each of these checks that fail, print a specific error message to stderr. The error messages should be of the following form: "Not a relocatable object or an executable file", or "Not a RISC-V file". These errors should be printed on their own line. If either of these checks fail, exit the program.

The final step in the lab is to print the following values to stderr:

  1. the file length
  2. the value of the e_shoff field of the header
  3. the value of the e_shnum field of the header
  4. the value of the e_shstrndx field of the header
Print all these values in decimal on their own line with a label from the list above. For example: fprintf(stderr, "the file length is %d\n", fileLength);

Put all your source code in a single file, "disRISCV.c". (This is the beginning of your disassembler for Program 3.)

There will be a variety of test files in ~cs520/public/lab5. Some of them will be 64-bit ELF files and some will not be.

Turn in this laboratory by typing:

% ~cs520/bin/submit lab5 disRISCV.c

Submissions can be checked by typing:

% ~cs520/bin/scheck lab5

Remember that there are no late submissions of labs. Submit what you have prior to 12noon on Sunday February 25. Be careful: one minute late is late.


Last modified on January 19, 2018.

Comments and questions should be directed to pjh@cs.unh.edu