imp_amig.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* imp_amiga.c: Routines to import an AmigaOS-hunks file
  2. Copyright (C) 2003 Kevin Kofler and Sebastian Reichelt
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software Foundation,
  13. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #include "imp_amig.h"
  15. #ifdef AMIGAOS_SUPPORT
  16. #include "../../formats/amigaos.h"
  17. #include <stdlib.h>
  18. #include <string.h>
  19. // Import the exported symbols of an AmigaOS-hunks file.
  20. BOOLEAN ArImportAmigaOSFile (OBJECT_FILE *ObjectFile)
  21. {
  22. // Call this for a nice and clean failing exit.
  23. #define Fail() ({return FALSE;})
  24. #define FailWithError(ErrorMsg...) ({Error (FileName, ErrorMsg); Fail ();})
  25. #define TestMem(Ptr) ({ if (!(Ptr)) {FailWithError ("Out of memory.");} })
  26. // Check if a given object with a given type is completely inside the file.
  27. #define IsInFile(Ptr,Type) ((Ptr) >= File && (Ptr) + sizeof (Type) <= File + FileSize)
  28. #define TestInFile(Ptr,Type) ({ if (!(IsInFile (Ptr, Type))) {FailWithError ("Corrupt A68k object file.");} })
  29. // Get next big-endian longint. We will need this in many places here, since
  30. // unlike COFF, AmigaOS-hunks is a sequential format, not a pointer-based one.
  31. #define GetNextTI4(Ptr) ({register TI4 __TI4;TestInFile(Ptr,TI4);__TI4=(*((TI4*)Ptr));Ptr+=4;ReadTI4(__TI4);})
  32. // Local Variables
  33. const I1 *File = ObjectFile->Data;
  34. SIZE FileSize = ObjectFile->Size;
  35. const char *FileName = ObjectFile->FileName;
  36. const I1 *ptr = File;
  37. I4 hunkSize;
  38. if (!File)
  39. return FALSE;
  40. // Read unit hunk
  41. if (GetNextTI4(ptr) != AMIGAOS_HUNK_UNIT)
  42. // This should already be trapped by IsAmigaOSFile, but just to make sure.
  43. FailWithError("Corrupt A68k object file (unit hunk missing).");
  44. hunkSize = GetNextTI4(ptr)<<2;
  45. TestInFile(ptr,I1[hunkSize]);
  46. ptr += hunkSize;
  47. while (ptr < (File + FileSize)) {
  48. I4 hunkType = GetNextTI4(ptr) & AMIGAOS_HUNK_TYPE_MASK;
  49. switch (hunkType) {
  50. case AMIGAOS_HUNK_UNIT:
  51. FailWithError("Corrupt A68k object file (duplicate unit hunk).");
  52. break;
  53. case AMIGAOS_HUNK_NAME:
  54. case AMIGAOS_HUNK_CODE:
  55. case AMIGAOS_HUNK_DATA:
  56. hunkSize = GetNextTI4(ptr)<<2;
  57. ptr += hunkSize;
  58. break;
  59. case AMIGAOS_HUNK_BSS:
  60. ptr += 4;
  61. break;
  62. case AMIGAOS_HUNK_RELOC_ABS2:
  63. case AMIGAOS_HUNK_RELOC_ABS4:
  64. case AMIGAOS_HUNK_RELOC_REL1:
  65. case AMIGAOS_HUNK_RELOC_REL2:
  66. case AMIGAOS_HUNK_RELOC_REL4:
  67. hunkSize = GetNextTI4(ptr)<<2;
  68. while (hunkSize) {
  69. ptr += hunkSize+4;
  70. hunkSize = GetNextTI4(ptr)<<2;
  71. }
  72. break;
  73. #ifdef AMIGAOS_TIGCC_EXTENSIONS
  74. case AMIGAOS_HUNK_RELOC_ABS4_POSNEG:
  75. case AMIGAOS_HUNK_RELOC_ABS2_POSNEG:
  76. case AMIGAOS_HUNK_RELOC_ABS1_POSNEG:
  77. hunkSize = GetNextTI4(ptr)<<4;
  78. ptr += hunkSize;
  79. break;
  80. #endif
  81. case AMIGAOS_HUNK_EXT:
  82. hunkSize = GetNextTI4(ptr);
  83. while (hunkSize) {
  84. // The most significant byte of the size longword encodes the symbol type.
  85. hunkType = hunkSize>>24;
  86. hunkSize = (hunkSize&0xffffffL)<<2;
  87. TestInFile(ptr,I1[hunkSize]);
  88. {
  89. char symName[hunkSize+1];
  90. strncpy(symName,ptr,hunkSize);
  91. symName[hunkSize] = 0;
  92. ptr += hunkSize;
  93. switch (hunkType) {
  94. case AMIGAOS_EXT_ABS:
  95. case AMIGAOS_EXT_DEF:
  96. ptr += 4;
  97. {
  98. SYMBOL *Symbol = calloc(1,sizeof(SYMBOL));
  99. TestMem(Symbol);
  100. Symbol->Parent = ObjectFile;
  101. strncpy(Symbol->Name,symName,MAX_SYM_LEN);
  102. Symbol->NameLength = strlen (Symbol->Name);
  103. Append(ObjectFile->Symbols,Symbol);
  104. ObjectFile->Parent->SymbolCount++;
  105. }
  106. break;
  107. case AMIGAOS_EXT_REF_ABS1:
  108. case AMIGAOS_EXT_REF_ABS2:
  109. case AMIGAOS_EXT_REF_ABS4:
  110. case AMIGAOS_EXT_REF_REL1:
  111. case AMIGAOS_EXT_REF_REL2:
  112. case AMIGAOS_EXT_REF_REL4:
  113. hunkSize = GetNextTI4(ptr)<<2;
  114. ptr += hunkSize;
  115. break;
  116. default:
  117. FailWithError("Unsupported AmigaOS symbol type `0x%lX'.",hunkType);
  118. break;
  119. }
  120. }
  121. hunkSize = GetNextTI4(ptr);
  122. }
  123. break;
  124. case AMIGAOS_HUNK_SYMBOL:
  125. hunkSize = GetNextTI4(ptr)<<2;
  126. while (hunkSize) {
  127. ptr += hunkSize+4;
  128. hunkSize = GetNextTI4(ptr)<<2;
  129. }
  130. break;
  131. case AMIGAOS_HUNK_END:
  132. break;
  133. default:
  134. FailWithError("Unsupported AmigaOS hunk type `0x%lX'.",hunkType);
  135. break;
  136. }
  137. }
  138. return TRUE; // success
  139. #undef GetNextTI4
  140. #undef TestInFile
  141. #undef IsInFile
  142. #undef TestMem
  143. #undef FailWithError
  144. #undef Fail
  145. }
  146. #endif /* AMIGAOS_SUPPORT */