171 lines
4.6 KiB
C
171 lines
4.6 KiB
C
|
|
/*
|
||
|
|
* CS 261: Main driver
|
||
|
|
*
|
||
|
|
* Name: Nicholas Tamassia
|
||
|
|
*
|
||
|
|
* This code was developed in compliance with the JMU Honor code.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "p1-check.h"
|
||
|
|
#include "p2-load.h"
|
||
|
|
#include "p3-disas.h"
|
||
|
|
|
||
|
|
/*
|
||
|
|
* helper function for printing help text
|
||
|
|
*/
|
||
|
|
void usage(char **argv) {
|
||
|
|
printf("Usage: %s <option(s)> mini-elf-file\n", argv[0]);
|
||
|
|
printf(" Options are:\n");
|
||
|
|
printf(" -h Display usage\n");
|
||
|
|
printf(" -H Show the Mini-ELF header\n");
|
||
|
|
printf(" -a Show all with brief memory\n");
|
||
|
|
printf(" -f Show all with full memory\n");
|
||
|
|
printf(" -s Show the program headers\n");
|
||
|
|
printf(" -m Show the memory contents (brief)\n");
|
||
|
|
printf(" -M Show the memory contents (full)\n");
|
||
|
|
printf(" -d Disassemble code contents\n");
|
||
|
|
printf(" -D Disassemble data contents\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
void exit_file_error(FILE *file) {
|
||
|
|
if (file) {
|
||
|
|
fclose(file);
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("Failed to read file\n");
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char **argv) {
|
||
|
|
int c;
|
||
|
|
bool show_elf_header = false;
|
||
|
|
bool show_program_header = false;
|
||
|
|
bool show_memory_brief = false;
|
||
|
|
bool show_memory_full = false;
|
||
|
|
bool show_code = false;
|
||
|
|
bool show_data = false;
|
||
|
|
|
||
|
|
while ((c = getopt(argc, argv, "hHafsmMdD")) != -1) {
|
||
|
|
switch (c) {
|
||
|
|
case 'h':
|
||
|
|
usage(argv);
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
case 'H':
|
||
|
|
show_elf_header = true;
|
||
|
|
break;
|
||
|
|
case 'a':
|
||
|
|
show_elf_header = true;
|
||
|
|
show_program_header = true;
|
||
|
|
show_memory_brief = true;
|
||
|
|
break;
|
||
|
|
case 'f':
|
||
|
|
show_elf_header = true;
|
||
|
|
show_program_header = true;
|
||
|
|
show_memory_full = true;
|
||
|
|
break;
|
||
|
|
case 's':
|
||
|
|
show_program_header = true;
|
||
|
|
break;
|
||
|
|
case 'm':
|
||
|
|
show_memory_brief = true;
|
||
|
|
break;
|
||
|
|
case 'M':
|
||
|
|
show_memory_full = true;
|
||
|
|
break;
|
||
|
|
case 'd':
|
||
|
|
show_code = true;
|
||
|
|
break;
|
||
|
|
case 'D':
|
||
|
|
show_data = true;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
usage(argv);
|
||
|
|
return EXIT_FAILURE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* File path was not the last argument */
|
||
|
|
bool invalid_arguments = optind != argc - 1;
|
||
|
|
/* Attempted to ask for brief and full memory at same time */
|
||
|
|
bool memory_flag_conflict = show_memory_brief && show_memory_full;
|
||
|
|
|
||
|
|
if (invalid_arguments || memory_flag_conflict) {
|
||
|
|
usage(argv);
|
||
|
|
return EXIT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
elf_hdr_t header = {0};
|
||
|
|
FILE *header_file = fopen(argv[optind], "r");
|
||
|
|
|
||
|
|
/* Read contents of header_file into header */
|
||
|
|
if (!read_header(header_file, &header)) {
|
||
|
|
exit_file_error(header_file);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (show_elf_header) {
|
||
|
|
dump_header(&header);
|
||
|
|
}
|
||
|
|
|
||
|
|
elf_phdr_t phdrs[header.e_num_phdr];
|
||
|
|
memset(phdrs, 0, sizeof(phdrs));
|
||
|
|
|
||
|
|
/* Read program headers into phdrs array */
|
||
|
|
for (int i = 0; i < header.e_num_phdr; i++) {
|
||
|
|
uint16_t offset = header.e_phdr_start + i * sizeof(elf_phdr_t);
|
||
|
|
if (!read_phdr(header_file, offset, &phdrs[i])) {
|
||
|
|
exit_file_error(header_file);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (show_program_header) {
|
||
|
|
dump_phdrs(header.e_num_phdr, phdrs);
|
||
|
|
}
|
||
|
|
|
||
|
|
byte_t memory[MEMSIZE];
|
||
|
|
memset(memory, 0, MEMSIZE);
|
||
|
|
|
||
|
|
/* Read memory segments into memory array */
|
||
|
|
for (int i = 0; i < header.e_num_phdr; i++) {
|
||
|
|
if (!load_segment(header_file, memory, &phdrs[i])) {
|
||
|
|
exit_file_error(header_file);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fclose(header_file);
|
||
|
|
|
||
|
|
if (show_memory_brief) {
|
||
|
|
for (int i = 0; i < header.e_num_phdr; i++) {
|
||
|
|
uint32_t start = phdrs[i].p_vaddr;
|
||
|
|
uint32_t end = start + phdrs[i].p_size;
|
||
|
|
|
||
|
|
dump_memory(memory, start, end);
|
||
|
|
}
|
||
|
|
} else if (show_memory_full) {
|
||
|
|
dump_memory(memory, 0, MEMSIZE);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (show_code) {
|
||
|
|
printf("Disassembly of executable contents:\n");
|
||
|
|
|
||
|
|
for (int i = 0; i < header.e_num_phdr; i++) {
|
||
|
|
if (phdrs[i].p_type == CODE) {
|
||
|
|
disassemble_code(memory, &phdrs[i], &header);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (show_data) {
|
||
|
|
printf("Disassembly of data contents:\n");
|
||
|
|
|
||
|
|
for (int i = 0; i < header.e_num_phdr; i++) {
|
||
|
|
if (phdrs[i].p_type == DATA && phdrs[i].p_flags == 4) {
|
||
|
|
disassemble_rodata(memory, &phdrs[i]);
|
||
|
|
} else if (phdrs[i].p_type == DATA) {
|
||
|
|
disassemble_data(memory, &phdrs[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return EXIT_SUCCESS;
|
||
|
|
}
|