1
0
mirror of https://github.com/zeldaret/oot.git synced 2024-09-21 04:24:43 +00:00

git subrepo pull (merge) tools/fado (#1501)

subrepo:
  subdir:   "tools/fado"
  merged:   "8d896ee97"
upstream:
  origin:   "git@github.com:EllipticEllipsis/fado.git"
  branch:   "master"
  commit:   "8d896ee97"
git-subrepo:
  version:  "0.4.5"
  origin:   "git@github.com:ingydotnet/git-subrepo.git"
  commit:   "dbb99be"
This commit is contained in:
Dragorn421 2023-02-26 20:04:00 +01:00 committed by GitHub
parent 9f0b7bb8a3
commit d4a6b21d46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 160 additions and 101 deletions

View File

@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = git@github.com:EllipticEllipsis/fado.git remote = git@github.com:EllipticEllipsis/fado.git
branch = master branch = master
commit = a0fa828089353ba48e378b281c23100c247b1c92 commit = 8d896ee97d565508755584803c409fc33bb0c953
parent = eadc477187888e1ae078d021b4a00b1366f0c9a4 parent = 9f09505d34619883748a7dab05071883281c14fd
method = merge method = merge
cmdver = 0.4.3 cmdver = 0.4.5

View File

@ -7,9 +7,9 @@ Contains
- **Fado** a program for generating the `.ovl`/relocation section for Zelda64 overlay files - **Fado** a program for generating the `.ovl`/relocation section for Zelda64 overlay files
- **Mido** an automatic dependency file generator - **Mido** an automatic dependency file generator
Compatible with both IDO and GCC (although [see below](N_B)). Compatible with both IDO and GCC (although [see below](N_B)). Both ordinary MIPS REL sections and RELA sections are now supported.
Format is the standard "Zelda64" .ovl section, with the relocs divided by section, as used by Output format is the standard "Zelda64" .ovl section, with the relocs divided by section, as used by
- *The Legend of Zelda: Ocarina of Time* (all Nintendo 64/Gamecube/iQue releases) - *The Legend of Zelda: Ocarina of Time* (all Nintendo 64/Gamecube/iQue releases)
- *The Legend of Zelda: Majora's Mask* (all Nintendo 64/Gamecube releases) - *The Legend of Zelda: Majora's Mask* (all Nintendo 64/Gamecube releases)

View File

@ -473,6 +473,14 @@ typedef struct {
Elf32_Word r_info; /* Relocation type and symbol index */ Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel; } Elf32_Rel;
/* Relocation table entry with addend (in section of type SHT_RELA). */
typedef struct {
Elf32_Addr r_offset; /* Address */
Elf32_Word r_info; /* Relocation type and symbol index */
Elf32_Sword r_addend; /* Addend */
} Elf32_Rela;
/* How to extract and insert information held in the r_info field. */ /* How to extract and insert information held in the r_info field. */
#define ELF32_R_SYM(val) ((val) >> 8) #define ELF32_R_SYM(val) ((val) >> 8)

View File

@ -105,7 +105,7 @@ bool Fairy_StartsWith(const char* string, const char* initial) {
FairyFileHeader* Fairy_ReadFileHeader(FairyFileHeader* header, FILE* file) { FairyFileHeader* Fairy_ReadFileHeader(FairyFileHeader* header, FILE* file) {
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
assert(fread(header, 0x34, 1, file) != 0); assert(fread(header, sizeof(char), 0x34, file) == 0x34);
if (!Fairy_VerifyMagic(header->e_ident)) { if (!Fairy_VerifyMagic(header->e_ident)) {
fprintf(stderr, "Not a valid ELF file.\n"); fprintf(stderr, "Not a valid ELF file.\n");
@ -150,7 +150,7 @@ FairySecHeader* Fairy_ReadSectionTable(FairySecHeader* sectionTable, FILE* file,
size_t tableSize = number * entrySize; size_t tableSize = number * entrySize;
fseek(file, tableOffset, SEEK_SET); fseek(file, tableOffset, SEEK_SET);
assert(fread(sectionTable, tableSize, 1, file) != 0); assert(fread(sectionTable, sizeof(char), tableSize, file) == tableSize);
/* Since the section table happens to only have entries of width 4, we can byteswap it by pretending it is a raw /* Since the section table happens to only have entries of width 4, we can byteswap it by pretending it is a raw
* uint32_t array */ * uint32_t array */
@ -165,13 +165,21 @@ FairySecHeader* Fairy_ReadSectionTable(FairySecHeader* sectionTable, FILE* file,
return sectionTable; return sectionTable;
} }
FairySym* Fairy_ReadSymbolTable(FairySym* symbolTable, FILE* file, size_t tableOffset, size_t tableSize) { size_t Fairy_ReadSymbolTable(FairySym** symbolTableOut, FILE* file, size_t tableOffset, size_t tableSize) {
size_t number = tableSize / sizeof(FairySym); size_t number = tableSize / sizeof(FairySym);
FairySym* symbolTable = malloc(tableSize);
fseek(file, tableOffset, SEEK_SET); *symbolTableOut = NULL;
assert(fread(symbolTable, tableSize, 1, file) != 0);
/* Reend the variables that are larger than bytes */ if (symbolTable == NULL) {
return 0;
}
if (fseek(file, tableOffset, SEEK_SET) != 0 || fread(symbolTable, sizeof(char), tableSize, file) != tableSize) {
free(symbolTable);
return 0;
}
/* Reend the variables that are wider than bytes */
{ {
size_t i; size_t i;
for (i = 0; i < number; i++) { for (i = 0; i < number; i++) {
@ -182,31 +190,65 @@ FairySym* Fairy_ReadSymbolTable(FairySym* symbolTable, FILE* file, size_t tableO
} }
} }
return symbolTable; *symbolTableOut = symbolTable;
return number;
} }
/* Can be used for both the section header string table and the strtab */ /* Can be used for both the section header string table and the strtab */
char* Fairy_ReadStringTable(char* stringTable, FILE* file, size_t tableOffset, size_t tableSize) { char* Fairy_ReadStringTable(char* stringTable, FILE* file, size_t tableOffset, size_t tableSize) {
fseek(file, tableOffset, SEEK_SET); fseek(file, tableOffset, SEEK_SET);
assert(fread(stringTable, tableSize, 1, file) != 0); assert(fread(stringTable, sizeof(char), tableSize, file) == tableSize);
return stringTable; return stringTable;
} }
/* offset and number are attained from the section table */ /* offset and number are attained from the section table, the returned pointer must be freed */
FairyRel* Fairy_ReadRelocs(FairyRel* relocTable, FILE* file, size_t offset, size_t size) { size_t Fairy_ReadRelocs(FairyRela** relocsOut, FILE* file, int type, size_t offset, size_t size) {
fseek(file, offset, SEEK_SET); /* Final size of the relocation table, relocations of type SHT_REL need more space for extra addend of 0 */
assert(fread(relocTable, size, 1, file) != 0); size_t finalSize = (type == SHT_REL) ? ((size * sizeof(FairyRela)) / sizeof(FairyRel)) : size;
void* readBuf = malloc(size);
FairyRela* relocTable = malloc(finalSize);
/* Reend the variables that are larger than bytes */ *relocsOut = NULL;
if (readBuf == NULL) {
return 0;
}
if (relocTable == NULL) {
free(readBuf);
return 0;
}
if (fseek(file, offset, SEEK_SET) != 0 || fread(readBuf, sizeof(char), size, file) != size) {
free(readBuf);
free(relocTable);
return 0;
}
/* Reend the variables that are wider than bytes */
{ {
size_t i; size_t i;
uint32_t* data = (uint32_t*)relocTable; uint32_t* data = (uint32_t*)readBuf;
for (i = 0; i < size / sizeof(uint32_t); i++) { for (i = 0; i < size / sizeof(uint32_t); i++) {
data[i] = REEND32(data[i]); data[i] = REEND32(data[i]);
} }
} }
return relocTable; /* Make the relocation table, for SHT_REL sections add an addend of 0 */
if (type == SHT_REL) {
size_t i;
FairyRel* rel = (FairyRel*)readBuf;
for (i = 0; i < size / sizeof(FairyRel); i++) {
relocTable[i].r_info = rel[i].r_info;
relocTable[i].r_offset = rel[i].r_offset;
relocTable[i].r_addend = 0;
}
} else {
memcpy(relocTable, readBuf, size);
}
free(readBuf);
*relocsOut = relocTable;
return finalSize / sizeof(FairyRela);
} }
char* Fairy_GetSectionName(FairySecHeader* sectionTable, char* shstrtab, size_t index) { char* Fairy_GetSectionName(FairySecHeader* sectionTable, char* shstrtab, size_t index) {
@ -240,7 +282,8 @@ void Fairy_InitFile(FairyFileInfo* fileInfo, FILE* file) {
shstrtab = malloc(sectionTable[fileHeader.e_shstrndx].sh_size * sizeof(char)); shstrtab = malloc(sectionTable[fileHeader.e_shstrndx].sh_size * sizeof(char));
fseek(file, sectionTable[fileHeader.e_shstrndx].sh_offset, SEEK_SET); fseek(file, sectionTable[fileHeader.e_shstrndx].sh_offset, SEEK_SET);
assert(fread(shstrtab, sectionTable[fileHeader.e_shstrndx].sh_size, 1, file) != 0); assert(fread(shstrtab, sizeof(char), sectionTable[fileHeader.e_shstrndx].sh_size, file) ==
sectionTable[fileHeader.e_shstrndx].sh_size);
/* Search for the sections we need */ /* Search for the sections we need */
{ {
@ -251,6 +294,8 @@ void Fairy_InitFile(FairyFileInfo* fileInfo, FILE* file) {
} }
for (currentIndex = 0; currentIndex < fileHeader.e_shnum; currentIndex++) { for (currentIndex = 0; currentIndex < fileHeader.e_shnum; currentIndex++) {
size_t off = 0;
currentSection = sectionTable[currentIndex]; currentSection = sectionTable[currentIndex];
switch (currentSection.sh_type) { switch (currentSection.sh_type) {
@ -299,10 +344,11 @@ void Fairy_InitFile(FairyFileInfo* fileInfo, FILE* file) {
case SHT_SYMTAB: case SHT_SYMTAB:
if (strcmp(&shstrtab[currentSection.sh_name + 1], "symtab") == 0) { if (strcmp(&shstrtab[currentSection.sh_name + 1], "symtab") == 0) {
fileInfo->symtabInfo.sectionSize = currentSection.sh_size; fileInfo->symtabInfo.sectionType = SHT_SYMTAB;
fileInfo->symtabInfo.sectionData = malloc(currentSection.sh_size); fileInfo->symtabInfo.sectionEntrySize = sizeof(FairySym);
Fairy_ReadSymbolTable(fileInfo->symtabInfo.sectionData, file, currentSection.sh_offset, fileInfo->symtabInfo.sectionEntryCount =
currentSection.sh_size); Fairy_ReadSymbolTable((FairySym**)&fileInfo->symtabInfo.sectionData, file,
currentSection.sh_offset, currentSection.sh_size);
} }
break; break;
@ -314,30 +360,32 @@ void Fairy_InitFile(FairyFileInfo* fileInfo, FILE* file) {
} }
break; break;
case SHT_RELA:
off += 1;
case SHT_REL: case SHT_REL:
off += 5;
/* This assumes only one reloc section of each name */ /* This assumes only one reloc section of each name */
// TODO: is this a problem? // TODO: is this a problem?
{ {
FairySection relocSection = FAIRY_SECTION_OTHER; FairySection relocSection = FAIRY_SECTION_OTHER;
/* Ignore the first 5 chars, which will always be ".rel." */ /* Ignore the first 5/6 chars, which will always be ".rel."/".rela." */
if (strcmp(&shstrtab[currentSection.sh_name + 5], "text") == 0) { if (strcmp(&shstrtab[currentSection.sh_name + off], "text") == 0) {
relocSection = FAIRY_SECTION_TEXT; relocSection = FAIRY_SECTION_TEXT;
FAIRY_DEBUG_PRINTF("%s", "Found rel.text section\n"); } else if (strcmp(&shstrtab[currentSection.sh_name + off], "data") == 0) {
} else if (strcmp(&shstrtab[currentSection.sh_name + 5], "data") == 0) {
relocSection = FAIRY_SECTION_DATA; relocSection = FAIRY_SECTION_DATA;
FAIRY_DEBUG_PRINTF("%s", "Found rel.data section\n"); } else if (strcmp(&shstrtab[currentSection.sh_name + off], "rodata") == 0) {
} else if (strcmp(&shstrtab[currentSection.sh_name + 5], "rodata") == 0) {
relocSection = FAIRY_SECTION_RODATA; relocSection = FAIRY_SECTION_RODATA;
FAIRY_DEBUG_PRINTF("%s", "Found rel.rodata section\n");
} else { } else {
break; break;
} }
FAIRY_DEBUG_PRINTF("Found %s section\n", &shstrtab[currentSection.sh_name]);
fileInfo->relocTablesInfo[relocSection].sectionSize = currentSection.sh_size; fileInfo->relocTablesInfo[relocSection].sectionType = SHT_RELA;
fileInfo->relocTablesInfo[relocSection].sectionData = malloc(currentSection.sh_size); fileInfo->relocTablesInfo[relocSection].sectionEntrySize = sizeof(FairyRela);
Fairy_ReadRelocs(fileInfo->relocTablesInfo[relocSection].sectionData, file, fileInfo->relocTablesInfo[relocSection].sectionEntryCount =
currentSection.sh_offset, currentSection.sh_size); Fairy_ReadRelocs((FairyRela**)&fileInfo->relocTablesInfo[relocSection].sectionData, file,
currentSection.sh_type, currentSection.sh_offset, currentSection.sh_size);
} }
break; break;

View File

@ -24,6 +24,7 @@ typedef Elf32_Ehdr FairyFileHeader;
typedef Elf32_Shdr FairySecHeader; typedef Elf32_Shdr FairySecHeader;
typedef Elf32_Sym FairySym; typedef Elf32_Sym FairySym;
typedef Elf32_Rel FairyRel; typedef Elf32_Rel FairyRel;
typedef Elf32_Rela FairyRela;
typedef struct { typedef struct {
int define; int define;
@ -32,7 +33,9 @@ typedef struct {
typedef struct { typedef struct {
void* sectionData; void* sectionData;
size_t sectionSize; int sectionType;
size_t sectionEntryCount;
size_t sectionEntrySize;
} FairySectionInfo; } FairySectionInfo;
typedef struct { typedef struct {
@ -60,9 +63,9 @@ bool Fairy_StartsWith(const char* string, const char* initial);
FairyFileHeader* Fairy_ReadFileHeader(FairyFileHeader* header, FILE* file); FairyFileHeader* Fairy_ReadFileHeader(FairyFileHeader* header, FILE* file);
FairySecHeader* Fairy_ReadSectionTable(FairySecHeader* sectionTable, FILE* file, size_t tableOffset, size_t number); FairySecHeader* Fairy_ReadSectionTable(FairySecHeader* sectionTable, FILE* file, size_t tableOffset, size_t number);
FairySym* Fairy_ReadSymbolTable(FairySym* symbolTable, FILE* file, size_t tableOffset, size_t tableSize);
char* Fairy_ReadStringTable(char* stringTable, FILE* file, size_t tableOffset, size_t tableSize); char* Fairy_ReadStringTable(char* stringTable, FILE* file, size_t tableOffset, size_t tableSize);
FairyRel* Fairy_ReadRelocs(FairyRel* relocTable, FILE* file, size_t offset, size_t number); size_t Fairy_ReadSymbolTable(FairySym** symbolTableOut, FILE* file, size_t tableOffset, size_t tableSize);
size_t Fairy_ReadRelocs(FairyRela** relocsOut, FILE* file, int type, size_t offset, size_t size);
char* Fairy_GetSectionName(FairySecHeader* sectionTable, char* shstrtab, size_t index); char* Fairy_GetSectionName(FairySecHeader* sectionTable, char* shstrtab, size_t index);
char* Fairy_GetSymbolName(FairySym* symtab, char* strtab, size_t index); char* Fairy_GetSymbolName(FairySym* symtab, char* strtab, size_t index);

View File

@ -32,7 +32,7 @@ void Fairy_PrintSymbolTable(FILE* inputFile) {
shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char)); shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char));
fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET); fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET);
assert(fread(shstrtab, sectionTable[shstrndx].sh_size, 1, inputFile) != 0); assert(fread(shstrtab, sizeof(char), sectionTable[shstrndx].sh_size, inputFile) == sectionTable[shstrndx].sh_size);
{ {
size_t currentIndex; size_t currentIndex;
@ -44,9 +44,8 @@ void Fairy_PrintSymbolTable(FILE* inputFile) {
case SHT_SYMTAB: case SHT_SYMTAB:
if (strcmp(&shstrtab[currentHeader.sh_name], ".symtab") == 0) { if (strcmp(&shstrtab[currentHeader.sh_name], ".symtab") == 0) {
printf("symtab found\n"); printf("symtab found\n");
symbolTableNum = currentHeader.sh_size / sizeof(FairySym); symbolTableNum = Fairy_ReadSymbolTable(&symbolTable, inputFile, currentHeader.sh_offset,
symbolTable = malloc(currentHeader.sh_size); currentHeader.sh_size);
Fairy_ReadSymbolTable(symbolTable, inputFile, currentHeader.sh_offset, currentHeader.sh_size);
} }
break; break;
@ -74,7 +73,8 @@ void Fairy_PrintSymbolTable(FILE* inputFile) {
printf("and mallocked\n"); printf("and mallocked\n");
fseek(inputFile, sectionTable[strtabndx].sh_offset, SEEK_SET); fseek(inputFile, sectionTable[strtabndx].sh_offset, SEEK_SET);
printf("file offset sought: %X\n", sectionTable[strtabndx].sh_offset); printf("file offset sought: %X\n", sectionTable[strtabndx].sh_offset);
assert(fread(strtab, sectionTable[strtabndx].sh_size, 1, inputFile) != 0); assert(fread(strtab, sizeof(char), sectionTable[strtabndx].sh_size, inputFile) ==
sectionTable[strtabndx].sh_size);
printf("file read\n"); printf("file read\n");
} }
} }
@ -117,7 +117,7 @@ void Fairy_PrintSymbolTable(FILE* inputFile) {
void Fairy_PrintRelocs(FILE* inputFile) { void Fairy_PrintRelocs(FILE* inputFile) {
FairyFileHeader fileHeader; FairyFileHeader fileHeader;
FairySecHeader* sectionTable; FairySecHeader* sectionTable;
FairyRel* relocs; FairyRela* relocs;
size_t shstrndx; size_t shstrndx;
char* shstrtab; char* shstrtab;
size_t currentSection; size_t currentSection;
@ -131,29 +131,28 @@ void Fairy_PrintRelocs(FILE* inputFile) {
shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char)); shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char));
fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET); fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET);
assert(fread(shstrtab, sectionTable[shstrndx].sh_size, 1, inputFile) != 0); assert(fread(shstrtab, sizeof(char), sectionTable[shstrndx].sh_size, inputFile) == sectionTable[shstrndx].sh_size);
for (currentSection = 0; currentSection < fileHeader.e_shnum; currentSection++) { for (currentSection = 0; currentSection < fileHeader.e_shnum; currentSection++) {
if (sectionTable[currentSection].sh_type != SHT_REL) { size_t nRelocs;
if (sectionTable[currentSection].sh_type != SHT_REL || sectionTable[currentSection].sh_type != SHT_RELA) {
continue; continue;
} }
printf("Section size: %d\n", sectionTable[currentSection].sh_size); printf("Section size: %d\n", sectionTable[currentSection].sh_size);
relocs = malloc(sectionTable[currentSection].sh_size * sizeof(char)); nRelocs = Fairy_ReadRelocs(&relocs, inputFile, sectionTable[currentSection].sh_type,
sectionTable[currentSection].sh_offset, sectionTable[currentSection].sh_size);
Fairy_ReadRelocs(relocs, inputFile, sectionTable[currentSection].sh_offset,
sectionTable[currentSection].sh_size);
// fseek(inputFile, sectionTable[currentSection].sh_offset, SEEK_SET); // fseek(inputFile, sectionTable[currentSection].sh_offset, SEEK_SET);
// assert(fread(relocs, sectionTable[currentSection].sh_size, 1, inputFile) != 0); // assert(fread(relocs, sizeof(char), sectionTable[currentSection].sh_size, inputFile) ==
// sectionTable[currentSection].sh_size);
printf("Relocs in section [%2zd]: %s:\n", currentSection, shstrtab + sectionTable[currentSection].sh_name); printf("Relocs in section [%2zd]: %s:\n", currentSection, shstrtab + sectionTable[currentSection].sh_name);
printf("Offset Info Type Symbol\n"); printf("Offset Info Type Symbol\n");
{ {
size_t currentReloc; size_t currentReloc;
for (currentReloc = 0; currentReloc < sectionTable[currentSection].sh_size / sizeof(*relocs); for (currentReloc = 0; currentReloc < nRelocs; currentReloc++) {
currentReloc++) {
printf("%08X,%08X ", relocs[currentReloc].r_offset, relocs[currentReloc].r_info); printf("%08X,%08X ", relocs[currentReloc].r_offset, relocs[currentReloc].r_info);
switch (ELF32_R_TYPE(relocs[currentReloc].r_info)) { switch (ELF32_R_TYPE(relocs[currentReloc].r_info)) {
@ -212,7 +211,7 @@ void Fairy_PrintSectionTable(FILE* inputFile) {
shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char)); shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char));
fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET); fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET);
assert(fread(shstrtab, sectionTable[shstrndx].sh_size, 1, inputFile) != 0); assert(fread(shstrtab, sizeof(char), sectionTable[shstrndx].sh_size, inputFile) == sectionTable[shstrndx].sh_size);
printf("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"); printf("[Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n");
for (currentSection = 0; currentSection < fileHeader.e_shnum; currentSection++) { for (currentSection = 0; currentSection < fileHeader.e_shnum; currentSection++) {
@ -261,7 +260,7 @@ const char* relSectionStrings[] = {
".rodata", ".rodata",
}; };
static uint32_t Fairy_PackReloc(FairyOverlayRelSection sec, FairyRel rel) { static uint32_t Fairy_PackReloc(FairyOverlayRelSection sec, FairyRela rel) {
return (sec << 0x1E) | (ELF32_R_TYPE(rel.r_info) << 0x18) | rel.r_offset; return (sec << 0x1E) | (ELF32_R_TYPE(rel.r_info) << 0x18) | rel.r_offset;
} }
@ -290,7 +289,7 @@ void Fairy_PrintSectionSizes(FairySecHeader* sectionTable, FILE* inputFile, size
bool strtabFound = false; bool strtabFound = false;
/* Count the reloc sections */ /* Count the reloc sections */
for (currentSection = 0; currentSection < number; currentSection++) { for (currentSection = 0; currentSection < number; currentSection++) {
if (sectionTable[currentSection].sh_type == SHT_REL) { if (sectionTable[currentSection].sh_type == SHT_REL || sectionTable[currentSection].sh_type == SHT_RELA) {
relocSectionsCount++; relocSectionsCount++;
} }
} }
@ -301,6 +300,8 @@ void Fairy_PrintSectionSizes(FairySecHeader* sectionTable, FILE* inputFile, size
/* Find the section sizes and the reloc sections */ /* Find the section sizes and the reloc sections */
for (currentSection = 0; currentSection < number; currentSection++) { for (currentSection = 0; currentSection < number; currentSection++) {
size_t off = 0;
currentHeader = sectionTable[currentSection]; currentHeader = sectionTable[currentSection];
sectionName = &shstrtab[currentHeader.sh_name + 1]; /* ignore the initial '.' */ sectionName = &shstrtab[currentHeader.sh_name + 1]; /* ignore the initial '.' */
switch (currentHeader.sh_type) { switch (currentHeader.sh_type) {
@ -329,17 +330,19 @@ void Fairy_PrintSectionSizes(FairySecHeader* sectionTable, FILE* inputFile, size
} }
break; break;
case SHT_RELA:
off += 1;
case SHT_REL: case SHT_REL:
relocSectionIndices[currentRelocSection] = currentSection; relocSectionIndices[currentRelocSection] = currentSection;
sectionName += 4; /* ignore the "rel." part */ off += 4; /* ignore the "rel."/"rela." part */
if (Fairy_StartsWith(sectionName, "rodata")) { if (Fairy_StartsWith(&sectionName[off], "rodata")) {
printf(".rel.rodata\n"); printf("%s\n", sectionName);
relocSectionSection[currentRelocSection] = REL_SECTION_RODATA; relocSectionSection[currentRelocSection] = REL_SECTION_RODATA;
} else if (Fairy_StartsWith(sectionName, "data")) { } else if (Fairy_StartsWith(&sectionName[off], "data")) {
printf(".rel.data\n"); printf("%s\n", sectionName);
relocSectionSection[currentRelocSection] = REL_SECTION_DATA; relocSectionSection[currentRelocSection] = REL_SECTION_DATA;
} else if (Fairy_StartsWith(sectionName, "text")) { } else if (Fairy_StartsWith(&sectionName[off], "text")) {
printf(".rel.text\n"); printf("%s\n", sectionName);
relocSectionSection[currentRelocSection] = REL_SECTION_TEXT; relocSectionSection[currentRelocSection] = REL_SECTION_TEXT;
} }
@ -373,36 +376,34 @@ void Fairy_PrintSectionSizes(FairySecHeader* sectionTable, FILE* inputFile, size
printf(".word 0x%08X # .bss size\n\n", bssSize); printf(".word 0x%08X # .bss size\n\n", bssSize);
if (!symtabFound) { if (!symtabFound) {
fprintf(stderr, "Symbol table not found"); fprintf(stderr, "Symbol table not found\n");
return; return;
} }
/* Obtain the symbol table */ /* Obtain the symbol table */
symtab = malloc(symtabHeader.sh_size);
// TODO: Consider replacing this with a lighter-weight read: sufficient to get the name, shndx // TODO: Consider replacing this with a lighter-weight read: sufficient to get the name, shndx
Fairy_ReadSymbolTable(symtab, inputFile, symtabHeader.sh_offset, symtabHeader.sh_size); Fairy_ReadSymbolTable(&symtab, inputFile, symtabHeader.sh_offset, symtabHeader.sh_size);
if (!strtabFound) { if (!strtabFound) {
fprintf(stderr, "String table not found"); fprintf(stderr, "String table not found\n");
} else { } else {
/* Obtain the string table */ /* Obtain the string table */
strtab = malloc(strtabHeader.sh_size); strtab = malloc(strtabHeader.sh_size);
fseek(inputFile, strtabHeader.sh_offset, SEEK_SET); fseek(inputFile, strtabHeader.sh_offset, SEEK_SET);
assert(fread(strtab, strtabHeader.sh_size, 1, inputFile) != 0); assert(fread(strtab, sizeof(char), strtabHeader.sh_size, inputFile) == strtabHeader.sh_size);
} }
/* Do single-file relocs */ /* Do single-file relocs */
{ {
FairyRel* relocs; FairyRela* relocs;
for (currentSection = 0; currentSection < relocSectionsCount; currentSection++) { for (currentSection = 0; currentSection < relocSectionsCount; currentSection++) {
size_t currentReloc; size_t currentReloc;
size_t sectionRelocCount; size_t nRelocs;
currentHeader = sectionTable[relocSectionIndices[currentSection]];
sectionRelocCount = currentHeader.sh_size / sizeof(FairyRel);
relocs = malloc(currentHeader.sh_size);
Fairy_ReadRelocs(relocs, inputFile, currentHeader.sh_offset, currentHeader.sh_size);
for (currentReloc = 0; currentReloc < sectionRelocCount; currentReloc++) { currentHeader = sectionTable[relocSectionIndices[currentSection]];
nRelocs = Fairy_ReadRelocs(&relocs, inputFile, currentHeader.sh_type, currentHeader.sh_offset,
currentHeader.sh_size);
for (currentReloc = 0; currentReloc < nRelocs; currentReloc++) {
FairySym symbol = symtab[ELF32_R_SYM(relocs[currentReloc].r_info)]; FairySym symbol = symtab[ELF32_R_SYM(relocs[currentReloc].r_info)];
if (symbol.st_shndx == SHN_UNDEF) { if (symbol.st_shndx == SHN_UNDEF) {
continue; // TODO: this is where multifile has to look elsewhere continue; // TODO: this is where multifile has to look elsewhere
@ -453,7 +454,7 @@ void PrintZeldaReloc(FILE* inputFile) {
shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char)); shstrtab = malloc(sectionTable[shstrndx].sh_size * sizeof(char));
fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET); fseek(inputFile, sectionTable[shstrndx].sh_offset, SEEK_SET);
assert(fread(shstrtab, sectionTable[shstrndx].sh_size, 1, inputFile) != 0); assert(fread(shstrtab, sizeof(char), sectionTable[shstrndx].sh_size, inputFile) == sectionTable[shstrndx].sh_size);
Fairy_PrintSectionSizes(sectionTable, inputFile, fileHeader.e_shentsize * fileHeader.e_shnum, shstrtab); Fairy_PrintSectionSizes(sectionTable, inputFile, fileHeader.e_shentsize * fileHeader.e_shnum, shstrtab);

View File

@ -112,15 +112,15 @@ bool vc_vector_is_equals(vc_vector* vector1, vc_vector* vector2) {
return memcmp(vector1->data, vector2->data, size_vector1) == 0; return memcmp(vector1->data, vector2->data, size_vector1) == 0;
} }
float vc_vector_get_growth_factor() { float vc_vector_get_growth_factor(void) {
return GROWTH_FACTOR; return GROWTH_FACTOR;
} }
size_t vc_vector_get_default_count_of_elements() { size_t vc_vector_get_default_count_of_elements(void) {
return DEFAULT_COUNT_OF_ELEMENTS; return DEFAULT_COUNT_OF_ELEMENTS;
} }
size_t vc_vector_struct_size() { size_t vc_vector_struct_size(void) {
return sizeof(vc_vector); return sizeof(vc_vector);
} }

View File

@ -24,13 +24,13 @@ void vc_vector_release(vc_vector* vector);
bool vc_vector_is_equals(vc_vector* vector1, vc_vector* vector2); bool vc_vector_is_equals(vc_vector* vector1, vc_vector* vector2);
// Returns constant value of the vector growth factor. // Returns constant value of the vector growth factor.
float vc_vector_get_growth_factor(); float vc_vector_get_growth_factor(void);
// Returns constant value of the vector default count of elements. // Returns constant value of the vector default count of elements.
size_t vc_vector_get_default_count_of_elements(); size_t vc_vector_get_default_count_of_elements(void);
// Returns constant value of the vector struct size. // Returns constant value of the vector struct size.
size_t vc_vector_struct_size(); size_t vc_vector_struct_size(void);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Element access // Element access

View File

@ -40,8 +40,7 @@ void Fado_ConstructStringVectors(vc_vector** stringVectors, FairyFileInfo* fileI
stringVectors[currentFile] = vc_vector_create(0x40, sizeof(char**), NULL); stringVectors[currentFile] = vc_vector_create(0x40, sizeof(char**), NULL);
/* Build a vector of pointers to defined symbols' names */ /* Build a vector of pointers to defined symbols' names */
for (currentSym = 0; currentSym < fileInfo[currentFile].symtabInfo.sectionSize / sizeof(FairySym); for (currentSym = 0; currentSym < fileInfo[currentFile].symtabInfo.sectionEntryCount; currentSym++) {
currentSym++) {
if ((symtab[currentSym].st_shndx != STN_UNDEF) && if ((symtab[currentSym].st_shndx != STN_UNDEF) &&
Fado_CheckInProgBitsSections(symtab[currentSym].st_shndx, fileInfo[currentFile].progBitsSections)) { Fado_CheckInProgBitsSections(symtab[currentSym].st_shndx, fileInfo[currentFile].progBitsSections)) {
/* Have to pass a double pointer so it copies the pointer instead of the start of the string */ /* Have to pass a double pointer so it copies the pointer instead of the start of the string */
@ -86,7 +85,7 @@ typedef struct {
} FadoRelocInfo; } FadoRelocInfo;
/* Construct the Zelda64ovl-compatible reloc word from an ELF reloc */ /* Construct the Zelda64ovl-compatible reloc word from an ELF reloc */
FadoRelocInfo Fado_MakeReloc(int file, FairySection section, FairyRel* data) { FadoRelocInfo Fado_MakeReloc(int file, FairySection section, FairyRela* data) {
FadoRelocInfo relocInfo = { 0 }; FadoRelocInfo relocInfo = { 0 };
uint32_t sectionPrefix = 0; uint32_t sectionPrefix = 0;
@ -223,11 +222,10 @@ void Fado_Relocs(FILE* outputFile, int inputFilesCount, FILE** inputFiles, const
relocList[section] = vc_vector_create(0x100, sizeof(FadoRelocInfo), NULL); relocList[section] = vc_vector_create(0x100, sizeof(FadoRelocInfo), NULL);
for (currentFile = 0; currentFile < inputFilesCount; currentFile++) { for (currentFile = 0; currentFile < inputFilesCount; currentFile++) {
FairyRel* relSection = fileInfos[currentFile].relocTablesInfo[section].sectionData; FairyRela* relSection = fileInfos[currentFile].relocTablesInfo[section].sectionData;
if (relSection != NULL) {
for (relocIndex = 0; if (relSection != NULL) {
relocIndex < fileInfos[currentFile].relocTablesInfo[section].sectionSize / sizeof(FairyRel); for (relocIndex = 0; relocIndex < fileInfos[currentFile].relocTablesInfo[section].sectionEntryCount;
relocIndex++) { relocIndex++) {
FadoRelocInfo currentReloc = Fado_MakeReloc(currentFile, section, &relSection[relocIndex]); FadoRelocInfo currentReloc = Fado_MakeReloc(currentFile, section, &relSection[relocIndex]);

View File

@ -15,7 +15,7 @@
#include "version.inc" #include "version.inc"
void PrintVersion() { void PrintVersion(void) {
printf("Fado (Fairy-Assisted relocations for Decompiled Overlays), version %s\n", versionNumber); printf("Fado (Fairy-Assisted relocations for Decompiled Overlays), version %s\n", versionNumber);
printf("Copyright (C) 2021 Elliptic Ellipsis\n"); printf("Copyright (C) 2021 Elliptic Ellipsis\n");
printf("%s\n", credits); printf("%s\n", credits);
@ -88,7 +88,7 @@ static size_t posArgCount = ARRAY_COUNT(posArgInfo);
static size_t optCount = ARRAY_COUNT(optInfo); static size_t optCount = ARRAY_COUNT(optInfo);
static struct option longOptions[ARRAY_COUNT(optInfo)]; static struct option longOptions[ARRAY_COUNT(optInfo)];
void ConstructLongOpts() { void ConstructLongOpts(void) {
size_t i; size_t i;
for (i = 0; i < optCount; i++) { for (i = 0; i < optCount; i++) {
@ -133,14 +133,15 @@ int main(int argc, char** argv) {
outputFileName = optarg; outputFileName = optarg;
outputFile = fopen(optarg, "wb"); outputFile = fopen(optarg, "wb");
if (outputFile == NULL) { if (outputFile == NULL) {
fprintf(stderr, "error: unable to open output file '%s' for writing", optarg); fprintf(stderr, "error: unable to open output file '%s' for writing\n", optarg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
break; break;
case 'v': case 'v':
if (sscanf(optarg, "%u", &gVerbosity) == 0) { if (sscanf(optarg, "%u", &gVerbosity) == 0) {
fprintf(stderr, "warning: verbosity argument '%s' should be a nonnegative decimal integer", optarg); fprintf(stderr, "warning: verbosity argument '%s' should be a nonnegative decimal integer\n",
optarg);
} }
break; break;
@ -182,7 +183,7 @@ int main(int argc, char** argv) {
FAIRY_INFO_PRINTF("Using input file %s\n", argv[optind + i]); FAIRY_INFO_PRINTF("Using input file %s\n", argv[optind + i]);
inputFiles[i] = fopen(argv[optind + i], "rb"); inputFiles[i] = fopen(argv[optind + i], "rb");
if (inputFiles[i] == NULL) { if (inputFiles[i] == NULL) {
fprintf(stderr, "error: unable to open input file '%s' for reading", argv[optind + i]); fprintf(stderr, "error: unable to open input file '%s' for reading\n", argv[optind + i]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -214,14 +215,14 @@ int main(int argc, char** argv) {
FILE* dependencyFile = fopen(dependencyFileName, "w"); FILE* dependencyFile = fopen(dependencyFileName, "w");
if (dependencyFile == NULL) { if (dependencyFile == NULL) {
fprintf(stderr, "error: unable to open dependency file '%s' for writing", dependencyFileName); fprintf(stderr, "error: unable to open dependency file '%s' for writing\n", dependencyFileName);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
strcpy(objectFile, outputFileName); strcpy(objectFile, outputFileName);
extensionStart = strrchr(objectFile, '.'); extensionStart = strrchr(objectFile, '.');
if (extensionStart == objectFile + fileNameLength) { if (extensionStart == objectFile + fileNameLength) {
fprintf(stderr, "error: file name should not end in a '.'"); fprintf(stderr, "error: file name should not end in a '.'\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
strcpy(extensionStart, ".o"); strcpy(extensionStart, ".o");

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2021 Elliptic Ellipsis */ /* Copyright (C) 2021 Elliptic Ellipsis */
/* SPDX-License-Identifier: AGPL-3.0-only */ /* SPDX-License-Identifier: AGPL-3.0-only */
const char versionNumber[] = "1.2.1"; const char versionNumber[] = "1.3.1";
const char credits[] = "Written by Elliptic Ellipsis\nand AngheloAlf"; const char credits[] = "Written by Elliptic Ellipsis\nwith additions from AngheloAlf and Tharo";
const char repo[] = "https://github.com/EllipticEllipsis/fado/"; const char repo[] = "https://github.com/EllipticEllipsis/fado/";