imp_coff.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /* imp_coff.c: Routines to import a COFF file
  2. Copyright (C) 2002-2003 Sebastian Reichelt
  3. Copyright (C) 2003-2005 Kevin Kofler
  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_coff.h"
  16. #ifdef COFF_SUPPORT
  17. #include "../formats/coff.h"
  18. #include "../manip.h"
  19. #include "../special.h"
  20. #include "../bincode/fix_m68k.h"
  21. #include <stdlib.h>
  22. #include <string.h>
  23. // Extra Information for a COFF Section
  24. typedef struct {
  25. SECTION *Section;
  26. char Name[COFF_SECTION_NAME_LEN+1];
  27. OFFSET VAddr;
  28. } SEC_INFO;
  29. // Extra Information for a COFF Symbol
  30. typedef struct {
  31. SYMBOL *Symbol;
  32. } SYM_INFO;
  33. // Import a COFF file into the internal data structures.
  34. BOOLEAN ImportCOFFFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const char *FileName)
  35. {
  36. // Call this for a nice and clean failing exit.
  37. #define Fail() ({ if (SymInfo) free (SymInfo); if (SecInfo) free (SecInfo); return FALSE; })
  38. #define TestMem(Ptr) ({ if (!(Ptr)) { Error (FileName, "Out of memory."); Fail (); } })
  39. // Check if a given object with a given type is completely inside the file.
  40. #define IsInFile(Ptr,Type) (((const I1 *) (Ptr)) >= File && ((const I1 *) (Ptr)) + sizeof (Type) <= File + FileSize)
  41. #define TestInFile(Ptr,Type) ({ if (!(IsInFile (Ptr, Type))) { Error (FileName, "Corrupt COFF object file."); Fail (); } })
  42. // Local Variables
  43. COFF_INFO FileInfo;
  44. const COFF_HEADER *COFFHeader = (const COFF_HEADER *) File;
  45. const COFF_SECTIONS *COFFSections;
  46. const COFF_SYMBOLS *COFFSymbols;
  47. const char *COFFStringTable;
  48. SEC_INFO *SecInfo = NULL;
  49. SYM_INFO *SymInfo = NULL;
  50. BOOLEAN InitializeBSS = TRUE;
  51. BOOLEAN AllRelocs = FALSE;
  52. OFFSET CurCOFFSectionNumber, CurCOFFSymbolNumber, CurCOFFRelocNumber;
  53. // Create file information in FileInfo.
  54. CreateCoffInfo (*COFFHeader, FileInfo);
  55. // Get pointer to list of sections.
  56. COFFSections = (const COFF_SECTIONS *) (File + FileInfo.PSections);
  57. // Get pointer to list of symbols.
  58. COFFSymbols = (const COFF_SYMBOLS *) (File + FileInfo.PSymbols);
  59. // Get pointer to string table.
  60. COFFStringTable = (const char *) (File + FileInfo.PStrings);
  61. // *** Process File-Local Special Symbols ***
  62. // For each symbol...
  63. for (CurCOFFSymbolNumber = 0; CurCOFFSymbolNumber < FileInfo.SymbolCount; CurCOFFSymbolNumber++)
  64. {
  65. // Get pointer to this symbol.
  66. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [CurCOFFSymbolNumber]);
  67. TestInFile (CurCOFFSymbol, COFF_SYMBOL);
  68. // Only process long symbol names.
  69. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  70. {
  71. // If the name is special, set the appropriate flag.
  72. const char *SymName = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  73. TestInFile (SymName, char);
  74. if (!(strcmp (SymName, SYM_OMIT_BSS_INIT)))
  75. InitializeBSS = FALSE;
  76. else if (!(strcmp (SymName, SYM_ALL_RELOCS)))
  77. AllRelocs = TRUE;
  78. else if (!(strcmp (SymName, SYM_IGNORE_GLOBAL_IMPORTS)))
  79. Program->IgnoreGlobalImports = TRUE;
  80. }
  81. // Skip corresponding auxiliary symbols.
  82. CurCOFFSymbolNumber += ReadTI1 (CurCOFFSymbol->AuxSymbolCount);
  83. }
  84. // *** Import Sections ***
  85. // Create extra section information table.
  86. SecInfo = calloc (FileInfo.SectionCount, sizeof (SEC_INFO));
  87. TestMem (SecInfo);
  88. // For each section...
  89. for (CurCOFFSectionNumber = 0; CurCOFFSectionNumber < FileInfo.SectionCount; CurCOFFSectionNumber++)
  90. {
  91. OFFSET StartupNumber;
  92. // Get pointer to this section.
  93. const COFF_SECTION *CurCOFFSection = &((*COFFSections) [CurCOFFSectionNumber]);
  94. TestInFile (CurCOFFSection, COFF_SECTION);
  95. // Put name and virtual address into section information.
  96. strncpy (SecInfo[CurCOFFSectionNumber].Name, CurCOFFSection->Name, sizeof (CurCOFFSection->Name));
  97. SecInfo[CurCOFFSectionNumber].VAddr = ReadTI4 (CurCOFFSection->VirtualAddress);
  98. // At first, determine whether it is a startup section.
  99. // This is very important, as we cannot omit it.
  100. StartupNumber = GetStartupSectionNumber (CurCOFFSection->Name, sizeof (CurCOFFSection->Name));
  101. // Omit empty sections to simplify the output.
  102. if ((!StartupNumber) && (IsZeroI4 (CurCOFFSection->Size)))
  103. {
  104. // Section is empty.
  105. // Check if the number of relocs is empty as well. If not, there
  106. // is probably an error in the object file.
  107. if (!(IsZeroI4 (CurCOFFSection->RelocCount)))
  108. Warning (FileName, "Empty section %ld has relocs.", (long) CurCOFFSectionNumber);
  109. }
  110. else
  111. {
  112. // Section is not empty (or a startup section).
  113. I4 Flags = ReadTI4 (CurCOFFSection->Flags);
  114. // Try to allocate data for the section, if necessary.
  115. BOOLEAN HasData = (!(Flags & COFF_SECTION_BSS)) && (!(IsZeroI4 (CurCOFFSection->PData)));
  116. SIZE Size = ReadTI4 (CurCOFFSection->Size);
  117. I1 *Data = NULL;
  118. if (HasData)
  119. {
  120. const I1 *SrcData = File + ReadTI4 (CurCOFFSection->PData);
  121. TestInFile (SrcData, I1 [Size]);
  122. TestMem ((Data = calloc (Size, 1)));
  123. memcpy (Data, SrcData, Size);
  124. }
  125. {
  126. char *SectionName = SecInfo[CurCOFFSectionNumber].Name;
  127. // Create a new section.
  128. SECTION *Section = calloc (1, sizeof (SECTION));
  129. TestMem (Section);
  130. Section->Parent = Program;
  131. // Initialize the section.
  132. Section->Data = Data;
  133. Section->Size = Size;
  134. // If neither the code flag nor the data flag is specified, default to data for non-startup sections and to code for startup sections.
  135. Section->Code = Data && ((Flags & COFF_SECTION_TEXT) || (StartupNumber && (!(Flags & COFF_SECTION_DATA))));
  136. #ifdef COFF_TIGCC_EXTENSIONS
  137. // Read TIGCC COFF section flags.
  138. Section->Mergeable = !!(Flags & COFF_SECTION_MERGEABLE);
  139. Section->Unaligned = !!(Flags & COFF_SECTION_UNALIGNED);
  140. #endif
  141. Section->Initialized = Data || InitializeBSS;
  142. Section->StartupNumber = StartupNumber;
  143. Section->Constructors = (!(strcmp (SectionName, ".ctors")));
  144. Section->Destructors = (!(strcmp (SectionName, ".dtors")));
  145. #ifdef DEBUGGING_INFO_SUPPORT
  146. if (!strcmp (SectionName, ".stab"))
  147. Section->DebuggingInfoType = DI_STAB;
  148. else if (!strcmp (SectionName, ".stabstr"))
  149. Section->DebuggingInfoType = DI_STABSTR;
  150. #endif
  151. Section->CanCutRanges = AllRelocs;
  152. Section->FileName = FileName;
  153. // Append/insert the section.
  154. InsertSection (Program, Section);
  155. // Create a section symbol for this section.
  156. if (!(CreateSectionSymbol (Section, SectionName)))
  157. Fail ();
  158. // Put this section into the extra information table.
  159. SecInfo[CurCOFFSectionNumber].Section = Section;
  160. }
  161. // Now we are stuck: We should import the symbols all at once,
  162. // when all of the sections have been imported. We cannot import
  163. // the relocation entries now because they reference symbols. So
  164. // the only good way is to import all sections first, then import
  165. // all symbols, and then the relocs for each section.
  166. }
  167. }
  168. // *** Import Symbols ***
  169. // Create extra symbol information table.
  170. SymInfo = calloc (FileInfo.SymbolCount, sizeof (SYM_INFO));
  171. TestMem (SymInfo);
  172. // For each symbol...
  173. for (CurCOFFSymbolNumber = 0; CurCOFFSymbolNumber < FileInfo.SymbolCount; CurCOFFSymbolNumber++)
  174. {
  175. // Get pointer to this symbol.
  176. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [CurCOFFSymbolNumber]);
  177. TestInFile (CurCOFFSymbol, COFF_SYMBOL);
  178. {
  179. // Temporary placeholder for symbol section.
  180. OFFSET SymSection = (SI2) (ReadTI2 (CurCOFFSymbol->Section));
  181. // Temporary placeholder for symbol value.
  182. OFFSET SymVal = (SI4) (ReadTI4 (CurCOFFSymbol->Value));
  183. // Temporary placeholder for symbol class.
  184. I1 SymClass = (ReadTI1 (CurCOFFSymbol->Class));
  185. // Temporary placeholder for symbol name.
  186. char SymName[MAX_SYM_LEN+1];
  187. // Set to zero for terminating zero byte.
  188. memset (SymName, 0, MAX_SYM_LEN + 1);
  189. // COFF symbol names are stored in a strange way. This is how to get them.
  190. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  191. {
  192. const char *Str = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  193. TestInFile (Str, char);
  194. strncpy (SymName, Str, MAX_SYM_LEN);
  195. }
  196. else
  197. strncpy (SymName, CurCOFFSymbol->Name.Name, 8);
  198. // Handle the symbol if it is special for this linker, only proceed if not.
  199. if (!(HandleSpecialSymbol (Program, SymName)))
  200. {
  201. // Check if the section number is nonzero. If it is zero, the symbol
  202. // is somewhat special.
  203. if (SymSection)
  204. {
  205. // Check if the section number is positive and the class is
  206. // <100. If not, the symbol is very special, e.g. absolute
  207. // or debugging; so ignore it.
  208. if (SymSection > 0 && SymClass < 100)
  209. {
  210. // Check if the section number is valid.
  211. if (SymSection <= FileInfo.SectionCount)
  212. {
  213. SECTION *Section = SecInfo[SymSection-1].Section;
  214. // The symbol is a real label in a real section.
  215. // First, check whether we didn't omit the section.
  216. // If we did, no problem; we need to give an error only if
  217. // someone actually uses the symbol (in a reloc).
  218. if (Section)
  219. {
  220. BOOLEAN Exported = (ReadTI1 (CurCOFFSymbol->Class) == COFF_SYMBOL_EXTERNAL);
  221. OFFSET Location = SymVal - SecInfo[SymSection-1].VAddr;
  222. if ((Location == 0) && (!Exported) && (!(strncmp (SymName, SecInfo[SymSection-1].Name, COFF_SECTION_NAME_LEN))))
  223. {
  224. // Use the section symbol instead.
  225. SymInfo[CurCOFFSymbolNumber].Symbol = Section->SectionSymbol;
  226. // Rename the section symbol to the full section name as stored in the symbol.
  227. CreateSectionSymbol (Section, SymName);
  228. }
  229. else
  230. {
  231. // Simply create a new symbol entry in that section.
  232. SYMBOL *Symbol = calloc (1, sizeof (SYMBOL));
  233. TestMem (Symbol);
  234. Symbol->Parent = Section;
  235. Symbol->Location = Location;
  236. strcpy (Symbol->Name, SymName);
  237. Symbol->Exported = Exported;
  238. InsertSymbol (Section, Symbol);
  239. // Put this symbol in the extra information table.
  240. SymInfo[CurCOFFSymbolNumber].Symbol = Symbol;
  241. }
  242. }
  243. }
  244. else
  245. Warning (FileName, "Ignoring symbol in nonexisting section number %ld.", (long) SymSection);
  246. }
  247. }
  248. else
  249. {
  250. // The section number is zero. This may have two reasons:
  251. // If the value is zero as well, this is an external reference.
  252. // If the value is positive, the symbol is a common uninitialized
  253. // symbol (i.e. BSS).
  254. if (SymVal > 0)
  255. {
  256. // The symbol is a common uninitialized symbol. Make one and
  257. // put it in the extra information table.
  258. if (!((SymInfo[CurCOFFSymbolNumber].Symbol = MakeCommonSymbol (Program, SymName, SymVal, InitializeBSS, FileName))))
  259. Fail ();
  260. }
  261. // Otherwise, the symbol is an external reference or some strange
  262. // unknown thing; we cannot handle it any further here, as we
  263. // cannot assign it to a section.
  264. }
  265. }
  266. }
  267. // Skip corresponding auxiliary symbols.
  268. CurCOFFSymbolNumber += ReadTI1 (CurCOFFSymbol->AuxSymbolCount);
  269. }
  270. // *** Import Relocation Entries ***
  271. // For each section...
  272. for (CurCOFFSectionNumber = 0; CurCOFFSectionNumber < FileInfo.SectionCount; CurCOFFSectionNumber++)
  273. {
  274. const RELOC *RelocHint = NULL;
  275. // Get pointer to this section.
  276. const COFF_SECTION *CurCOFFSection = &((*COFFSections) [CurCOFFSectionNumber]);
  277. // Get pointer to section in internal data structure.
  278. SECTION *Section = SecInfo[CurCOFFSectionNumber].Section;
  279. // Only proceed if we didn't omit the section.
  280. if (Section)
  281. {
  282. COUNT RelocCount = ReadTI2 (CurCOFFSection->RelocCount);
  283. const COFF_RELOCS *CurCOFFRelocs = (const COFF_RELOCS *) (File + ReadTI4 (CurCOFFSection->PRelocs));
  284. // For each reloc...
  285. for (CurCOFFRelocNumber = 0; CurCOFFRelocNumber < RelocCount; CurCOFFRelocNumber++)
  286. {
  287. OFFSET SymNum, COFFLocation;
  288. // Get pointer to this reloc.
  289. const COFF_RELOC *CurCOFFReloc = &((*CurCOFFRelocs) [CurCOFFRelocNumber]);
  290. TestInFile (CurCOFFReloc, COFF_RELOC);
  291. // Read the location (for better error messages).
  292. COFFLocation = ReadTI4 (CurCOFFReloc->Location);
  293. // Temporary placeholder for symbol number.
  294. SymNum = ReadTI4 (CurCOFFReloc->Symbol);
  295. // Check if the symbol number is valid.
  296. if (SymNum >= 0 && SymNum < FileInfo.SymbolCount)
  297. {
  298. // Determine the reloc's size and relation.
  299. SIZE RelocSize = 0;
  300. BOOLEAN Relative = FALSE;
  301. BOOLEAN Negative = FALSE;
  302. BOOLEAN Unoptimizable = FALSE;
  303. I2 RelocType = ReadTI2 (CurCOFFReloc->Type);
  304. #ifdef COFF_TIGCC_EXTENSIONS
  305. Unoptimizable = (RelocType & COFF_RELOC_UNOPTIMIZABLE);
  306. RelocType &= ~COFF_RELOC_UNOPTIMIZABLE;
  307. #endif
  308. switch (RelocType)
  309. {
  310. case COFF_RELOC_REL1:
  311. Relative = TRUE;
  312. case COFF_RELOC_ABS1:
  313. RelocSize = 1;
  314. break;
  315. case COFF_RELOC_REL2:
  316. Relative = TRUE;
  317. case COFF_RELOC_ABS2:
  318. RelocSize = 2;
  319. break;
  320. case COFF_RELOC_REL4:
  321. Relative = TRUE;
  322. case COFF_RELOC_ABS4:
  323. RelocSize = 4;
  324. break;
  325. #ifdef COFF_TIGCC_EXTENSIONS
  326. case COFF_RELOC_ABS1_NEG:
  327. RelocSize = 1;
  328. Negative = TRUE;
  329. break;
  330. case COFF_RELOC_ABS2_NEG:
  331. RelocSize = 2;
  332. Negative = TRUE;
  333. break;
  334. #endif
  335. case COFF_RELOC_ABS4_NEG:
  336. RelocSize = 4;
  337. Negative = TRUE;
  338. break;
  339. }
  340. // Check whether we were able to translate the reloc type.
  341. if (RelocSize > 0)
  342. {
  343. OFFSET Location = COFFLocation - SecInfo[CurCOFFSectionNumber].VAddr;
  344. SYMBOL *Symbol = SymInfo[SymNum].Symbol;
  345. // Check if we really imported the target symbol.
  346. if (Symbol)
  347. {
  348. // Yes, we did.
  349. // Find the virtual address of the target section.
  350. // We will need this to subtract the virtual location of the target symbol.
  351. OFFSET VAddr = 0;
  352. OFFSET COFFSec;
  353. for (COFFSec = 0; COFFSec < FileInfo.SectionCount; COFFSec++)
  354. {
  355. if (SecInfo[COFFSec].Section == Symbol->Parent)
  356. {
  357. VAddr = SecInfo[COFFSec].VAddr;
  358. break;
  359. }
  360. }
  361. // Handle negative relocs by searching for matching positive ones.
  362. if (Negative)
  363. {
  364. // Search for a matching positive reloc.
  365. RELOC *PositiveReloc = FindMatchingReloc (Section, Location, RelocSize, FALSE, NULL, RelocHint);
  366. // We can only do something with the negative reloc
  367. // if we have found a matching positive one.
  368. if (PositiveReloc)
  369. {
  370. // Make the positive reloc relative, with
  371. // this reloc's target as the relation.
  372. LOCATION *Relation = calloc (1, sizeof (LOCATION));
  373. TestMem (Relation);
  374. Relation->Symbol = Symbol;
  375. Relation->SymbolName = Relation->Symbol->Name;
  376. PositiveReloc->Relative = TRUE;
  377. PositiveReloc->Relation = Relation;
  378. // Subtract the target offset for this reloc
  379. // from the positive reloc's fixed offset.
  380. PositiveReloc->FixedOffset += VAddr + Symbol->Location;
  381. HandleLocation (PositiveReloc, Relation);
  382. RelocHint = PositiveReloc;
  383. }
  384. else
  385. Warning (FileName, "Removing negative reloc at 0x%lX in section %ld to `%s' with no matching positive reloc.", (long) Location, (long) CurCOFFSectionNumber, Symbol->Name);
  386. }
  387. else // Positive
  388. {
  389. OFFSET Offset = 0;
  390. // Now all we need to do is to set up a reloc to this symbol.
  391. RELOC *Reloc = calloc (1, sizeof (RELOC));
  392. TestMem (Reloc);
  393. Reloc->Parent = Section;
  394. Reloc->Location = Location;
  395. Reloc->Target.Symbol = Symbol;
  396. Reloc->Target.SymbolName = Reloc->Target.Symbol->Name;
  397. Reloc->Size = RelocSize;
  398. Reloc->Relative = Relative;
  399. Reloc->Unoptimizable = Unoptimizable;
  400. // Calculate the reloc's target offset.
  401. // The section contents contain the virtual
  402. // address of the target.
  403. if ((Location >= 0) && (Location + RelocSize <= Section->Size))
  404. {
  405. if (Section->Data)
  406. {
  407. Offset = ReadSTI (Section->Data + Location, RelocSize);
  408. memset (Section->Data + Location, 0, RelocSize);
  409. }
  410. else
  411. Warning (FileName, "Adding reloc %ld at 0x%lX in section %ld without data to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  412. }
  413. else
  414. Warning (FileName, "Adding reloc %ld at 0x%lX outside of section %ld to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  415. // Subtract the virtual address of the target symbol,
  416. // since we only want the difference to the symbol.
  417. Offset -= VAddr + Symbol->Location;
  418. // Relative relocs contain the difference between
  419. // the virtual target address and the current
  420. // virtual address. So we have to add the current
  421. // virtual address to get only the offset.
  422. if (Relative)
  423. Offset += Location + SecInfo[CurCOFFSectionNumber].VAddr;
  424. // For compatibility with files generated by
  425. // unpatched versions of GNU as, treat offsets from
  426. // section symbols as TargetOffset rather than
  427. // FixedOffset.
  428. // Apply architecture-specific fixes to the target offset.
  429. // These fixes are not needed if the correct target
  430. // symbol is referenced.
  431. if (Symbol == Symbol->Parent->SectionSymbol)
  432. Reloc->Target.Offset = ((Section->Code && Symbol->Parent->Code) ? M68kFixTargetOffset (Offset, RelocSize, Relative) : Offset);
  433. // Calculate the remaining part of the offset.
  434. Reloc->FixedOffset = Offset - Reloc->Target.Offset;
  435. // Append the reloc to the linked list.
  436. InsertReloc (Section, Reloc);
  437. }
  438. }
  439. else
  440. {
  441. // No, we didn't. We have to find the cause of this.
  442. // If it is an externally defined symbol, set up a
  443. // reloc anyway. If not, give a warning.
  444. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [SymNum]);
  445. // Check whether it is an external symbol.
  446. if (IsZeroI2 (CurCOFFSymbol->Section) && IsZeroI4 (CurCOFFSymbol->Value))
  447. {
  448. // Read the symbol name.
  449. char *SymName = calloc (MAX_SYM_LEN + 1, 1);
  450. TestMem (SymName);
  451. // COFF symbol names are stored in a strange way. This is how to get them.
  452. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  453. {
  454. const char *Str = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  455. TestInFile (Str, char);
  456. strncpy (SymName, Str, MAX_SYM_LEN);
  457. }
  458. else
  459. strncpy (SymName, CurCOFFSymbol->Name.Name, 8);
  460. // Set up the reloc, without a specified symbol.
  461. // Handle negative relocs by searching for matching positive ones.
  462. if (Negative)
  463. {
  464. // Search for a matching positive reloc.
  465. RELOC *PositiveReloc = FindMatchingReloc (Section, Location, RelocSize, FALSE, NULL, RelocHint);
  466. // We can only do something with the negative reloc
  467. // if we have found a matching positive one.
  468. if (PositiveReloc)
  469. {
  470. // Make the positive reloc relative, with
  471. // this reloc's target as the relation.
  472. LOCATION *Relation = calloc (1, sizeof (LOCATION));
  473. TestMem (Relation);
  474. Relation->SymbolName = SymName;
  475. PositiveReloc->Relative = TRUE;
  476. PositiveReloc->Relation = Relation;
  477. HandleLocation (PositiveReloc, Relation);
  478. RelocHint = PositiveReloc;
  479. }
  480. else
  481. Warning (FileName, "Removing negative reloc at 0x%lX in section %ld to `%s' with no matching positive reloc.", (long) Location, (long) CurCOFFSectionNumber, SymName);
  482. }
  483. else // Positive
  484. {
  485. RELOC *Reloc = calloc (1, sizeof (RELOC));
  486. TestMem (Reloc);
  487. Reloc->Parent = Section;
  488. Reloc->Location = Location;
  489. Reloc->Target.SymbolName = SymName;
  490. Reloc->Size = RelocSize;
  491. Reloc->Relative = Relative;
  492. Reloc->Unoptimizable = Unoptimizable;
  493. // Calculate the reloc's target offset
  494. // (which is written into the fixed offset).
  495. // The section contents contain the virtual
  496. // address of the target.
  497. if (Location >= 0 && Location + RelocSize <= Section->Size)
  498. {
  499. if (Section->Data)
  500. {
  501. Reloc->FixedOffset = ReadSTI (Section->Data + Location, RelocSize);
  502. memset (Section->Data + Location, 0, RelocSize);
  503. }
  504. else
  505. Warning (FileName, "Adding reloc %ld at 0x%lX in section %ld without data to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  506. }
  507. else
  508. Warning (FileName, "Adding reloc %ld at 0x%lX outside of section %ld to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  509. // Relative relocs contain the difference between
  510. // the virtual target address (which is 0 or some
  511. // small offset in this case) and the current
  512. // virtual address. So we have to add the current
  513. // virtual address to get only the offset.
  514. if (Relative)
  515. Reloc->FixedOffset += Location + SecInfo[CurCOFFSectionNumber].VAddr;
  516. // Add the reloc to the section.
  517. InsertReloc (Section, Reloc);
  518. }
  519. }
  520. else
  521. Warning (FileName, "Ignoring reloc %ld at 0x%lX in section %ld to unimported symbol %ld.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, (long) SymNum);
  522. }
  523. }
  524. else
  525. Warning (FileName, "Ignoring reloc %ld at 0x%lX in section %ld with unknown type `0x%lX'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, (long) (ReadTI2 (CurCOFFReloc->Type)));
  526. }
  527. else
  528. Warning (FileName, "Ignoring reloc %ld at 0x%lX in section %ld to nonexisting symbol %ld.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, (long) SymNum);
  529. }
  530. }
  531. }
  532. // *** Finished ***
  533. // Free allocated memory and exit with a positive result.
  534. free (SymInfo);
  535. free (SecInfo);
  536. return TRUE;
  537. #undef TestInFile
  538. #undef IsInFile
  539. #undef TestMem
  540. #undef Fail
  541. }
  542. #endif /* COFF_SUPPORT */