Files
CS261-Computer-Systems-I/p3-disas/main.c
2025-10-06 00:14:04 -04:00

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