Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

986 lines
30 KiB

4 years ago
  1. /***********************************************************************
  2. * Microsoft (R) 32-Bit Incremental Linker
  3. *
  4. * Copyright (C) Microsoft Corp 1992-95. All rights reserved.
  5. *
  6. * File: mips.cpp
  7. *
  8. * File Comments:
  9. *
  10. * This module contains all mips specific code.
  11. *
  12. ***********************************************************************/
  13. #include "link.h"
  14. void
  15. ApplyMipsFixups (
  16. PCON pcon,
  17. PIMAGE_RELOCATION prel,
  18. DWORD creloc,
  19. BYTE *pbRawData,
  20. PIMAGE_SYMBOL rgsym,
  21. PIMAGE pimage,
  22. PSYMBOL_INFO rgsyminfo
  23. )
  24. /*++
  25. Routine Description:
  26. Applys all Mips fixups to raw data.
  27. Arguments:
  28. CFW - need comments.
  29. Return Value:
  30. None.
  31. --*/
  32. {
  33. BOOL fFixed;
  34. BOOL fDebugFixup;
  35. BOOL fSkipIncrPdataFixup;
  36. DWORD rvaSec;
  37. DWORD iReloc;
  38. fFixed = pimage->Switch.Link.fFixed;
  39. fSkipIncrPdataFixup = (fIncrDbFile && PsecPCON(pcon) == psecException);
  40. fDebugFixup = (PsecPCON(pcon) == psecDebug);
  41. BOOL fSaveDebugFixup = (pimage->Switch.Link.DebugType & FixupDebug) && !fDebugFixup;
  42. rvaSec = pcon->rva;
  43. for (iReloc = creloc; iReloc; iReloc--, prel++) {
  44. DWORD rvaCur;
  45. BYTE *pb;
  46. DWORD isym;
  47. SHORT isecTarget;
  48. DWORD rvaTarget;
  49. DWORD vaTarget;
  50. BOOL fAbsolute;
  51. rvaCur = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  52. pb = pbRawData + prel->VirtualAddress - RvaSrcPCON(pcon);
  53. isym = prel->SymbolTableIndex;
  54. isecTarget = rgsym[isym].SectionNumber;
  55. rvaTarget = rgsym[isym].Value;
  56. if (fINCR &&
  57. !fDebugFixup &&
  58. rgsyminfo[isym].fJmpTbl &&
  59. (rgsym[isym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL ||
  60. rgsym[isym].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
  61. rgsym[isym].StorageClass == IMAGE_SYM_CLASS_FAR_EXTERNAL) &&
  62. // Leave most of pdata pointing to original code except for Handler
  63. ((PsecPCON(pcon) != psecException) ||
  64. (((rvaCur - rvaSec) % sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)) == offsetof(IMAGE_RUNTIME_FUNCTION_ENTRY, ExceptionHandler)))) {
  65. BOOL fNonZeroOffset;
  66. switch (prel->Type) {
  67. case IMAGE_REL_MIPS_JMPADDR:
  68. fNonZeroOffset = (*(DWORD UNALIGNED *) pb & 0x3FFFFFF) != 0;
  69. break;
  70. case IMAGE_REL_MIPS_REFWORDNB:
  71. case IMAGE_REL_MIPS_REFWORD:
  72. fNonZeroOffset = *(DWORD UNALIGNED *) pb != 0;
  73. break;
  74. case IMAGE_REL_MIPS_REFHI:
  75. fNonZeroOffset = *(SHORT UNALIGNED *) pb != 0;
  76. fNonZeroOffset |= (prel[1].SymbolTableIndex != 0);
  77. break;
  78. case IMAGE_REL_MIPS_REFLO:
  79. fNonZeroOffset = *(SHORT UNALIGNED *) pb != 0;
  80. break;
  81. default:
  82. ErrorPcon(pcon, UNKNOWNFIXUP, prel->Type, SzNameFixupSym(pimage, rgsym + isym));
  83. CountFixupError(pimage);
  84. break;
  85. }
  86. if (fNonZeroOffset) {
  87. // Don't go thru the jump table for fixups to functions on non-zero offset
  88. MarkExtern_FuncFixup(&rgsym[isym], pimage, pcon);
  89. } else {
  90. // Fixup since offset is to the addr
  91. rvaTarget = pconJmpTbl->rva + rgsyminfo[isym].Offset-(CbJumpEntry()-sizeof(DWORD));
  92. }
  93. }
  94. if (isecTarget == IMAGE_SYM_ABSOLUTE) {
  95. fAbsolute = TRUE;
  96. vaTarget = rvaTarget;
  97. } else {
  98. fAbsolute = FALSE;
  99. vaTarget = pimage->ImgOptHdr.ImageBase + rvaTarget;
  100. // UNDONE: Check for rvaTarget == 0. Possible fixup to discarded code?
  101. }
  102. if (fSaveDebugFixup && !fAbsolute) {
  103. SaveDebugFixup(prel->Type, 0, rvaCur, rvaTarget);
  104. }
  105. switch (prel->Type) {
  106. DWORD dw;
  107. LONG lT;
  108. PSEC psec;
  109. case IMAGE_REL_MIPS_ABSOLUTE:
  110. break;
  111. case IMAGE_REL_MIPS_REFHALF:
  112. *(SHORT UNALIGNED *) pb += (SHORT) (vaTarget >> 16);
  113. assert(!fSkipIncrPdataFixup);
  114. if (!fAbsolute) {
  115. StoreBaseRelocation(IMAGE_REL_BASED_HIGH,
  116. rvaCur,
  117. isecTarget,
  118. 0,
  119. fFixed);
  120. }
  121. break;
  122. case IMAGE_REL_MIPS_REFWORD:
  123. *(DWORD UNALIGNED *) pb += vaTarget;
  124. if (!fAbsolute && !fSkipIncrPdataFixup) {
  125. StoreBaseRelocation(IMAGE_REL_BASED_HIGHLOW,
  126. rvaCur,
  127. isecTarget,
  128. 0,
  129. fFixed);
  130. }
  131. break;
  132. case IMAGE_REL_MIPS_JMPADDR:
  133. if ((vaTarget & 3) != 0) {
  134. ErrorPcon(pcon, UNALIGNEDFIXUP, SzNameFixupSym(pimage, rgsym + isym));
  135. CountFixupError(pimage);
  136. vaTarget &= ~3;
  137. }
  138. dw = *(DWORD UNALIGNED *) pb;
  139. // We don't mask and sign extend the displacement because
  140. // we only care about the low 26 bits of the result.
  141. lT = (LONG) dw;
  142. lT += (vaTarget >> 2); // Displacement is in DWORDs
  143. *(DWORD UNALIGNED *) pb = (dw & 0xFC000000) | (lT & 0x03FFFFFF);
  144. assert(!fSkipIncrPdataFixup);
  145. if (!fAbsolute) {
  146. StoreBaseRelocation(IMAGE_REL_BASED_MIPS_JMPADDR,
  147. rvaCur,
  148. isecTarget,
  149. 0,
  150. fFixed);
  151. }
  152. break;
  153. case IMAGE_REL_MIPS_REFHI:
  154. // A REFHI has to be followed by a PAIR
  155. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_MIPS_PAIR)) {
  156. // UNDONE: This should be an error
  157. WarningPcon(pcon, UNMATCHEDPAIR, "REFHI");
  158. break;
  159. }
  160. iReloc--;
  161. prel++;
  162. if (fSaveDebugFixup && !fAbsolute) {
  163. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  164. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  165. }
  166. lT = *(SHORT UNALIGNED *) pb; // fetch the hi word
  167. lT <<= 16; // Shift to high half.
  168. // Sign extend the low.
  169. lT += (LONG) (SHORT) prel->SymbolTableIndex;
  170. lT += rvaTarget;
  171. assert(!fSkipIncrPdataFixup);
  172. if (!fAbsolute) {
  173. StoreBaseRelocation(IMAGE_REL_BASED_HIGHADJ,
  174. rvaCur,
  175. isecTarget,
  176. lT,
  177. fFixed);
  178. lT += pimage->ImgOptHdr.ImageBase;
  179. }
  180. // By adding the 0x8000 to the low word, if the 16th bit
  181. // is set, the addition will cause the high word to get
  182. // incremented. Because the chip sign extends the low word,
  183. // this will effectively cancel the increment at runtime.
  184. lT += 0x8000;
  185. *(SHORT UNALIGNED *) pb = (SHORT) (lT >> 16);
  186. break;
  187. case IMAGE_REL_MIPS_REFLO:
  188. *(SHORT UNALIGNED *) pb += (SHORT) vaTarget;
  189. assert(!fSkipIncrPdataFixup);
  190. if (!fAbsolute) {
  191. StoreBaseRelocation(IMAGE_REL_BASED_LOW,
  192. rvaCur,
  193. isecTarget,
  194. 0,
  195. fFixed);
  196. }
  197. break;
  198. case IMAGE_REL_MIPS_GPREL:
  199. case IMAGE_REL_MIPS_LITERAL:
  200. if (pextGp == NULL) {
  201. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  202. CountFixupError(pimage);
  203. break;
  204. }
  205. // Make sure we're in bounds.
  206. if (fAbsolute || (rvaTarget < rvaGp) || (rvaTarget >= rvaGpMax)) {
  207. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  208. CountFixupError(pimage);
  209. }
  210. lT = (LONG) *(SHORT UNALIGNED *) pb;
  211. lT += rvaTarget - pextGp->ImageSymbol.Value;
  212. // Make sure the target is within range
  213. if ((lT < -0x8000L) || (lT > 0x7FFFL)) {
  214. ErrorPcon(pcon, GPFIXUPTOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  215. CountFixupError(pimage);
  216. }
  217. *(SHORT UNALIGNED *) pb = (SHORT) lT;
  218. break;
  219. case IMAGE_REL_MIPS_SECTION:
  220. if (isecTarget > 0) {
  221. *(WORD UNALIGNED *) pb += (WORD) isecTarget;
  222. } else if (fAbsolute) {
  223. // Max section # + 1 is the sstSegMap entry for absolute
  224. // symbols.
  225. *(WORD UNALIGNED *) pb += (WORD) (pimage->ImgFileHdr.NumberOfSections + 1);
  226. } else {
  227. *(WORD UNALIGNED *) pb += 0;
  228. }
  229. break;
  230. case IMAGE_REL_MIPS_SECREL:
  231. if (!fAbsolute) {
  232. psec = PsecFindIsec(isecTarget, &pimage->secs);
  233. if (psec != NULL) {
  234. rvaTarget -= psec->rva;
  235. } else {
  236. // This occurs when a discarded comdat is the target of
  237. // a relocation in the .debug section.
  238. assert(rvaTarget == 0);
  239. }
  240. }
  241. if (!fDebugFixup && (rvaTarget >= 0x8000)) {
  242. // UNDONE: Better error?
  243. ErrorPcon(pcon, GPFIXUPTOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  244. CountFixupError(pimage);
  245. }
  246. *(DWORD UNALIGNED *) pb += rvaTarget;
  247. break;
  248. case IMAGE_REL_MIPS_REFWORDNB:
  249. *(DWORD UNALIGNED *) pb += rvaTarget;
  250. break;
  251. case IMAGE_REL_MIPS_SECRELHI :
  252. if (!fAbsolute) {
  253. psec = PsecFindIsec(isecTarget, &pimage->secs);
  254. if (psec != NULL) {
  255. rvaTarget -= psec->rva;
  256. } else {
  257. // This occurs when a discarded comdat is the target of
  258. // a relocation in the .debug section.
  259. assert(rvaTarget == 0);
  260. }
  261. }
  262. // A SECRELHI has to be followed by a PAIR
  263. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_MIPS_PAIR)) {
  264. // UNDONE: This should be an error
  265. WarningPcon(pcon, UNMATCHEDPAIR, "SECRELHI");
  266. break;
  267. }
  268. iReloc--;
  269. prel++;
  270. if (fSaveDebugFixup && !fAbsolute) {
  271. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  272. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  273. }
  274. lT = *(SHORT UNALIGNED *) pb; // fetch the hi word
  275. lT <<= 16; // Shift to high half.
  276. // Sign extend the low.
  277. lT += (LONG) (SHORT) prel->SymbolTableIndex;
  278. lT += rvaTarget;
  279. // By adding the 0x8000 to the low word, if the 16th bit
  280. // is set, the addition will cause the high word to get
  281. // incremented. Because the chip sign extends the low word,
  282. // this will effectively cancel the increment at runtime.
  283. lT += 0x8000;
  284. *(SHORT UNALIGNED *) pb = (SHORT) (lT >> 16);
  285. break;
  286. case IMAGE_REL_MIPS_SECRELLO :
  287. if (!fAbsolute) {
  288. psec = PsecFindIsec(isecTarget, &pimage->secs);
  289. if (psec != NULL) {
  290. rvaTarget -= psec->rva;
  291. } else {
  292. // This occurs when a discarded comdat is the target of
  293. // a relocation in the .debug section.
  294. assert(rvaTarget == 0);
  295. }
  296. }
  297. *(SHORT UNALIGNED *) pb += (SHORT) rvaTarget;
  298. break;
  299. case IMAGE_REL_MIPS_PAIR:
  300. // UNDONE: This should be an error
  301. WarningPcon(pcon, UNMATCHEDPAIR, "PAIR");
  302. break;
  303. default:
  304. ErrorPcon(pcon, UNKNOWNFIXUP, prel->Type, SzNameFixupSym(pimage, rgsym + isym));
  305. CountFixupError(pimage);
  306. break;
  307. }
  308. }
  309. }
  310. void
  311. ApplyMipsRomFixups (
  312. PCON pcon,
  313. PIMAGE_RELOCATION prel,
  314. DWORD creloc,
  315. BYTE *pbRawData,
  316. PIMAGE_SYMBOL rgsym,
  317. PIMAGE pimage,
  318. PSYMBOL_INFO /* rgsyminfo */
  319. )
  320. /*++
  321. Routine Description:
  322. Applys all Mips fixups to raw data.
  323. Arguments:
  324. CFW: comments needed
  325. Return Value:
  326. None.
  327. --*/
  328. {
  329. BOOL fFixed;
  330. DWORD rvaSec;
  331. DWORD RomOffset;
  332. BOOL fRefHi;
  333. DWORD iReloc;
  334. DWORD iRomSection;
  335. BOOL fRefHiLast;
  336. DWORD rvaRefHi;
  337. // If this is a debug or exception section, then skip the relocations.
  338. if ((PsecPCON(pcon) == psecDebug) || (PsecPCON(pcon) == psecException)) {
  339. return;
  340. }
  341. fFixed = pimage->Switch.Link.fFixed;
  342. BOOL fSaveDebugFixup = (pimage->Switch.Link.DebugType & FixupDebug);
  343. rvaSec = pcon->rva;
  344. // UNDONE: This is a gross hack until we figure out the "right" way to add
  345. // resources to rom images. Given that they only load rom images from outside
  346. // the process and are simply mapping the code in, the NB reloc needs to be
  347. // relative to the beginning of the image. BryanT
  348. RomOffset = pimage->ImgOptHdr.BaseOfCode -
  349. FileAlign(pimage->ImgOptHdr.FileAlignment,
  350. (sizeof(IMAGE_ROM_HEADERS) +
  351. (pimage->ImgFileHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))));
  352. // This is a ROM image, so create MIPS relocations instead of based.
  353. // The relocation Value field is used to store the RomSection parameter.
  354. fRefHi = FALSE;
  355. for (iReloc = creloc; iReloc; iReloc--, prel++) {
  356. DWORD rvaCur;
  357. BYTE *pb;
  358. DWORD isym;
  359. SHORT isecTarget;
  360. DWORD rvaTarget;
  361. DWORD vaTarget;
  362. BOOL fAbsolute;
  363. rvaCur = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  364. pb = pbRawData + prel->VirtualAddress - RvaSrcPCON(pcon);
  365. isym = prel->SymbolTableIndex;
  366. isecTarget = rgsym[isym].SectionNumber;
  367. rvaTarget = rgsym[isym].Value;
  368. if (isecTarget == IMAGE_SYM_ABSOLUTE) {
  369. fAbsolute = TRUE;
  370. vaTarget = rvaTarget;
  371. } else {
  372. fAbsolute = FALSE;
  373. vaTarget = pimage->ImgOptHdr.ImageBase + rvaTarget;
  374. // UNDONE: Check for rvaTarget == 0. Possible fixup to discarded code?
  375. if (!fFixed) {
  376. PSEC psec;
  377. psec = PsecFindIsec(isecTarget, &pimage->secs);
  378. // NULL psec's can result from looking for a symbol that doesn't
  379. // have storage. For instance, the linker defined symbol "header".
  380. // Since it's usually the address of the symbol that's interesting,
  381. // we'll just declare it as code.
  382. if (psec == NULL) {
  383. iRomSection = R_SN_TEXT;
  384. } else if (psec->flags & IMAGE_SCN_CNT_CODE) {
  385. iRomSection = R_SN_TEXT;
  386. } else if (psec->flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
  387. iRomSection = R_SN_BSS;
  388. } else if (psec->flags & IMAGE_SCN_CNT_INITIALIZED_DATA) {
  389. iRomSection = (psec->flags & IMAGE_SCN_MEM_WRITE) ? R_SN_DATA : R_SN_RDATA;
  390. } else {
  391. iRomSection = (DWORD) IMAGE_SYM_ABSOLUTE & 0xFF;
  392. }
  393. }
  394. }
  395. if (fSaveDebugFixup && !fAbsolute) {
  396. SaveDebugFixup(prel->Type, 0, rvaCur, rvaTarget);
  397. }
  398. fRefHiLast = fRefHi;
  399. fRefHi = FALSE;
  400. switch (prel->Type) {
  401. DWORD dw;
  402. LONG lT;
  403. case IMAGE_REL_MIPS_ABSOLUTE:
  404. break;
  405. case IMAGE_REL_MIPS_REFHALF:
  406. *(SHORT UNALIGNED *) pb += (SHORT) (vaTarget >> 16);
  407. if (!fAbsolute) {
  408. StoreBaseRelocation(IMAGE_REL_MIPS_REFHALF,
  409. rvaCur,
  410. isecTarget,
  411. iRomSection,
  412. fFixed);
  413. }
  414. break;
  415. case IMAGE_REL_MIPS_REFWORD:
  416. *(DWORD UNALIGNED *) pb += vaTarget;
  417. if (!fAbsolute) {
  418. StoreBaseRelocation(IMAGE_REL_MIPS_REFWORD,
  419. rvaCur,
  420. isecTarget,
  421. iRomSection,
  422. fFixed);
  423. }
  424. break;
  425. case IMAGE_REL_MIPS_JMPADDR:
  426. if ((vaTarget & 3) != 0) {
  427. ErrorPcon(pcon, UNALIGNEDFIXUP, SzNameFixupSym(pimage, rgsym + isym));
  428. CountFixupError(pimage);
  429. vaTarget &= ~3;
  430. }
  431. dw = *(DWORD UNALIGNED *) pb;
  432. // We don't mask and sign extend the displacement because
  433. // we only care about the low 26 bits of the result.
  434. lT = (LONG) dw;
  435. lT += (vaTarget >> 2); // Displacement is in DWORDs
  436. *(DWORD UNALIGNED *) pb = (dw & 0xFC000000) | (lT & 0x03FFFFFF);
  437. if (!fAbsolute) {
  438. StoreBaseRelocation(IMAGE_REL_MIPS_JMPADDR,
  439. rvaCur,
  440. isecTarget,
  441. iRomSection,
  442. fFixed);
  443. }
  444. break;
  445. case IMAGE_REL_MIPS_REFHI:
  446. // A REFHI has to be followed by a PAIR
  447. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_MIPS_PAIR)) {
  448. // UNDONE: This should be an error
  449. WarningPcon(pcon, UNMATCHEDPAIR, "REFHI");
  450. break;
  451. }
  452. iReloc--;
  453. prel++;
  454. if (fSaveDebugFixup && !fAbsolute) {
  455. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  456. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  457. }
  458. fRefHi = TRUE;
  459. lT = *(SHORT UNALIGNED *) pb; // fetch the hi word
  460. lT <<= 16; // Shift to high half.
  461. // Sign extend the low.
  462. lT += (LONG) (SHORT) prel->SymbolTableIndex;
  463. lT += rvaTarget;
  464. if (!fAbsolute) {
  465. StoreBaseRelocation(IMAGE_REL_MIPS_REFHI,
  466. rvaCur,
  467. isecTarget,
  468. iRomSection,
  469. fFixed);
  470. // Save the REFHI address for the following REFLO.
  471. rvaRefHi = rvaCur;
  472. lT += pimage->ImgOptHdr.ImageBase;
  473. }
  474. // By adding the 0x8000 to the low word, if the 16th bit
  475. // is set, the addition will cause the high word to get
  476. // incremented. Because the chip sign extends the low word,
  477. // this will effectively cancel the increment at runtime.
  478. lT += 0x8000;
  479. *(SHORT UNALIGNED *) pb = (SHORT) (lT >> 16);
  480. // UNDONE: Do ROM images require REFHI, PAIR, then REFLO?
  481. // UNDONE: If so, the following should be an error.
  482. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_MIPS_REFLO)) {
  483. // UNDONE: Make this a real warning
  484. printf("LINK : warning : No REFLO, base = %08lx, type = %d\n",
  485. prel[1].VirtualAddress,
  486. prel[1].Type);
  487. }
  488. break;
  489. case IMAGE_REL_MIPS_REFLO:
  490. if (!fAbsolute) {
  491. if (fRefHiLast) {
  492. // For REFLO_MATCHED, store the address of the REFHI
  493. // plus one as the address of the relocation. This
  494. // preserves the order of the relocations when they
  495. // are sorted. The Value field contains the actual
  496. // target.
  497. StoreBaseRelocation(IMAGE_REL_MIPS_REFLO_MATCHED,
  498. rvaRefHi + 1,
  499. isecTarget,
  500. rvaCur,
  501. fFixed);
  502. } else {
  503. StoreBaseRelocation(IMAGE_REL_MIPS_REFLO,
  504. rvaCur,
  505. isecTarget,
  506. iRomSection,
  507. fFixed);
  508. }
  509. }
  510. *(SHORT UNALIGNED *) pb += (SHORT) vaTarget;
  511. break;
  512. case IMAGE_REL_MIPS_GPREL:
  513. case IMAGE_REL_MIPS_LITERAL:
  514. // There is no GP support for ROM images
  515. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  516. CountFixupError(pimage);
  517. break;
  518. case IMAGE_REL_MIPS_REFWORDNB:
  519. *(DWORD UNALIGNED *) pb += rvaTarget - RomOffset;
  520. break;
  521. case IMAGE_REL_MIPS_PAIR:
  522. // UNDONE: This should be an error
  523. WarningPcon(pcon, UNMATCHEDPAIR, "PAIR");
  524. break;
  525. default:
  526. ErrorPcon(pcon, UNKNOWNFIXUP, prel->Type, SzNameFixupSym(pimage, rgsym + isym));
  527. CountFixupError(pimage);
  528. break;
  529. }
  530. }
  531. }
  532. void
  533. WriteMipsRomRelocations (
  534. PIMAGE pimage
  535. )
  536. /*++
  537. Routine Description:
  538. Writes Mips relocations.
  539. Arguments:
  540. None.
  541. Return Value:
  542. None.
  543. --*/
  544. {
  545. struct SectionSpan {
  546. INT cRel;
  547. DWORD rvaStart;
  548. DWORD rvaEnd;
  549. DWORD foSecHdr;
  550. DWORD foData;
  551. } SectionList[5]; // A list of .text, .bss , .rdata and .data
  552. INT iSec;
  553. INT cSec;
  554. ENM_SEC enm_sec;
  555. BASE_RELOC *pbr;
  556. FileSeek(FileWriteHandle, psecBaseReloc->foRawData, SEEK_SET);
  557. // Create List of sections and their start and end RVAs (rva, rva + cbRawData)
  558. iSec = 0;
  559. InitEnmSec(&enm_sec, &pimage->secs);
  560. while (FNextEnmSec(&enm_sec)) {
  561. PSEC psec;
  562. psec = enm_sec.psec;
  563. if ((!strcmp(psec->szName, ".text")) || (!strcmp(psec->szName, ".data")) ||
  564. (!strcmp(psec->szName, ".bss")) || (!strcmp(psec->szName, ".rdata"))) {
  565. // UNDONE: Why not save PSEC?
  566. SectionList[iSec].rvaStart = psec->rva;
  567. SectionList[iSec].rvaEnd = psec->rva + psec->cbRawData;
  568. SectionList[iSec].foSecHdr = psec->foSecHdr;
  569. SectionList[iSec].cRel = 0;
  570. SectionList[iSec].foData = 0;
  571. iSec++;
  572. }
  573. }
  574. assert(iSec < 5); // we only expect 4 sections
  575. cSec = 0;
  576. for (pbr = rgbr; pbr != pbrCur; pbr++) {
  577. DWORD vaddr;
  578. BOOL found;
  579. IMAGE_BASE_RELOCATION block;
  580. vaddr = pbr->rva;
  581. // Count relocs by section
  582. // UNDONE: The RELOCs are sorted by VirtualAddress so that following
  583. // UNDONE: code could be simplified.
  584. found = FALSE;
  585. for (iSec = cSec; iSec < 4; iSec++) {
  586. if ((vaddr >= SectionList[iSec].rvaStart) && (vaddr <= SectionList[iSec].rvaEnd)) {
  587. SectionList[iSec].cRel++;
  588. if (!SectionList[iSec].foData) {
  589. SectionList[iSec].foData = FileTell(FileWriteHandle);
  590. }
  591. cSec = iSec;
  592. found = TRUE;
  593. break;
  594. }
  595. }
  596. if (!found) {
  597. // Did not find it in the first four
  598. // UNDONE: Need a real error here
  599. printf("LINK : error : relocation out of range\n");
  600. }
  601. // spit out relocs
  602. block.VirtualAddress = vaddr;
  603. block.SizeOfBlock = (pbr->Type << 27) + pbr->Value;
  604. FileWrite(FileWriteHandle, &block, 8);
  605. if (pbr->Type == IMAGE_REL_MIPS_REFHI) {
  606. if (pbr[1].Type != IMAGE_REL_MIPS_REFLO_MATCHED) {
  607. // UNDONE: Make this a real warning
  608. printf("LINK : warning : Illegal Hi/Lo relocation pair\n");
  609. } else {
  610. pbr++;
  611. block.VirtualAddress = pbr->Value;
  612. block.SizeOfBlock = (IMAGE_REL_MIPS_REFLO << 27) + pbr[-1].Value;
  613. FileWrite(FileWriteHandle, &block, 8);
  614. SectionList[iSec].cRel++;
  615. }
  616. }
  617. // TEMPTEMP
  618. // UNDONE: It is normally OK to have a stand along REFLO. Is there
  619. // UNDONE: some MIPS ROM restriction that motivates this check?
  620. if (pbr->Type == IMAGE_REL_MIPS_REFLO) {
  621. printf("LINK : warning : Unmatched REFLO\n");
  622. }
  623. // TEMPTEMP
  624. }
  625. // Now write the foReloc anf cReloc to the specific sections
  626. #define OFFSET_TO_foReloc offsetof(IMAGE_SECTION_HEADER, PointerToRelocations)
  627. #define OFFSET_TO_cReloc offsetof(IMAGE_SECTION_HEADER, NumberOfRelocations)
  628. for (iSec = 0; iSec < 4; iSec++) {
  629. // Write count of relocations
  630. FileSeek(FileWriteHandle, SectionList[iSec].foSecHdr + OFFSET_TO_cReloc, SEEK_SET);
  631. FileWrite(FileWriteHandle, &SectionList[iSec].cRel, sizeof(WORD));
  632. if (SectionList[iSec].cRel) {
  633. // Write pointer to relocations
  634. FileSeek(FileWriteHandle, SectionList[iSec].foSecHdr + OFFSET_TO_foReloc, SEEK_SET);
  635. FileWrite(FileWriteHandle, &SectionList[iSec].foData, sizeof(DWORD));
  636. }
  637. }
  638. }
  639. void MipsLinkerInit(PIMAGE pimage, BOOL *pfIlinkSupported)
  640. {
  641. *pfIlinkSupported = TRUE;
  642. // If section alignment switch not used, set the default.
  643. if (!FUsedOpt(pimage->SwitchInfo, OP_ALIGN)) {
  644. pimage->ImgOptHdr.SectionAlignment = _4K;
  645. }
  646. if (pimage->Switch.Link.fROM) {
  647. ApplyFixups = ApplyMipsRomFixups;
  648. fImageMappedAsFile = TRUE;
  649. pimage->ImgFileHdr.SizeOfOptionalHeader = sizeof(IMAGE_ROM_OPTIONAL_HEADER);
  650. if (!pimage->ImgOptHdr.BaseOfCode) {
  651. pimage->ImgOptHdr.BaseOfCode = pimage->ImgOptHdr.ImageBase;
  652. }
  653. pimage->ImgOptHdr.ImageBase = 0;
  654. } else {
  655. ApplyFixups = ApplyMipsFixups;
  656. // If the section alignment is < _4K then make the file alignment the
  657. // same as the section alignment. This ensures that the image will
  658. // be the same in memory as in the image file, since the alignment is less
  659. // than the maximum alignment of memory-mapped files.
  660. if (pimage->ImgOptHdr.SectionAlignment < _4K) {
  661. fImageMappedAsFile = TRUE;
  662. pimage->ImgOptHdr.FileAlignment = pimage->ImgOptHdr.SectionAlignment;
  663. }
  664. }
  665. }
  666. const char *SzMipsRelocationType(WORD wType, WORD *pcb, BOOL *pfSymValid)
  667. {
  668. const char *szName;
  669. WORD cb;
  670. switch (wType) {
  671. case IMAGE_REL_MIPS_ABSOLUTE :
  672. szName = "ABS";
  673. cb = 0;
  674. break;
  675. case IMAGE_REL_MIPS_PAIR :
  676. szName = "PAIR";
  677. cb = 0;
  678. break;
  679. case IMAGE_REL_MIPS_REFHALF :
  680. szName = "REFHALF";
  681. cb = sizeof(SHORT);
  682. break;
  683. case IMAGE_REL_MIPS_REFWORD :
  684. szName = "REFWORD";
  685. cb = sizeof(DWORD);
  686. break;
  687. case IMAGE_REL_MIPS_REFWORDNB :
  688. szName = "REFWORDNB";
  689. cb = sizeof(DWORD);
  690. break;
  691. case IMAGE_REL_MIPS_JMPADDR :
  692. szName = "JMPADDR";
  693. cb = sizeof(DWORD);
  694. break;
  695. case IMAGE_REL_MIPS_REFHI :
  696. szName = "REFHI";
  697. cb = sizeof(SHORT);
  698. break;
  699. case IMAGE_REL_MIPS_REFLO :
  700. szName = "REFLO";
  701. cb = sizeof(SHORT);
  702. break;
  703. case IMAGE_REL_MIPS_GPREL :
  704. szName = "GPREL";
  705. cb = sizeof(SHORT);
  706. break;
  707. case IMAGE_REL_MIPS_LITERAL :
  708. szName = "LITERAL";
  709. cb = sizeof(SHORT);
  710. break;
  711. case IMAGE_REL_MIPS_SECTION :
  712. szName = "SECTION";
  713. cb = sizeof(SHORT);
  714. break;
  715. case IMAGE_REL_MIPS_SECREL :
  716. szName = "SECREL";
  717. cb = sizeof(DWORD);
  718. break;
  719. case IMAGE_REL_MIPS_SECRELLO :
  720. szName = "SECRELLO";
  721. cb = sizeof(SHORT);
  722. break;
  723. case IMAGE_REL_MIPS_SECRELHI :
  724. szName = "SECRELHI";
  725. cb = sizeof(SHORT);
  726. break;
  727. default :
  728. szName = NULL;
  729. cb = 0;
  730. break;
  731. }
  732. *pcb = cb;
  733. *pfSymValid = (cb != 0);
  734. return(szName);
  735. }