imp_amig.c 5.0 KB

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