/* * 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 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; }