imp_coff.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* imp_coff.c: Routines to import a COFF file
  2. Copyright (C) 2003 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_coff.h"
  15. #ifdef COFF_SUPPORT
  16. #include "../../formats/coff.h"
  17. #include <stdlib.h>
  18. #include <string.h>
  19. // Import the exported symbols of a COFF file.
  20. BOOLEAN ArImportCOFFFile (OBJECT_FILE *ObjectFile)
  21. {
  22. // Call this for a nice and clean failing exit.
  23. #define Fail() ({ return FALSE; })
  24. #define TestMem(Ptr) ({ if (!(Ptr)) { Error (FileName, "Out of memory."); Fail (); } })
  25. // Check if a given object with a given type is completely inside the file.
  26. #define IsInFile(Ptr,Type) ((((const I1 *) (Ptr)) >= File) && (((const I1 *) (Ptr)) + sizeof (Type) <= File + FileSize))
  27. #define TestInFile(Ptr,Type) ({ if (!(IsInFile (Ptr, Type))) { Error (FileName, "Corrupt COFF object file."); Fail (); } })
  28. // Local Variables
  29. const I1 *File = ObjectFile->Data;
  30. SIZE FileSize = ObjectFile->Size;
  31. const char *FileName = ObjectFile->FileName;
  32. COFF_INFO FileInfo;
  33. const COFF_HEADER *COFFHeader = (const COFF_HEADER *) File;
  34. const COFF_SECTIONS *COFFSections;
  35. const COFF_SYMBOLS *COFFSymbols;
  36. const char *COFFStringTable;
  37. OFFSET CurCOFFSymbolNumber;
  38. if (!File)
  39. return FALSE;
  40. // Create file information in FileInfo.
  41. CreateCoffInfo (*COFFHeader, FileInfo);
  42. // Get pointer to list of sections.
  43. COFFSections = (const COFF_SECTIONS *) (File + FileInfo.PSections);
  44. // Get pointer to list of symbols.
  45. COFFSymbols = (const COFF_SYMBOLS *) (File + FileInfo.PSymbols);
  46. // Get pointer to string table.
  47. COFFStringTable = (const char *) (File + FileInfo.PStrings);
  48. // For each symbol...
  49. for (CurCOFFSymbolNumber = 0; CurCOFFSymbolNumber < FileInfo.SymbolCount; CurCOFFSymbolNumber++)
  50. {
  51. // Get pointer to this symbol.
  52. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [CurCOFFSymbolNumber]);
  53. TestInFile (CurCOFFSymbol, COFF_SYMBOL);
  54. {
  55. // Check whether the symbol is exported.
  56. if (ReadTI1 (CurCOFFSymbol->Class) == COFF_SYMBOL_EXTERNAL)
  57. {
  58. // Of course, a single attribute for exported symbols would
  59. // be too easy. In COFF, finding out whether it is exported
  60. // is a little complicated and dirty: If the symbol is
  61. // "external" but lives in a specific section, this means
  62. // that it is exported. If it does not live in a section, but
  63. // still has a value, it is a common symbol; I think we can
  64. // look at "external" common symbols as exported, too, even
  65. // though multiple files can export them at once. If it does
  66. // not have a section or value, it is either an imported
  67. // symbol (which should be ignored) or an exported symbol
  68. // which is declared but never defined (and since this is a
  69. // convenient way of passing information to the linker
  70. // without cluttering the source code, we should not ignore
  71. // this kind of symbol). The only way to distinguish these
  72. // two kinds of symbols seems to be to look for a reloc using
  73. // the symbol. If a reloc exists, it is definitely an
  74. // imported symbol. If none exists, it is hopefully an
  75. // exported symbol.
  76. BOOLEAN Exported = TRUE;
  77. if ((IsZeroI2 (CurCOFFSymbol->Section)) && (IsZeroI4 (CurCOFFSymbol->Value)))
  78. {
  79. OFFSET CurCOFFSectionNumber;
  80. // For each section...
  81. for (CurCOFFSectionNumber = 0; (CurCOFFSectionNumber < FileInfo.SectionCount) && Exported; CurCOFFSectionNumber++)
  82. {
  83. // Get pointer to this section.
  84. const COFF_SECTION *CurCOFFSection = &((*COFFSections) [CurCOFFSectionNumber]);
  85. TestInFile (CurCOFFSection, COFF_SECTION);
  86. {
  87. // Get info about relocs.
  88. COUNT RelocCount = ReadTI2 (CurCOFFSection->RelocCount);
  89. const COFF_RELOCS *CurCOFFRelocs = (const COFF_RELOCS *) (File + ReadTI4 (CurCOFFSection->PRelocs));
  90. OFFSET CurCOFFRelocNumber;
  91. // For each reloc...
  92. for (CurCOFFRelocNumber = 0; CurCOFFRelocNumber < RelocCount; CurCOFFRelocNumber++)
  93. {
  94. // Get pointer to this reloc.
  95. const COFF_RELOC *CurCOFFReloc = &((*CurCOFFRelocs) [CurCOFFRelocNumber]);
  96. TestInFile (CurCOFFReloc, COFF_RELOC);
  97. // Test if the reloc points to the current symbol.
  98. if ((OFFSET) (ReadTI4 (CurCOFFReloc->Symbol)) == CurCOFFSymbolNumber)
  99. {
  100. // It did. So the symbol is imported, not exported.
  101. Exported = FALSE;
  102. break;
  103. }
  104. }
  105. }
  106. }
  107. }
  108. // Only add symbols which are really exported.
  109. if (Exported)
  110. {
  111. // Create a new symbol inside the archive.
  112. SYMBOL *Symbol = calloc (1, sizeof (SYMBOL));
  113. TestMem (Symbol);
  114. Symbol->Parent = ObjectFile;
  115. // COFF symbol names are stored in a strange way. This is how to get them.
  116. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  117. {
  118. const char *Str = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  119. TestInFile (Str, char);
  120. strncpy (Symbol->Name, Str, MAX_SYM_LEN);
  121. }
  122. else
  123. strncpy (Symbol->Name, CurCOFFSymbol->Name.Name, 8);
  124. Symbol->NameLength = strlen (Symbol->Name);
  125. // Add the symbol to the linked list.
  126. Append (ObjectFile->Symbols, Symbol);
  127. ObjectFile->Parent->SymbolCount++;
  128. }
  129. }
  130. }
  131. // Skip corresponding auxiliary symbols.
  132. CurCOFFSymbolNumber += ReadTI1 (CurCOFFSymbol->AuxSymbolCount);
  133. }
  134. // Exit with a positive result.
  135. return TRUE;
  136. #undef TestInFile
  137. #undef IsInFile
  138. #undef TestMem
  139. #undef Fail
  140. }
  141. #endif /* COFF_SUPPORT */