#include #include #include #define SWAP_ENDIAN_16BIT(num) (((num&0xff00)>>8)|((num&0x00ff)<<8)) #define SWAP_ENDIAN_32BIT(num) (((num&0xff000000)>>24)|((num&0x00ff0000)>>8)|((num&0x0000ff00)<<8)|((num&0x000000ff)<<24)) #define ELF_HEADER_SIZE 52 #define DOL_HEADER_SIZE 256 #define SECTION_SIZE 32 #define BSS_SECTION_SIZE 32 #define TEXT_OFFSET_OFFSET 4 // TEXT_ADDRESS_OFFSET always immediately follows this entry #define TEXT_SIZE_OFFSET 16 #define BSS_ADDRESS_OFFSET 8 #define BSS_SIZE_OFFSET 20 #define DATA_OFFSET_OFFSET 4 // DATA_ADDRESS_OFFSET always immediately follows this entry #define DATA_SIZE_OFFSET 16 typedef struct { unsigned long text_offset[7]; unsigned long data_offset[11]; unsigned long text_address[7]; unsigned long data_address[11]; unsigned long text_size[7]; unsigned long data_size[11]; unsigned long bss_address; unsigned long bss_size; unsigned long entry_point; } dol_header; int main (int argc, const char * argv[]) { FILE *dol_file, *elf_file; long dol_file_size; void *dol_buffer; dol_header dh; short f, num_text_sections=0, num_data_sections=0, total_sections=0, elf_header_size; static char elf_header[52] = {0x7f,0x45,0x4c,0x46,1,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0x14,0,0,0,1,0,0,0,0,0,0,0,0x34,0,0,0,0,0x80,0,0,0,0,0x34,0,0x20,0,0,0,0,0,0,0,0}; static char text_section[32] = {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,32}; static char data_section[32] = {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,32}; static char bss_section[32] = {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,32}; static char padding[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; static char prog_version[80] = "dol2elf v0.1 - cmonkey 2012\n\n"; if(argc != 3) { printf("%s", prog_version); printf("This program will convert a retail DOL file back into an ELF file\n"); printf("which will be compatible with makedol.exe\n\n"); printf("Usage : dol2elf \n"); return 0; } // try and open the DOL file. Exit if we can't open it. dol_file = fopen(argv[1], "rb"); if(!dol_file) { printf("Couldn't open DOL for reading. Check filename is correct\n"); return 0; } for(f=0;f<7;f++) fread(&dh.text_offset[f], 1, 4, dol_file); for(f=0;f<11;f++) fread(&dh.data_offset[f], 1, 4, dol_file); for(f=0;f<7;f++) fread(&dh.text_address[f], 1, 4, dol_file); for(f=0;f<11;f++) fread(&dh.data_address[f], 1, 4, dol_file); for(f=0;f<7;f++) fread(&dh.text_size[f], 1, 4, dol_file); for(f=0;f<11;f++) fread(&dh.data_size[f], 1, 4, dol_file); // get BSS address fread(&dh.bss_address, 1, 4, dol_file); // get BSS size fread(&dh.bss_size, 1, 4, dol_file); // get module entry point fread(&dh.entry_point, 1, 4, dol_file); // display details from DOL header printf("%s", prog_version); printf("BSS address:\t%08lX\nBSS size:\t%08lX\n\n", SWAP_ENDIAN_32BIT(dh.bss_address), SWAP_ENDIAN_32BIT(dh.bss_size)); printf("Entry point:\t%08lX\n\n", SWAP_ENDIAN_32BIT(dh.entry_point)); for(f=0;f<7;f++) { if(dh.text_offset[f] != 0 && dh.text_address[f] != 0 && dh.text_size[f] != 0) { printf("Text section %d: Offset=%08lX Address=%08lX Size=%08lX\n", f, SWAP_ENDIAN_32BIT(dh.text_offset[f]), SWAP_ENDIAN_32BIT(dh.text_address[f]), SWAP_ENDIAN_32BIT(dh.text_size[f])); num_text_sections++; } } printf("\n"); for(f=0;f<11;f++) { if(dh.data_offset[f] != 0 && dh.data_address[f] != 0 && dh.data_size[f] != 0) { printf("Data section %d: Offset=%08lX Address=%08lX Size=%08lX\n", f, SWAP_ENDIAN_32BIT(dh.data_offset[f]), SWAP_ENDIAN_32BIT(dh.data_address[f]), SWAP_ENDIAN_32BIT(dh.data_size[f])); num_data_sections++; } } total_sections = num_data_sections + num_text_sections + 1; // + 1 for BSS section printf("\nNumber of text sections: %d\n", num_text_sections); printf("Number of data sections: %d\n", num_data_sections); // calculate size of ELF header elf_header_size = 52 + (total_sections * SECTION_SIZE) + 12; // 52 bytes for ELF header + 12 bytes for padding printf("\nSize of ELF header will be %d bytes\n", elf_header_size); elf_file = fopen(argv[2],"wb"); if(!elf_file) { printf("Couldn't open ELF for writing. Check you have write access to the directory.\n"); fclose(dol_file); return 0; } // write the ELF header fwrite(&elf_header,1,52,elf_file); // insert the module entry point into the header fseek(elf_file,24,SEEK_SET); fwrite(&dh.entry_point,1,4,elf_file); // insert total number of program sections into the header fseek(elf_file,44,SEEK_SET); total_sections = SWAP_ENDIAN_16BIT(total_sections); fwrite(&total_sections,1,2,elf_file); total_sections = SWAP_ENDIAN_16BIT(total_sections); // move file pointer to end of ELF header fseek(elf_file, 52, SEEK_SET); // ELF header is 52 bytes long // write the text sections for(f=0;f