diff options
Diffstat (limited to 'arm-riscos-gnueabi/recipes/patches/gccsdk/elf2aif-eabi-support.p')
-rw-r--r-- | arm-riscos-gnueabi/recipes/patches/gccsdk/elf2aif-eabi-support.p | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/arm-riscos-gnueabi/recipes/patches/gccsdk/elf2aif-eabi-support.p b/arm-riscos-gnueabi/recipes/patches/gccsdk/elf2aif-eabi-support.p new file mode 100644 index 0000000..afac755 --- /dev/null +++ b/arm-riscos-gnueabi/recipes/patches/gccsdk/elf2aif-eabi-support.p @@ -0,0 +1,394 @@ +Index: elf2aif/src/elf2aif.c +=================================================================== +--- elf2aif/src/elf2aif.c (revision 7698) ++++ elf2aif/src/elf2aif.c (working copy) +@@ -54,7 +54,7 @@ + typedef struct + { + uint8_t decompress[4]; /* BL to decompression code for compressed images */ +- uint8_t selfreloc[4]; /* BL to self-relocation code */ ++ uint8_t selfreloc[4]; /* BL to self-relocation code (*) */ + uint8_t zeroinit[4]; /* BL to zero init code */ + uint8_t entrypoint[4]; /* BL to image entry point (*) */ + uint8_t exitinst[4]; /* Exit instruction */ +@@ -72,47 +72,50 @@ + } aifheader_t; + + static int opt_verbose = 0; ++static int opt_eabi = 0; + + static Elf32_External_Ehdr elf_ehdr; + static phdr_list_t *elf_phdrlistP; + static const char *elf_filename; ++static uint32_t got_addr = 0; + +-static const unsigned int aifcode[] = { +- 0xE1A00000, /* NOP (BL decompress) */ +- 0xE1A00000, /* NOP (BL self-relocate) */ +- 0xEB00000C, /* BL zero-init */ +- 0xEB000000, /* BL entrypoint (*) */ +- 0xEF000011, /* SWI OS_Exit */ +- 0x00000000, /* Image R/O size (*) */ +- 0x00000000, /* Image R/W size (*) */ +- 0x00000000, /* Image debug size */ +- 0x00000000, /* Image zero-init size (*) */ +- 0x00000000, /* Image debug type */ +- 0x00000000, /* Image base (*) */ +- 0x00000000, /* Workspace size */ +- 0x00000020, /* 32-bit addressing */ +- 0x00000000, /* Data base */ +- 0x00000000, /* Reserved */ +- 0x00000000, /* Reserved */ +- 0xE1A00000, /* MOV R0, R0 */ +- 0xE04EC00F, /* SUB R12, R14, PC */ +- 0xE08FC00C, /* ADD R12, PC, R12 */ +- 0xE99C0017, /* LDMIB R12, {R0-R2, R4} */ +- 0xE24CC010, /* SUB R12, R12, #0x10 */ +- 0xE08CC000, /* ADD R12, R12, R0 */ +- 0xE08CC001, /* ADD R12, R12, R1 */ +- 0xE3A00000, /* MOV R0, #0 */ +- 0xE3A01000, /* MOV R1, #0 */ +- 0xE3A02000, /* MOV R2, #0 */ +- 0xE3A03000, /* MOV R3, #0 */ +- 0xE3540000, /* CMP R4, #0 */ ++static const uint32_t aifcode[] = { ++ 0xE1A00000, /* NOP (BL decompress) */ ++ 0xE1A00000, /* NOP (BL self-relocate) (*) */ ++ 0xEB00000C, /* BL zero-init */ ++ 0xEB000000, /* BL entrypoint (*) */ ++ 0xEF000011, /* SWI OS_Exit */ ++ 0x00000000, /* Image R/O size (*) */ ++ 0x00000000, /* Image R/W size (*) */ ++ 0x00000000, /* Image debug size */ ++ 0x00000000, /* Image zero-init size (*) */ ++ 0x00000000, /* Image debug type */ ++ 0x00000000, /* Image base (*) */ ++ 0x00000000, /* Workspace size */ ++ 0x00000020, /* 32-bit addressing */ ++ 0x00000000, /* Data base */ ++ 0x00000000, /* Reserved */ ++ 0x00000000, /* Reserved */ ++ 0xE1A00000, /* MOV R0, R0 */ ++ 0xE04EC00F, /* SUB R12, R14, PC */ ++ 0xE08FC00C, /* ADD R12, PC, R12 */ ++ 0xE99C0017, /* LDMIB R12, {R0-R2, R4} */ ++ 0xE24CC010, /* SUB R12, R12, #16 */ ++ 0xE08CC000, /* ADD R12, R12, R0 */ ++ 0xE08CC001, /* ADD R12, R12, R1 */ ++ 0xE3A00000, /* MOV R0, #0 */ ++ 0xE3A01000, /* MOV R1, #0 */ ++ 0xE3A02000, /* MOV R2, #0 */ ++ 0xE3A03000, /* MOV R3, #0 */ ++ 0xE3540000, /* CMP R4, #0 */ + /* zeroloop: */ +- 0xD1A0F00E, /* MOVLE PC, R14 */ +- 0xE8AC000F, /* STMIA R12!, {R0-R3} */ +- 0xE2544010, /* SUBS R4, R4, #16 */ +- 0xEAFFFFFB /* B zeroloop */ ++ 0xD1A0F00E, /* MOVLE PC, R14 */ ++ 0xE8AC000F, /* STMIA R12!, {R0-R3} */ ++ 0xE2544010, /* SUBS R4, R4, #16 */ ++ 0xEAFFFFFB /* B zeroloop */ + }; + ++ + /* Read a little-endian 'short' value. */ + static uint16_t + RdShort (const uint8_t sh[2]) +@@ -143,6 +146,7 @@ + fprintf (stderr, "Usage: elf2aif [options] <ELF file> [<AIF file>]\n" + "Convert static ARM ELF binary to AIF (Acorn Image Format) binary.\n" + "Options:\n" ++ " -e, --eabi source binary uses EABI\n" + " -v, --verbose prints informational messages during processing\n" + " --help display this help and exit\n" + " --version output version information and exit\n"); +@@ -201,7 +205,8 @@ + return EXIT_FAILURE; + } + +- if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM) ++ if ((!opt_eabi && elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM) || ++ (opt_eabi && elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_NONE)) + { + fprintf (stderr, "ELF file '%s' is not for ARM\n", elf_filename); + return EXIT_FAILURE; +@@ -344,6 +349,97 @@ + } + + static int ++e2a_readshdr (FILE * elfhandle) ++{ ++ Elf32_External_Shdr shstentry; ++ uint32_t shoffset, shentrysize, shentrycount, shstrndx; ++ uint32_t shstoffset, shstsize; ++ char *shst; ++ ++ if ((shoffset = RdLong (elf_ehdr.e_shoff)) == 0 ++ || (shentrycount = RdShort (elf_ehdr.e_shnum)) == 0) ++ { ++ fprintf (stderr, "ELF file '%s' does not have section headers\n", ++ elf_filename); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shentrysize = RdShort (elf_ehdr.e_shentsize)) < sizeof (Elf32_External_Shdr)) ++ { ++ fprintf (stderr, "Size section header entry is too small\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shstrndx = RdShort (elf_ehdr.e_shstrndx)) >= shentrycount) { ++ fprintf (stderr, "String table index out of bounds\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if (fseek (elfhandle, shoffset + (shstrndx * shentrysize), SEEK_SET) != 0 ++ || fread (&shstentry, sizeof (Elf32_External_Shdr), 1, elfhandle) != 1) ++ { ++ fprintf (stderr, "Failed to read section header string table header\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shstoffset = RdLong (shstentry.sh_offset)) == 0) ++ { ++ fprintf (stderr, "Section header string table data missing\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shstsize = RdLong (shstentry.sh_size)) == 0) ++ { ++ fprintf (stderr, "Invalid section header string table size\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shst = malloc (shstsize)) == NULL) ++ { ++ fprintf (stderr, "Out of memory\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if (fseek (elfhandle, shstoffset, SEEK_SET) != 0 ++ || fread (shst, 1, shstsize, elfhandle) != shstsize) ++ { ++ fprintf (stderr, "Failed to read section header string table\n"); ++ return EXIT_FAILURE; ++ } ++ ++ while (shentrycount) ++ { ++ Elf32_External_Shdr shentry; ++ uint32_t shnameoff; ++ ++ if (fseek (elfhandle, shoffset, SEEK_SET) != 0 ++ || fread (&shentry, sizeof (Elf32_External_Shdr), 1, elfhandle) != 1) ++ { ++ fprintf (stderr, "Failed to read section header entry\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if ((shnameoff = RdLong (shentry.sh_name)) >= shstsize) ++ { ++ fprintf (stderr, "Section name out of bounds\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if (strcmp ((shst + shnameoff), ".got") == 0) ++ { ++ got_addr = RdLong (shentry.sh_addr); ++ } ++ ++ shoffset += shentrysize; ++ --shentrycount; ++ } ++ ++ free (shst); ++ ++ return EXIT_SUCCESS; ++} ++ ++static int + e2a_copy (FILE * elfhandle, FILE * aifhandle) + { + const phdr_list_t *phdrP; +@@ -488,21 +584,156 @@ + } + + memcpy (&aifhdr, aifcode, sizeof (aifcode)); +- WrLong (aifhdr.entrypoint, +- RdLong (aifhdr.entrypoint) + +- ((exec_addr - load_addr - +- (offsetof (aifheader_t, entrypoint) + 8)) >> 2)); ++ if (opt_eabi) ++ { ++ /* BL to relocation code */ ++ WrLong (aifhdr.selfreloc, ++ /* Default is a NOP, so reading it is useless */ ++ 0xEB000000 + ++ ((aifend - (offsetof (aifheader_t, selfreloc) + 8)) >> 2)); ++ ++ /* BL to EABI startcode */ ++ WrLong (aifhdr.entrypoint, ++ RdLong (aifhdr.entrypoint) + ++ ((sizeof(aifcode) - (offsetof (aifheader_t, entrypoint) + 8)) >> 2)); ++ } ++ else ++ { ++ /* BL to program entrypoint */ ++ WrLong (aifhdr.entrypoint, ++ RdLong (aifhdr.entrypoint) + ++ ((exec_addr - load_addr - ++ (offsetof (aifheader_t, entrypoint) + 8)) >> 2)); ++ } + WrLong (aifhdr.rosize, rosize); + WrLong (aifhdr.rwsize, rwsize); + WrLong (aifhdr.zisize, zisize); + WrLong (aifhdr.imagebase, load_addr); +- if (fwrite (&aifhdr, sizeof (aifhdr), 1, aifhandle) != 1 +- || fseek (aifhandle, aifend, SEEK_SET) != 0) ++ if (fwrite (&aifhdr, sizeof (aifhdr), 1, aifhandle) != 1) + { + fprintf (stderr, "Failed to write aif header\n"); + return EXIT_FAILURE; + } + ++ /* In the EABI case we need to inject the code to install ++ * the ARMEABISupport abort handler */ ++ if (opt_eabi) ++ { ++ assert (128 == sizeof (aifcode)); ++ uint32_t entrycode[] = { ++ /* Space for GOTT_BASE injection (see below) */ ++ 0xE1A00000, /* MOV R0, R0 */ ++ 0xE1A00000, /* MOV R0, R0 */ ++ /* Install the abort handler */ ++ 0xE3A00002, /* MOV R0, #2 */ ++ 0xEF059D01, /* SWI ARMEABISupport_AbortOp */ ++ /* Proceed to the real program start */ ++ 0xEA000000, /* B <program_start> (*) */ ++ /* Offset of the GOT relative to the load address (or 0 if none) */ ++ 0x00000000, /* DCD <got_offset> (*) */ ++ }; ++ ++ const uint32_t reloccode[] = { ++ /* RelocCode: */ ++ 0xE1A00000, /* MOV R0, R0 */ ++ /* Dynamically compute the program load address */ ++ 0xE04EC00F, /* SUB R12, LR, PC */ ++ 0xE08FC00C, /* ADD R12, PC, R12 */ ++ 0xE24CC00C, /* SUB R12, R12, #12 */ ++ /* Prevent reentry by replacing the branch to the relocation code. */ ++ 0xE51F0018, /* LDR R0, =RelocCode */ ++ 0xE58C0004, /* STR R0, [R12, #4] */ ++ /* Relocate the GOT offset (above) to its absolute address */ ++ 0xE59C0094, /* LDR R0, [R12, #&94] */ ++ 0xE3300000, /* TEQ R0, #0 */ ++ 0x1080000C, /* ADDNE R0, R0, R12 */ ++ 0x158C0094, /* STRNE R0, [R12, #&94] */ ++ /* Fill in GOTT_BASE at load + 0x38, unless running under DDT */ ++ 0xE59C0038, /* LDR R0, [R12, #&38] */ ++ 0xE3300000, /* TEQ R0, #0 */ ++ 0x1A000002, /* BNE ddt_hack */ ++ 0xE28C0094, /* ADD R0, R12, #&94 */ ++ 0xE58C0038, /* STR R0, [R12, #&38] */ ++ 0xE1A0F00E, /* MOV PC, LR */ ++ /* Hack for DDT (which uses the reserved field at &8038 to ++ * temporarily store the address of the zero-initialisation code ++ * during program start, which is reinstated after DDT's ++ * replacement is called). In this case, modify the entrycode ++ * (above) to inject it for us. ++ * ++ * This does prevent the RO area being marked non-writeable if ++ * the modified entrycode gets executed, however (in the non-DDT ++ * case, the entrycode does not write to the AIF header, so ++ * there is no reason the RO area can't be non-writeable then). ++ * By definition the RO area must be writeable for relocations to ++ * work, so it is perfectly safe to assume that it is when this ++ * code runs. ++ */ ++ /* ddt_hack: */ ++ 0xE59F001C, /* LDR R0, =ddt_hack_data */ ++ 0xE59F101C, /* LDR R1, =ddt_hack_data+4 */ ++ 0xE58C0080, /* STR R0, [R12, #&80] */ ++ 0xE58C1084, /* STR R1, [R12, #&84] */ ++ /* Invalidate instruction cache */ ++ 0xE3A00001, /* MOV R0, #1 */ ++ 0xE28C1080, /* ADD R1, R12, #&80 */ ++ 0xE28C2088, /* ADD R2, R12, #&88 */ ++ 0xEF02006E, /* SWI XOSSynchroniseCodeAreas */ ++ 0xE1A0F00E, /* MOV PC, LR */ ++ /* Instructions to inject into entrycode. Uses PC-relative ++ * addressing, so must be kept in sync with changes to entrycode ++ * or the location of entrycode within memory. */ ++ /* ddt_hack_data: */ ++ /* Compute address of GOT field after entrycode */ ++ 0xE28F000C, /* ADR R0, got_address */ ++ /* Store computed address in GOTT_BASE (load + 0x38) */ ++ 0xE50F0054, /* STR R0, [pc, #-&54] */ ++ /* Relocation sentinel: just in case anything expects one */ ++ 0xFFFFFFFF, /* DCD -1 */ ++ }; ++ ++ /* Ensure there is sufficient space for the EABI entry code */ ++ if (opt_eabi && exec_addr - load_addr < sizeof (aifcode) + sizeof (entrycode)) ++ { ++ fprintf (stderr, "First program segment is not what we hoped to be " ++ "(not enough place before _start symbol for EABI entrycode)\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if (opt_verbose) ++ printf ("Writing EABI entry code at offset 0x%x\n", sizeof (aifcode)); ++ ++ entrycode[4] |= (exec_addr - load_addr - (sizeof (aifcode) + 4*4 + 8)) >> 2; ++ if (got_addr) ++ { ++ if (opt_verbose) ++ printf ("Found GOT at 0x%x\n", got_addr); ++ entrycode[5] = (got_addr - load_addr); ++ } ++ if (fseek (aifhandle, sizeof (aifcode), SEEK_SET) != 0 ++ || fwrite (&entrycode, sizeof (entrycode), 1, aifhandle) != 1) ++ { ++ fprintf (stderr, "Failed to write EABI entrycode\n"); ++ return EXIT_FAILURE; ++ } ++ ++ if (opt_verbose) ++ printf ("Writing relocation code at offset 0x%x\n", aifend); ++ ++ if (fseek (aifhandle, aifend, SEEK_SET) != 0 ++ || fwrite (&reloccode, sizeof (reloccode), 1, aifhandle) != 1) ++ { ++ fprintf (stderr, "Failed to write relocation code\n"); ++ return EXIT_FAILURE; ++ } ++ } ++ ++ if (fseek (aifhandle, aifend, SEEK_SET) != 0) ++ { ++ fprintf (stderr, "Failed to seek to end of file\n"); ++ return EXIT_FAILURE; ++ } ++ + return EXIT_SUCCESS; + } + +@@ -557,6 +788,7 @@ + elf_filename = elffilename; + + if (e2a_readehdr (elfhandle) == EXIT_SUCCESS ++ && e2a_readshdr (elfhandle) == EXIT_SUCCESS + && e2a_readphdr (elfhandle) == EXIT_SUCCESS + && e2a_copy (elfhandle, aifhandle) == EXIT_SUCCESS) + status = EXIT_SUCCESS; +@@ -683,6 +915,9 @@ + fprintf (stderr, "Warning: extra options/arguments ignored\n"); + return EXIT_SUCCESS; + } ++ else if (!strcmp (&argv[i][1], "-eabi") ++ || !strcmp (&argv[i][1], "e")) ++ opt_eabi = 1; + else if (!strcmp (&argv[i][1], "-verbose") + || !strcmp (&argv[i][1], "v")) + ++opt_verbose; |