imp_coff.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /* imp_coff.c: Routines to import a COFF file
  2. Copyright (C) 2002-2003 Sebastian Reichelt
  3. Copyright (C) 2003-2004 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. Section->CanCutRanges = AllRelocs;
  146. Section->FileName = FileName;
  147. // Append/insert the section.
  148. InsertSection (Program, Section);
  149. // Create a section symbol for this section.
  150. if (!(CreateSectionSymbol (Section, SectionName)))
  151. Fail ();
  152. // Put this section into the extra information table.
  153. SecInfo[CurCOFFSectionNumber].Section = Section;
  154. }
  155. // Now we are stuck: We should import the symbols all at once,
  156. // when all of the sections have been imported. We cannot import
  157. // the relocation entries now because they reference symbols. So
  158. // the only good way is to import all sections first, then import
  159. // all symbols, and then the relocs for each section.
  160. }
  161. }
  162. // *** Import Symbols ***
  163. // Create extra symbol information table.
  164. SymInfo = calloc (FileInfo.SymbolCount, sizeof (SYM_INFO));
  165. TestMem (SymInfo);
  166. // For each symbol...
  167. for (CurCOFFSymbolNumber = 0; CurCOFFSymbolNumber < FileInfo.SymbolCount; CurCOFFSymbolNumber++)
  168. {
  169. // Get pointer to this symbol.
  170. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [CurCOFFSymbolNumber]);
  171. TestInFile (CurCOFFSymbol, COFF_SYMBOL);
  172. {
  173. // Temporary placeholder for symbol section.
  174. OFFSET SymSection = (SI2) (ReadTI2 (CurCOFFSymbol->Section));
  175. // Temporary placeholder for symbol value.
  176. OFFSET SymVal = (SI4) (ReadTI4 (CurCOFFSymbol->Value));
  177. // Temporary placeholder for symbol class.
  178. I1 SymClass = (ReadTI1 (CurCOFFSymbol->Class));
  179. // Temporary placeholder for symbol name.
  180. char SymName[MAX_SYM_LEN+1];
  181. // Set to zero for terminating zero byte.
  182. memset (SymName, 0, MAX_SYM_LEN + 1);
  183. // COFF symbol names are stored in a strange way. This is how to get them.
  184. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  185. {
  186. const char *Str = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  187. TestInFile (Str, char);
  188. strncpy (SymName, Str, MAX_SYM_LEN);
  189. }
  190. else
  191. strncpy (SymName, CurCOFFSymbol->Name.Name, 8);
  192. // Handle the symbol if it is special for this linker, only proceed if not.
  193. if (!(HandleSpecialSymbol (Program, SymName)))
  194. {
  195. // Check if the section number is nonzero. If it is zero, the symbol
  196. // is somewhat special.
  197. if (SymSection)
  198. {
  199. // Check if the section number is positive and the class is
  200. // <100. If not, the symbol is very special, e.g. absolute
  201. // or debugging; so ignore it.
  202. if (SymSection > 0 && SymClass < 100)
  203. {
  204. // Check if the section number is valid.
  205. if (SymSection <= FileInfo.SectionCount)
  206. {
  207. SECTION *Section = SecInfo[SymSection-1].Section;
  208. // The symbol is a real label in a real section.
  209. // First, check whether we didn't omit the section.
  210. // If we did, no problem; we need to give an error only if
  211. // someone actually uses the symbol (in a reloc).
  212. if (Section)
  213. {
  214. BOOLEAN Exported = (ReadTI1 (CurCOFFSymbol->Class) == COFF_SYMBOL_EXTERNAL);
  215. OFFSET Location = SymVal - SecInfo[SymSection-1].VAddr;
  216. if ((Location == 0) && (!Exported) && (!(strncmp (SymName, SecInfo[SymSection-1].Name, COFF_SECTION_NAME_LEN))))
  217. {
  218. // Use the section symbol instead.
  219. SymInfo[CurCOFFSymbolNumber].Symbol = Section->SectionSymbol;
  220. // Rename the section symbol to the full section name as stored in the symbol.
  221. CreateSectionSymbol (Section, SymName);
  222. }
  223. else
  224. {
  225. // Simply create a new symbol entry in that section.
  226. SYMBOL *Symbol = calloc (1, sizeof (SYMBOL));
  227. TestMem (Symbol);
  228. Symbol->Parent = Section;
  229. Symbol->Location = Location;
  230. strcpy (Symbol->Name, SymName);
  231. Symbol->Exported = Exported;
  232. InsertSymbol (Section, Symbol);
  233. // Put this symbol in the extra information table.
  234. SymInfo[CurCOFFSymbolNumber].Symbol = Symbol;
  235. }
  236. }
  237. }
  238. else
  239. Warning (FileName, "Ignoring symbol in nonexisting section number %ld.", (long) SymSection);
  240. }
  241. }
  242. else
  243. {
  244. // The section number is zero. This may have two reasons:
  245. // If the value is zero as well, this is an external reference.
  246. // If the value is positive, the symbol is a common uninitialized
  247. // symbol (i.e. BSS).
  248. if (SymVal > 0)
  249. {
  250. // The symbol is a common uninitialized symbol. Make one and
  251. // put it in the extra information table.
  252. if (!((SymInfo[CurCOFFSymbolNumber].Symbol = MakeCommonSymbol (Program, SymName, SymVal, InitializeBSS, FileName))))
  253. Fail ();
  254. }
  255. // Otherwise, the symbol is an external reference or some strange
  256. // unknown thing; we cannot handle it any further here, as we
  257. // cannot assign it to a section.
  258. }
  259. }
  260. }
  261. // Skip corresponding auxiliary symbols.
  262. CurCOFFSymbolNumber += ReadTI1 (CurCOFFSymbol->AuxSymbolCount);
  263. }
  264. // *** Import Relocation Entries ***
  265. // For each section...
  266. for (CurCOFFSectionNumber = 0; CurCOFFSectionNumber < FileInfo.SectionCount; CurCOFFSectionNumber++)
  267. {
  268. const RELOC *RelocHint = NULL;
  269. // Get pointer to this section.
  270. const COFF_SECTION *CurCOFFSection = &((*COFFSections) [CurCOFFSectionNumber]);
  271. // Get pointer to section in internal data structure.
  272. SECTION *Section = SecInfo[CurCOFFSectionNumber].Section;
  273. // Only proceed if we didn't omit the section.
  274. if (Section)
  275. {
  276. COUNT RelocCount = ReadTI2 (CurCOFFSection->RelocCount);
  277. const COFF_RELOCS *CurCOFFRelocs = (const COFF_RELOCS *) (File + ReadTI4 (CurCOFFSection->PRelocs));
  278. // For each reloc...
  279. for (CurCOFFRelocNumber = 0; CurCOFFRelocNumber < RelocCount; CurCOFFRelocNumber++)
  280. {
  281. OFFSET SymNum, COFFLocation;
  282. // Get pointer to this reloc.
  283. const COFF_RELOC *CurCOFFReloc = &((*CurCOFFRelocs) [CurCOFFRelocNumber]);
  284. TestInFile (CurCOFFReloc, COFF_RELOC);
  285. // Read the location (for better error messages).
  286. COFFLocation = ReadTI4 (CurCOFFReloc->Location);
  287. // Temporary placeholder for symbol number.
  288. SymNum = ReadTI4 (CurCOFFReloc->Symbol);
  289. // Check if the symbol number is valid.
  290. if (SymNum >= 0 && SymNum < FileInfo.SymbolCount)
  291. {
  292. // Determine the reloc's size and relation.
  293. SIZE RelocSize = 0;
  294. BOOLEAN Relative = FALSE;
  295. BOOLEAN Negative = FALSE;
  296. BOOLEAN Unoptimizable = FALSE;
  297. I2 RelocType = ReadTI2 (CurCOFFReloc->Type);
  298. #ifdef COFF_TIGCC_EXTENSIONS
  299. Unoptimizable = (RelocType & COFF_RELOC_UNOPTIMIZABLE);
  300. RelocType &= ~COFF_RELOC_UNOPTIMIZABLE;
  301. #endif
  302. switch (RelocType)
  303. {
  304. case COFF_RELOC_REL1:
  305. Relative = TRUE;
  306. case COFF_RELOC_ABS1:
  307. RelocSize = 1;
  308. break;
  309. case COFF_RELOC_REL2:
  310. Relative = TRUE;
  311. case COFF_RELOC_ABS2:
  312. RelocSize = 2;
  313. break;
  314. case COFF_RELOC_REL4:
  315. Relative = TRUE;
  316. case COFF_RELOC_ABS4:
  317. RelocSize = 4;
  318. break;
  319. #ifdef COFF_TIGCC_EXTENSIONS
  320. case COFF_RELOC_ABS1_NEG:
  321. RelocSize = 1;
  322. Negative = TRUE;
  323. break;
  324. case COFF_RELOC_ABS2_NEG:
  325. RelocSize = 2;
  326. Negative = TRUE;
  327. break;
  328. #endif
  329. case COFF_RELOC_ABS4_NEG:
  330. RelocSize = 4;
  331. Negative = TRUE;
  332. break;
  333. }
  334. // Check whether we were able to translate the reloc type.
  335. if (RelocSize > 0)
  336. {
  337. OFFSET Location = COFFLocation - SecInfo[CurCOFFSectionNumber].VAddr;
  338. SYMBOL *Symbol = SymInfo[SymNum].Symbol;
  339. // Check if we really imported the target symbol.
  340. if (Symbol)
  341. {
  342. // Yes, we did.
  343. // Find the virtual address of the target section.
  344. // We will need this to subtract the virtual location of the target symbol.
  345. OFFSET VAddr = 0;
  346. OFFSET COFFSec;
  347. for (COFFSec = 0; COFFSec < FileInfo.SectionCount; COFFSec++)
  348. {
  349. if (SecInfo[COFFSec].Section == Symbol->Parent)
  350. {
  351. VAddr = SecInfo[COFFSec].VAddr;
  352. break;
  353. }
  354. }
  355. // Handle negative relocs by searching for matching positive ones.
  356. if (Negative)
  357. {
  358. // Search for a matching positive reloc.
  359. RELOC *PositiveReloc = FindMatchingReloc (Section, Location, RelocSize, FALSE, NULL, RelocHint);
  360. // We can only do something with the negative reloc
  361. // if we have found a matching positive one.
  362. if (PositiveReloc)
  363. {
  364. // Make the positive reloc relative, with
  365. // this reloc's target as the relation.
  366. LOCATION *Relation = calloc (1, sizeof (LOCATION));
  367. TestMem (Relation);
  368. Relation->Symbol = Symbol;
  369. Relation->SymbolName = Relation->Symbol->Name;
  370. PositiveReloc->Relative = TRUE;
  371. PositiveReloc->Relation = Relation;
  372. // Subtract the target offset for this reloc
  373. // from the positive reloc's fixed offset.
  374. PositiveReloc->FixedOffset += VAddr + Symbol->Location;
  375. HandleLocation (PositiveReloc, Relation);
  376. RelocHint = PositiveReloc;
  377. }
  378. else
  379. Warning (FileName, "Removing negative reloc at 0x%lX in section %ld to `%s' with no matching positive reloc.", (long) Location, (long) CurCOFFSectionNumber, Symbol->Name);
  380. }
  381. else // Positive
  382. {
  383. OFFSET Offset = 0;
  384. // Now all we need to do is to set up a reloc to this symbol.
  385. RELOC *Reloc = calloc (1, sizeof (RELOC));
  386. TestMem (Reloc);
  387. Reloc->Parent = Section;
  388. Reloc->Location = Location;
  389. Reloc->Target.Symbol = Symbol;
  390. Reloc->Target.SymbolName = Reloc->Target.Symbol->Name;
  391. Reloc->Size = RelocSize;
  392. Reloc->Relative = Relative;
  393. Reloc->Unoptimizable = Unoptimizable;
  394. // Calculate the reloc's target offset.
  395. // The section contents contain the virtual
  396. // address of the target.
  397. if ((Location >= 0) && (Location + RelocSize <= Section->Size))
  398. {
  399. if (Section->Data)
  400. {
  401. Offset = ReadSTI (Section->Data + Location, RelocSize);
  402. memset (Section->Data + Location, 0, RelocSize);
  403. }
  404. else
  405. Warning (FileName, "Adding reloc %ld at 0x%lX in section %ld without data to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  406. }
  407. else
  408. Warning (FileName, "Adding reloc %ld at 0x%lX outside of section %ld to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  409. // Subtract the virtual address of the target symbol,
  410. // since we only want the difference to the symbol.
  411. Offset -= VAddr + Symbol->Location;
  412. // Relative relocs contain the difference between
  413. // the virtual target address and the current
  414. // virtual address. So we have to add the current
  415. // virtual address to get only the offset.
  416. if (Relative)
  417. Offset += Location + SecInfo[CurCOFFSectionNumber].VAddr;
  418. // For compatibility with files generated by
  419. // unpatched versions of GNU as, treat offsets from
  420. // section symbols as TargetOffset rather than
  421. // FixedOffset.
  422. // Apply architecture-specific fixes to the target offset.
  423. // These fixes are not needed if the correct target
  424. // symbol is referenced.
  425. if (Symbol == Symbol->Parent->SectionSymbol)
  426. Reloc->Target.Offset = ((Section->Code && Symbol->Parent->Code) ? M68kFixTargetOffset (Offset, RelocSize, Relative) : Offset);
  427. // Calculate the remaining part of the offset.
  428. Reloc->FixedOffset = Offset - Reloc->Target.Offset;
  429. // Append the reloc to the linked list.
  430. InsertReloc (Section, Reloc);
  431. }
  432. }
  433. else
  434. {
  435. // No, we didn't. We have to find the cause of this.
  436. // If it is an externally defined symbol, set up a
  437. // reloc anyway. If not, give a warning.
  438. const COFF_SYMBOL *CurCOFFSymbol = &((*COFFSymbols) [SymNum]);
  439. // Check whether it is an external symbol.
  440. if (IsZeroI2 (CurCOFFSymbol->Section) && IsZeroI4 (CurCOFFSymbol->Value))
  441. {
  442. // Read the symbol name.
  443. char *SymName = calloc (MAX_SYM_LEN + 1, 1);
  444. TestMem (SymName);
  445. // COFF symbol names are stored in a strange way. This is how to get them.
  446. if (IsZero (CurCOFFSymbol->Name.StringRef.Zero))
  447. {
  448. const char *Str = COFFStringTable + ReadTI4 (CurCOFFSymbol->Name.StringRef.StringOffset);
  449. TestInFile (Str, char);
  450. strncpy (SymName, Str, MAX_SYM_LEN);
  451. }
  452. else
  453. strncpy (SymName, CurCOFFSymbol->Name.Name, 8);
  454. // Set up the reloc, without a specified symbol.
  455. // Handle negative relocs by searching for matching positive ones.
  456. if (Negative)
  457. {
  458. // Search for a matching positive reloc.
  459. RELOC *PositiveReloc = FindMatchingReloc (Section, Location, RelocSize, FALSE, NULL, RelocHint);
  460. // We can only do something with the negative reloc
  461. // if we have found a matching positive one.
  462. if (PositiveReloc)
  463. {
  464. // Make the positive reloc relative, with
  465. // this reloc's target as the relation.
  466. LOCATION *Relation = calloc (1, sizeof (LOCATION));
  467. TestMem (Relation);
  468. Relation->SymbolName = SymName;
  469. PositiveReloc->Relative = TRUE;
  470. PositiveReloc->Relation = Relation;
  471. HandleLocation (PositiveReloc, Relation);
  472. RelocHint = PositiveReloc;
  473. }
  474. else
  475. Warning (FileName, "Removing negative reloc at 0x%lX in section %ld to `%s' with no matching positive reloc.", (long) Location, (long) CurCOFFSectionNumber, SymName);
  476. }
  477. else // Positive
  478. {
  479. RELOC *Reloc = calloc (1, sizeof (RELOC));
  480. TestMem (Reloc);
  481. Reloc->Parent = Section;
  482. Reloc->Location = Location;
  483. Reloc->Target.SymbolName = SymName;
  484. Reloc->Size = RelocSize;
  485. Reloc->Relative = Relative;
  486. Reloc->Unoptimizable = Unoptimizable;
  487. // Calculate the reloc's target offset
  488. // (which is written into the fixed offset).
  489. // The section contents contain the virtual
  490. // address of the target.
  491. if (Location >= 0 && Location + RelocSize <= Section->Size)
  492. {
  493. if (Section->Data)
  494. {
  495. Reloc->FixedOffset = ReadSTI (Section->Data + Location, RelocSize);
  496. memset (Section->Data + Location, 0, RelocSize);
  497. }
  498. else
  499. Warning (FileName, "Adding reloc %ld at 0x%lX in section %ld without data to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  500. }
  501. else
  502. Warning (FileName, "Adding reloc %ld at 0x%lX outside of section %ld to `%s'.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, Reloc->Target.SymbolName);
  503. // Relative relocs contain the difference between
  504. // the virtual target address (which is 0 or some
  505. // small offset in this case) and the current
  506. // virtual address. So we have to add the current
  507. // virtual address to get only the offset.
  508. if (Relative)
  509. Reloc->FixedOffset += Location + SecInfo[CurCOFFSectionNumber].VAddr;
  510. // Add the reloc to the section.
  511. InsertReloc (Section, Reloc);
  512. }
  513. }
  514. else
  515. Warning (FileName, "Ignoring reloc %ld at 0x%lX in section %ld to unimported symbol %ld.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, (long) SymNum);
  516. }
  517. }
  518. else
  519. 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)));
  520. }
  521. else
  522. Warning (FileName, "Ignoring reloc %ld at 0x%lX in section %ld to nonexisting symbol %ld.", (long) CurCOFFRelocNumber, (long) COFFLocation, (long) CurCOFFSectionNumber, (long) SymNum);
  523. }
  524. }
  525. }
  526. // *** Finished ***
  527. // Free allocated memory and exit with a positive result.
  528. free (SymInfo);
  529. free (SecInfo);
  530. return TRUE;
  531. #undef TestInFile
  532. #undef IsInFile
  533. #undef TestMem
  534. #undef Fail
  535. }
  536. #endif /* COFF_SUPPORT */