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.

1071 lines
34 KiB

4 years ago
  1. /***********************************************************************
  2. * Microsoft (R) 32-Bit Incremental Linker
  3. *
  4. * Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
  5. *
  6. * File: alpha.cpp
  7. *
  8. * File Comments:
  9. *
  10. * Alpha specific routines
  11. *
  12. ***********************************************************************/
  13. #include "link.h"
  14. static const DWORD AlphaBsrThunk[] = { // at is $28
  15. 0x279f0000, // ldah at, hi_addr(zero)
  16. 0x239c0000, // lda at, lo_addr(at)
  17. 0x6bfc0000, // jmp $31, (at)
  18. 0x00000000 // halt (maintain 16 byte align and puke if execute)
  19. };
  20. // use CalculatePtrs template to calculate the size of a section
  21. DWORD
  22. CalculateTextSectionSize (
  23. PIMAGE pimage,
  24. DWORD rvaBase
  25. )
  26. {
  27. ENM_SEC enm_sec;
  28. ENM_GRP enm_grp;
  29. ENM_DST enm_dst;
  30. PSEC psec;
  31. PGRP pgrp;
  32. PCON pcon;
  33. DWORD rva;
  34. DWORD cbRawData;
  35. DWORD cbSection;
  36. // UNDONE: This is what we want to do. For now, it's not quite there.
  37. //
  38. // Here's what we're trying to find. Given an image that looks like this:
  39. //
  40. // +--------------------+
  41. // / non-paged code \ (.text, etc)
  42. // \ /
  43. // +--------------------+
  44. // / non-paged data \ (.data, .bss, .sdata, etc) ??? These m/b paged also
  45. // \ /
  46. // +--------------------+
  47. // / paged code \ (PAGExxx code sections)
  48. // \ /
  49. // +--------------------+
  50. // / paged data \ (PAGExxx data sections)
  51. // \ /
  52. // +--------------------+
  53. // / discarded code \ (INIT section, etc).
  54. // \ /
  55. // +--------------------+
  56. // / discarded data \ (resources, debug, etc)
  57. // \ /
  58. // +--------------------+
  59. //
  60. // Is it possible to have a BSR (local jump) that's more than 4M away. To
  61. // do this, we keep track of the total size of each section
  62. cbSection = 0;
  63. InitEnmSec(&enm_sec, &pimage->secs);
  64. while (FNextEnmSec(&enm_sec)) {
  65. psec = enm_sec.psec;
  66. if (FetchContent(psec->flags) != IMAGE_SCN_CNT_CODE) {
  67. continue;
  68. }
  69. // UNDONE: What about code sections not named ".text$xxx"?
  70. if (strcmp(psec->szName, ".text")) {
  71. continue;
  72. }
  73. rva = rvaBase;
  74. cbRawData = 0;
  75. InitEnmGrp(&enm_grp, psec);
  76. while (FNextEnmGrp(&enm_grp)) {
  77. DWORD rvaAligned;
  78. DWORD cbGrpPad;
  79. pgrp = enm_grp.pgrp;
  80. // Align the beginning of the group to correspond with the
  81. // highest-aligned contribution in it.
  82. assert((pgrp->cbAlign & (pgrp->cbAlign - 1)) == 0); // 2^N
  83. rvaAligned = rva & ~(pgrp->cbAlign - 1);
  84. if (rvaAligned != rva) {
  85. rvaAligned = rvaAligned + pgrp->cbAlign;
  86. }
  87. if ((cbGrpPad = rvaAligned - rva) != 0) {
  88. rva += cbGrpPad;
  89. cbRawData += cbGrpPad;
  90. }
  91. // Process each contribution within the group
  92. InitEnmDst(&enm_dst, pgrp);
  93. while (FNextEnmDst(&enm_dst)) {
  94. DWORD cbConPad;
  95. cbConPad = 0;
  96. pcon = enm_dst.pcon;
  97. if (pcon->cbRawData) {
  98. cbConPad = RvaAlign(rva,pcon->flags) - rva; // Calculate padding needed for con alignment
  99. }
  100. rva += pcon->cbRawData + cbConPad;
  101. cbRawData += pcon->cbRawData + cbConPad;
  102. }
  103. }
  104. cbSection = FileAlign(pimage->ImgOptHdr.FileAlignment,
  105. (psec->cbRawData + cbRawData));
  106. }
  107. return(cbSection);
  108. }
  109. typedef struct ALPHAThunkList {
  110. PCON pcon; // con whose padding these thunks appear as
  111. DWORD rva; // rva of con
  112. DWORD count; // count of thunks left
  113. DWORD Total; // Total number of thunks allocated
  114. DWORD *rgvaDest; // list of destination addresses
  115. } *pALPHAThunkList, ALPHAThunkList;
  116. pALPHAThunkList AlphaThunkList;
  117. DWORD AlphaThunkListCount;
  118. DWORD AlphaThunkListSize;
  119. // will be good for 16 Mb text sections. Most sane people will not have larger apps
  120. #define ALPHA_THUNK_LIST_SIZE 4
  121. // Add to a list of available thunk space to be used by out of range BSR's on Alpha
  122. void
  123. AlphaAddToThunkList(
  124. PCON pcon,
  125. DWORD rva,
  126. DWORD count
  127. )
  128. {
  129. assert(!(rva % 16)); // Make sure the thunks start right...
  130. if (AlphaThunkList == NULL) {
  131. AlphaThunkList = (pALPHAThunkList) PvAlloc(ALPHA_THUNK_LIST_SIZE * sizeof(ALPHAThunkList));
  132. AlphaThunkListSize += ALPHA_THUNK_LIST_SIZE;
  133. }
  134. if (AlphaThunkListCount >= AlphaThunkListSize) {
  135. AlphaThunkListSize += ALPHA_THUNK_LIST_SIZE;
  136. AlphaThunkList = (pALPHAThunkList) PvRealloc(AlphaThunkList, AlphaThunkListSize * sizeof(ALPHAThunkList));
  137. }
  138. AlphaThunkList[AlphaThunkListCount].rgvaDest = (DWORD *) PvAlloc(count * sizeof(DWORD));
  139. AlphaThunkList[AlphaThunkListCount].pcon = pcon;
  140. AlphaThunkList[AlphaThunkListCount].rva = rva;
  141. AlphaThunkList[AlphaThunkListCount].count = count;
  142. AlphaThunkList[AlphaThunkListCount].Total = count;
  143. AlphaThunkListCount++;
  144. }
  145. // Get a Thunk for an out of range BSR. If no such thunk is available, return 0
  146. DWORD
  147. RvaAlphaThunk(
  148. PIMAGE pimage,
  149. DWORD rva, // Where we're coming from
  150. BOOL fAbsolute,
  151. SHORT isecDest,
  152. DWORD vaDest // Where we're going to
  153. )
  154. {
  155. DWORD i;
  156. DWORD rvaThunk = 0;
  157. for (i = 0; i < AlphaThunkListCount; i++) {
  158. DWORD ib = AlphaThunkList[i].rva - rva;
  159. if (AlphaThunkList[i].count == 0) {
  160. // No thunks available in this list (all have been consumed)
  161. continue;
  162. }
  163. if (ib < 0x400000) {
  164. DWORD j;
  165. DWORD dwUsed = AlphaThunkList[i].Total - AlphaThunkList[i].count;
  166. for (j = 0; j < dwUsed; j++) {
  167. if (AlphaThunkList[i].rgvaDest[j] == vaDest) {
  168. // Here's a thunk going there already. Tag along.
  169. rvaThunk = AlphaThunkList[i].rva - (ALPHA_THUNK_SIZE * (dwUsed - j));
  170. return(rvaThunk);
  171. }
  172. }
  173. rvaThunk = AlphaThunkList[i].rva;
  174. if (!fAbsolute) {
  175. // Store the required relocs
  176. DWORD rvaDest = vaDest - pimage->ImgOptHdr.ImageBase;
  177. if (pimage->Switch.Link.DebugType & FixupDebug) {
  178. SaveDebugFixup(IMAGE_REL_ALPHA_INLINE_REFLONG, 0, rvaThunk, rvaDest);
  179. SaveDebugFixup(IMAGE_REL_ALPHA_MATCH, 0, rvaThunk, 4);
  180. }
  181. StoreBaseRelocation(IMAGE_REL_BASED_HIGHADJ,
  182. rvaThunk,
  183. isecDest,
  184. rvaDest,
  185. pimage->Switch.Link.fFixed);
  186. StoreBaseRelocation(IMAGE_REL_BASED_LOW,
  187. rvaThunk + 4,
  188. isecDest,
  189. 0,
  190. pimage->Switch.Link.fFixed);
  191. }
  192. // UNDONE: What debug symbolic is needed to step through it?
  193. AlphaThunkList[i].rgvaDest[AlphaThunkList[i].Total - AlphaThunkList[i].count] = vaDest;
  194. AlphaThunkList[i].count--;
  195. AlphaThunkList[i].rva += ALPHA_THUNK_SIZE;
  196. break;
  197. }
  198. }
  199. return(rvaThunk);
  200. }
  201. void
  202. EmitAlphaThunks(VOID)
  203. {
  204. DWORD iList;
  205. // Iterate over all thunk lists
  206. for (iList = 0; iList < AlphaThunkListCount; iList++) {
  207. DWORD num_thunks;
  208. PCON pcon;
  209. DWORD foDest;
  210. DWORD iThunk;
  211. // Number of thunks to emit = total allocated - number unused
  212. num_thunks = AlphaThunkList[iList].Total - AlphaThunkList[iList].count;
  213. pcon = AlphaThunkList[iList].pcon;
  214. // File offset for writing thunk = Fo of previous pcon
  215. // + number of bytes of PCON (includes pad)
  216. // - space allocated forthunks
  217. foDest = pcon->foRawDataDest + pcon->cbRawData - AlphaThunkList[iList].Total * ALPHA_THUNK_SIZE;
  218. // iterate over the number of thunks to emit
  219. for (iThunk = 0; iThunk < num_thunks; iThunk++) {
  220. DWORD AlphaThunk[5];
  221. DWORD Dest;
  222. DWORD *Thunkptr;
  223. memcpy(AlphaThunk, AlphaBsrThunk, ALPHA_THUNK_SIZE);
  224. // Dest = place the thunk needs to jump to
  225. Dest = AlphaThunkList[iList].rgvaDest[iThunk];
  226. // Now fix the instructions to point to destination
  227. // Fix ldah
  228. Thunkptr = AlphaThunk;
  229. *(WORD *) Thunkptr = (WORD) (Dest >> 16);
  230. if ((Dest & 0x00008000) != 0) {
  231. *(WORD *) Thunkptr += 1;
  232. }
  233. // Fix lda
  234. Thunkptr++; // next instruction
  235. *(WORD *) Thunkptr = (WORD) (Dest & 0x0000FFFF);
  236. FileSeek(FileWriteHandle, foDest, SEEK_SET);
  237. FileWrite(FileWriteHandle, AlphaThunk, ALPHA_THUNK_SIZE);
  238. // Increment to point to next thunk
  239. foDest += ALPHA_THUNK_SIZE;
  240. }
  241. // Free list of destinations
  242. #if DBG
  243. DWORD q;
  244. for (q = 0; q < AlphaThunkListCount; q++) {
  245. printf("ThunkList[%d] - Total: %d - Used: %d - DeadSpace: %d\n",
  246. q,
  247. AlphaThunkList[q].Total,
  248. AlphaThunkList[q].Total - AlphaThunkList[q].count,
  249. AlphaThunkList[q].count * ALPHA_THUNK_SIZE);
  250. }
  251. #endif
  252. FreePv(AlphaThunkList[iList].rgvaDest);
  253. }
  254. FreePv(AlphaThunkList);
  255. }
  256. void
  257. ApplyAlphaFixups(
  258. PCON pcon,
  259. PIMAGE_RELOCATION prel,
  260. DWORD creloc,
  261. BYTE *pbRawData,
  262. PIMAGE_SYMBOL rgsym,
  263. PIMAGE pimage,
  264. PSYMBOL_INFO rgsyminfo
  265. )
  266. /*++
  267. Routine Description:
  268. Applys all Alpha fixups to raw data.
  269. Arguments:
  270. ObjectFilename - Name of object containing the fixup records.
  271. PtrReloc - A pointer to a relocation list.
  272. PtrSection - A pointer to the section data.
  273. Raw - A pointer to the raw data.
  274. Return Value:
  275. None.
  276. --*/
  277. {
  278. BOOL fFixed;
  279. BOOL fDebugFixup;
  280. BOOL fSkipIncrPdataFixup;
  281. DWORD rvaSec;
  282. DWORD iReloc;
  283. DWORD RomOffset = 0;
  284. fFixed = pimage->Switch.Link.fFixed;
  285. fSkipIncrPdataFixup = (fIncrDbFile && PsecPCON(pcon) == psecException);
  286. fDebugFixup = (PsecPCON(pcon) == psecDebug);
  287. BOOL fSaveDebugFixup = (pimage->Switch.Link.DebugType & FixupDebug) && !fDebugFixup;
  288. rvaSec = pcon->rva;
  289. // UNDONE: This is a gross hack until we figure out the "right" way to add
  290. // resources to rom images. Given that they only load rom images from outside
  291. // the process and are simply mapping the code in, the NB reloc needs to be
  292. // relative to the beginning of the image. BryanT
  293. if (pimage->Switch.Link.fROM) {
  294. RomOffset = pimage->ImgOptHdr.BaseOfCode -
  295. FileAlign(pimage->ImgOptHdr.FileAlignment,
  296. (sizeof(IMAGE_ROM_HEADERS) +
  297. (pimage->ImgFileHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))));
  298. }
  299. for (iReloc = creloc; iReloc; iReloc--, prel++) {
  300. DWORD rvaCur;
  301. BYTE *pb;
  302. DWORD isym;
  303. SHORT isecTarget;
  304. DWORD rvaTarget;
  305. DWORD vaTarget;
  306. BOOL fAbsolute;
  307. rvaCur = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  308. pb = pbRawData + prel->VirtualAddress - RvaSrcPCON(pcon);
  309. isym = prel->SymbolTableIndex;
  310. isecTarget = rgsym[isym].SectionNumber;
  311. rvaTarget = rgsym[isym].Value;
  312. if (fINCR && !fDebugFixup && rgsyminfo[isym].fJmpTbl &&
  313. (rgsym[isym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL ||
  314. rgsym[isym].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
  315. rgsym[isym].StorageClass == IMAGE_SYM_CLASS_FAR_EXTERNAL) &&
  316. // Leave most of pdata pointing to original code except for Handler
  317. ((PsecPCON(pcon) != psecException) ||
  318. (((rvaCur - rvaSec) % sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)) == offsetof(IMAGE_RUNTIME_FUNCTION_ENTRY, ExceptionHandler)))) {
  319. BOOL fNonZeroOffset;
  320. switch (prel->Type) {
  321. case IMAGE_REL_ALPHA_GPDISP:
  322. fNonZeroOffset = (*(DWORD UNALIGNED *) pb & 0x3FFFFFF) != 0;
  323. break;
  324. case IMAGE_REL_ALPHA_REFLONG:
  325. case IMAGE_REL_ALPHA_BRADDR:
  326. fNonZeroOffset = (*(DWORD UNALIGNED *) pb & 0x1fffff) != 0;
  327. break;
  328. case IMAGE_REL_ALPHA_REFHI:
  329. fNonZeroOffset = (*(SHORT UNALIGNED *) pb) != 0;
  330. fNonZeroOffset |= (prel[1].SymbolTableIndex != 0);
  331. break;
  332. case IMAGE_REL_ALPHA_REFLO:
  333. fNonZeroOffset = (*(SHORT UNALIGNED *) pb) != 0;
  334. break;
  335. case IMAGE_REL_ALPHA_REFLONGNB:
  336. fNonZeroOffset = (*(DWORD UNALIGNED *) pb) != 0;
  337. break;
  338. case IMAGE_REL_ALPHA_HINT:
  339. fNonZeroOffset = (*(DWORD UNALIGNED *) pb & 0x3fff) != 0;
  340. break;
  341. default:
  342. ErrorPcon(pcon, UNKNOWNFIXUP, prel->Type, SzNameFixupSym(pimage, rgsym + isym));
  343. CountFixupError(pimage);
  344. break;
  345. }
  346. if (fNonZeroOffset) {
  347. // Don't go thru the jump table for fixups to functions on non-zero offset
  348. MarkExtern_FuncFixup(&rgsym[isym], pimage, pcon);
  349. } else {
  350. // Fixup since offset is to the addr
  351. rvaTarget = pconJmpTbl->rva + rgsyminfo[isym].Offset-(CbJumpEntry()-sizeof(DWORD));
  352. }
  353. }
  354. if (isecTarget == IMAGE_SYM_ABSOLUTE) {
  355. fAbsolute = TRUE;
  356. vaTarget = rvaTarget;
  357. } else {
  358. fAbsolute = FALSE;
  359. vaTarget = pimage->ImgOptHdr.ImageBase + rvaTarget;
  360. // UNDONE: Check for rvaTarget == 0. Possible fixup to discarded code?
  361. }
  362. if (fSaveDebugFixup && !fAbsolute) {
  363. SaveDebugFixup(prel->Type, 0, rvaCur, rvaTarget);
  364. }
  365. switch (prel->Type) {
  366. LONG lT;
  367. DWORD dw;
  368. PSEC psec;
  369. case IMAGE_REL_ALPHA_ABSOLUTE :
  370. break;
  371. case IMAGE_REL_ALPHA_REFLONG :
  372. *(DWORD UNALIGNED *) pb += vaTarget;
  373. if (!fAbsolute && !fSkipIncrPdataFixup) {
  374. StoreBaseRelocation(IMAGE_REL_BASED_HIGHLOW,
  375. rvaCur,
  376. isecTarget,
  377. 0,
  378. fFixed);
  379. }
  380. break;
  381. case IMAGE_REL_ALPHA_REFQUAD :
  382. *(DWORD UNALIGNED *) pb += vaTarget;
  383. if (*(DWORD UNALIGNED *) pb & 0x80000000) {
  384. *(DWORD UNALIGNED *)(pb + 4) = 0xFFFFFFFF;
  385. } else {
  386. *(DWORD UNALIGNED *)(pb + 4) = 0x00000000;
  387. }
  388. assert(!fSkipIncrPdataFixup);
  389. if (!fAbsolute) {
  390. StoreBaseRelocation(IMAGE_REL_BASED_HIGHLOW,
  391. rvaCur,
  392. isecTarget,
  393. 0,
  394. fFixed);
  395. }
  396. break;
  397. // 32 or 16 bit displacement from GP to virtual address.
  398. // GPREL32 is, of course, 32bits, while literal must be
  399. // within 16 bits.
  400. case IMAGE_REL_ALPHA_GPREL32 :
  401. if (pextGp == NULL) {
  402. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  403. CountFixupError(pimage);
  404. break;
  405. }
  406. // Make sure we're in bounds.
  407. if (fAbsolute || (rvaTarget < rvaGp) || (rvaTarget >= rvaGpMax)) {
  408. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  409. CountFixupError(pimage);
  410. }
  411. *(LONG UNALIGNED *) pb += (LONG) (rvaTarget - pextGp->ImageSymbol.Value);
  412. break;
  413. case IMAGE_REL_ALPHA_LITERAL :
  414. if (pextGp == NULL) {
  415. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  416. CountFixupError(pimage);
  417. break;
  418. }
  419. // Make sure we're in bounds.
  420. if (fAbsolute || (rvaTarget < rvaGp) || (rvaTarget >= rvaGpMax)) {
  421. ErrorPcon(pcon, GPFIXUPNOTSDATA, SzNameFixupSym(pimage, rgsym + isym));
  422. CountFixupError(pimage);
  423. }
  424. lT = (LONG) *(SHORT UNALIGNED *) pb;
  425. lT += rvaTarget - pextGp->ImageSymbol.Value;
  426. // Make sure the target is within range
  427. if ((lT < -0x8000L) || (lT > 0x7FFFL)) {
  428. ErrorPcon(pcon, GPFIXUPTOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  429. CountFixupError(pimage);
  430. }
  431. *(SHORT UNALIGNED *) pb = (SHORT) lT;
  432. break;
  433. case IMAGE_REL_ALPHA_LITUSE :
  434. // UNDONE: Should this be ignored or an error?
  435. break;
  436. case IMAGE_REL_ALPHA_BRADDR :
  437. if ((vaTarget & 3) != 0) {
  438. ErrorPcon(pcon, UNALIGNEDFIXUP, SzNameFixupSym(pimage, rgsym + isym));
  439. CountFixupError(pimage);
  440. rvaTarget &= ~3;
  441. vaTarget &= ~3;
  442. }
  443. dw = *(DWORD UNALIGNED *) pb;
  444. lT = (LONG) (dw & 0x001FFFFF);
  445. if ((lT & 0x00100000) != 0) {
  446. lT |= 0xFFE00000; // Sign extend
  447. }
  448. lT <<= 2; // Displacement is in DWORDs
  449. lT += rvaTarget - (rvaCur + sizeof(DWORD));
  450. if (!UndefinedSymbols &&
  451. (fAbsolute || (lT >= 0x400000L) || (lT < -0x400000L))) {
  452. DWORD rvaThunk;
  453. if (Verbose) {
  454. WarningPcon(pcon, TOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  455. }
  456. // UNDONE: This doesn't work if instruction has a
  457. // UNDONE: non-zero displacement in the object file.
  458. if ((rvaThunk = RvaAlphaThunk(pimage, rvaCur, fAbsolute, isecTarget, vaTarget)) == 0) {
  459. // No thunks left
  460. FatalPcon(pcon, TOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  461. }
  462. lT = rvaThunk - (rvaCur + sizeof(DWORD));
  463. }
  464. lT >>= 2; // Displacement is in DWORDs
  465. *(DWORD UNALIGNED *) pb = (dw & 0xFFE00000) | (lT & 0x001FFFFF);
  466. break;
  467. case IMAGE_REL_ALPHA_HINT :
  468. if ((vaTarget & 3) != 0) {
  469. ErrorPcon(pcon, UNALIGNEDFIXUP, SzNameFixupSym(pimage, rgsym + isym));
  470. CountFixupError(pimage);
  471. vaTarget &= ~3;
  472. }
  473. dw = *(DWORD UNALIGNED *) pb;
  474. // We don't mask and sign extend the displacement because
  475. // we only care about the low 14 bits of the result.
  476. lT = (LONG) dw;
  477. lT += (vaTarget >> 2); // Displacement is in DWORDs
  478. *(DWORD UNALIGNED *) pb = (dw & 0xFFFFC000) | (lT & 0x00003FFF);
  479. break;
  480. case IMAGE_REL_ALPHA_INLINE_REFLONG :
  481. // A INLINE_REFLONG has to be followed by a MATCH or ABSOLUTE
  482. // The proper way is to use MATCH relocations. Ancient
  483. // (obsolete) Alpha compilers emited ABSOLUTE relocations.
  484. // Also, the NT 3.1 SDK linker emited ABSOLUTE in import thunks.
  485. if ((iReloc == 0) ||
  486. ((prel[1].Type != IMAGE_REL_ALPHA_MATCH) &&
  487. (prel[1].Type != IMAGE_REL_ALPHA_ABSOLUTE))) {
  488. // UNDONE: This should be an error
  489. WarningPcon(pcon, UNMATCHEDPAIR, "INLINE_REFLONG");
  490. break;
  491. }
  492. iReloc--;
  493. prel++;
  494. if (fSaveDebugFixup && !fAbsolute) {
  495. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  496. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  497. }
  498. {
  499. LONG ibLow;
  500. WORD UNALIGNED *pwLow;
  501. DWORD vaTargetAndDisp;
  502. if (prel->Type == IMAGE_REL_ALPHA_ABSOLUTE) {
  503. // The displacement of 4 was implied by ABSOLUTE usage
  504. ibLow = 4;
  505. } else {
  506. ibLow = (LONG) prel->SymbolTableIndex;
  507. }
  508. pwLow = (WORD UNALIGNED *) (pb + ibLow);
  509. // If the low 16 bits would sign extend as a negative
  510. // number by the alpha chip (lda sign extends), add one
  511. // to the high 16 bits.
  512. vaTargetAndDisp = (*(WORD UNALIGNED *) pb << 16) + *pwLow;
  513. vaTargetAndDisp += vaTarget;
  514. *(WORD UNALIGNED *) pb = (WORD) (vaTargetAndDisp >> 16);
  515. *pwLow = (WORD) vaTargetAndDisp;
  516. if ((vaTargetAndDisp & 0x8000) != 0) {
  517. *(WORD UNALIGNED *) pb += 1;
  518. }
  519. assert(!fSkipIncrPdataFixup);
  520. if (!fAbsolute) {
  521. // Store both the high and low relocation information
  522. // if the image is to be remapped.
  523. StoreBaseRelocation(IMAGE_REL_BASED_HIGHADJ,
  524. rvaCur,
  525. isecTarget,
  526. vaTargetAndDisp - pimage->ImgOptHdr.ImageBase,
  527. fFixed);
  528. StoreBaseRelocation(IMAGE_REL_BASED_LOW,
  529. rvaCur + ibLow,
  530. isecTarget,
  531. 0,
  532. fFixed);
  533. }
  534. }
  535. break;
  536. case IMAGE_REL_ALPHA_REFHI :
  537. // A REFHI has to be followed by a PAIR
  538. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_ALPHA_PAIR)) {
  539. // UNDONE: This should be an error
  540. WarningPcon(pcon, UNMATCHEDPAIR, "REFHI");
  541. break;
  542. }
  543. iReloc--;
  544. prel++;
  545. if (fSaveDebugFixup && !fAbsolute) {
  546. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  547. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  548. }
  549. lT = *(SHORT UNALIGNED *) pb; // fetch the hi word
  550. lT <<= 16; // Shift to high half.
  551. // Sign extend the low.
  552. lT += (LONG) (SHORT) prel->SymbolTableIndex;
  553. lT += rvaTarget;
  554. assert(!fSkipIncrPdataFixup);
  555. if (!fAbsolute) {
  556. StoreBaseRelocation(IMAGE_REL_BASED_HIGHADJ,
  557. rvaCur,
  558. isecTarget,
  559. lT,
  560. fFixed);
  561. lT += pimage->ImgOptHdr.ImageBase;
  562. }
  563. // By adding the 0x8000 to the low word, if the 16th bit
  564. // is set, the addition will cause the high word to get
  565. // incremented. Because the chip sign extends the low word,
  566. // this will effectively cancel the increment at runtime.
  567. lT += 0x8000;
  568. *(SHORT UNALIGNED *) pb = (SHORT) (lT >> 16);
  569. break;
  570. case IMAGE_REL_ALPHA_REFLO :
  571. *(SHORT UNALIGNED *) pb += (SHORT) vaTarget;
  572. assert(!fSkipIncrPdataFixup);
  573. if (!fAbsolute) {
  574. StoreBaseRelocation(IMAGE_REL_BASED_LOW,
  575. rvaCur,
  576. isecTarget,
  577. 0,
  578. fFixed);
  579. }
  580. break;
  581. case IMAGE_REL_ALPHA_PAIR :
  582. // Shouldn't happen, but give warning if it does.
  583. // UNDONE: This should be an error
  584. WarningPcon(pcon, UNMATCHEDPAIR, "PAIR");
  585. break;
  586. case IMAGE_REL_ALPHA_MATCH :
  587. // Shouldn't happen, but give warning if it does.
  588. // UNDONE: This should be an error
  589. WarningPcon(pcon, UNMATCHEDPAIR, "MATCH");
  590. break;
  591. case IMAGE_REL_ALPHA_SECTION :
  592. if (isecTarget > 0) {
  593. *(WORD UNALIGNED *) pb += (WORD) isecTarget;
  594. } else if (fAbsolute) {
  595. // Max section # + 1 is the sstSegMap entry for absolute
  596. // symbols.
  597. *(WORD UNALIGNED *) pb += (WORD) (pimage->ImgFileHdr.NumberOfSections + 1);
  598. } else {
  599. *(WORD UNALIGNED *) pb += 0;
  600. }
  601. break;
  602. case IMAGE_REL_ALPHA_SECREL :
  603. if (!fAbsolute) {
  604. psec = PsecFindIsec(isecTarget, &pimage->secs);
  605. if (psec != NULL) {
  606. rvaTarget -= psec->rva;
  607. } else {
  608. // This occurs when a discarded comdat is the target of
  609. // a relocation in the .debug section.
  610. assert(rvaTarget == 0);
  611. }
  612. }
  613. // Check for old object files using SECREL for an instruction operand
  614. *(DWORD UNALIGNED *) pb += rvaTarget;
  615. if (!fDebugFixup && ((*(WORD UNALIGNED *) pb > MAXSHORT) || (rvaTarget >= MAXSHORT))) {
  616. // UNDONE: Better error?
  617. ErrorPcon(pcon, GPFIXUPTOOFAR, SzNameFixupSym(pimage, rgsym + isym));
  618. CountFixupError(pimage);
  619. }
  620. break;
  621. case IMAGE_REL_ALPHA_REFLONGNB :
  622. *(DWORD UNALIGNED *) pb += rvaTarget - RomOffset;
  623. break;
  624. case IMAGE_REL_ALPHA_SECRELHI :
  625. if (!fAbsolute) {
  626. psec = PsecFindIsec(isecTarget, &pimage->secs);
  627. if (psec != NULL) {
  628. rvaTarget -= psec->rva;
  629. } else {
  630. // This occurs when a discarded comdat is the target of
  631. // a relocation in the .debug section.
  632. assert(rvaTarget == 0);
  633. }
  634. }
  635. // A SECRELHI has to be followed by a PAIR
  636. if ((iReloc == 0) || (prel[1].Type != IMAGE_REL_ALPHA_PAIR)) {
  637. // UNDONE: This should be an error
  638. WarningPcon(pcon, UNMATCHEDPAIR, "SECRELHI");
  639. break;
  640. }
  641. iReloc--;
  642. prel++;
  643. if (fSaveDebugFixup && !fAbsolute) {
  644. DWORD rvaFixup = rvaSec + prel->VirtualAddress - RvaSrcPCON(pcon);
  645. SaveDebugFixup(prel->Type, 0, rvaFixup, prel->SymbolTableIndex);
  646. }
  647. lT = *(SHORT UNALIGNED *) pb; // fetch the hi word
  648. lT <<= 16; // Shift to high half.
  649. // Sign extend the low.
  650. lT += (LONG) (SHORT) prel->SymbolTableIndex;
  651. lT += rvaTarget;
  652. // By adding the 0x8000 to the low word, if the 16th bit
  653. // is set, the addition will cause the high word to get
  654. // incremented. Because the chip sign extends the low word,
  655. // this will effectively cancel the increment at runtime.
  656. lT += 0x8000;
  657. *(SHORT UNALIGNED *) pb = (SHORT) (lT >> 16);
  658. break;
  659. case IMAGE_REL_ALPHA_SECRELLO :
  660. if (!fAbsolute) {
  661. psec = PsecFindIsec(isecTarget, &pimage->secs);
  662. if (psec != NULL) {
  663. rvaTarget -= psec->rva;
  664. } else {
  665. // This occurs when a discarded comdat is the target of
  666. // a relocation in the .debug section.
  667. assert(rvaTarget == 0);
  668. }
  669. }
  670. *(SHORT UNALIGNED *) pb += (SHORT) rvaTarget;
  671. break;
  672. default:
  673. ErrorPcon(pcon, UNKNOWNFIXUP, prel->Type, SzNameFixupSym(pimage, rgsym + isym));
  674. CountFixupError(pimage);
  675. break;
  676. }
  677. }
  678. }
  679. void
  680. AlphaLinkerInit(
  681. PIMAGE pimage,
  682. BOOL * pfIlinkSupported
  683. )
  684. {
  685. *pfIlinkSupported = TRUE;
  686. // If section alignment switch not used, set the default.
  687. if (!FUsedOpt(pimage->SwitchInfo, OP_ALIGN)) {
  688. pimage->ImgOptHdr.SectionAlignment = _8K;
  689. }
  690. ApplyFixups = ApplyAlphaFixups;
  691. if (pimage->Switch.Link.fROM) {
  692. fImageMappedAsFile = TRUE;
  693. pimage->ImgFileHdr.SizeOfOptionalHeader = sizeof(IMAGE_ROM_OPTIONAL_HEADER);
  694. if (!pimage->ImgOptHdr.BaseOfCode) {
  695. pimage->ImgOptHdr.BaseOfCode = pimage->ImgOptHdr.ImageBase;
  696. }
  697. pimage->ImgOptHdr.ImageBase = 0;
  698. } else {
  699. // If the section alignment is < 8192 then make the file alignment the
  700. // same as the section alignment. This ensures that the image will
  701. // be the same in memory as in the image file, since the alignment is less
  702. // than the maximum alignment of memory-mapped files.
  703. if (pimage->ImgOptHdr.SectionAlignment < _8K) {
  704. fImageMappedAsFile = TRUE;
  705. pimage->ImgOptHdr.FileAlignment = pimage->ImgOptHdr.SectionAlignment;
  706. }
  707. }
  708. }
  709. const char *
  710. SzAlphaRelocationType(
  711. WORD wType,
  712. WORD *pcb,
  713. BOOL *pfSymValid
  714. )
  715. {
  716. const char *szName;
  717. WORD cb;
  718. BOOL fSymValid = TRUE;
  719. switch (wType) {
  720. case IMAGE_REL_ALPHA_ABSOLUTE :
  721. szName = "ABS";
  722. cb = 0;
  723. fSymValid = FALSE;
  724. break;
  725. case IMAGE_REL_ALPHA_REFLONG :
  726. szName = "REFLONG";
  727. cb = sizeof(DWORD);
  728. break;
  729. case IMAGE_REL_ALPHA_REFQUAD :
  730. szName = "REFQUAD";
  731. cb = 2 * sizeof(LONG);
  732. break;
  733. case IMAGE_REL_ALPHA_GPREL32 :
  734. szName = "GPREL32";
  735. cb = sizeof(DWORD);
  736. break;
  737. case IMAGE_REL_ALPHA_LITERAL :
  738. szName = "LITERAL";
  739. cb = sizeof(SHORT);
  740. break;
  741. case IMAGE_REL_ALPHA_LITUSE :
  742. szName = "LITUSE";
  743. cb = sizeof(SHORT);
  744. break;
  745. case IMAGE_REL_ALPHA_GPDISP :
  746. szName = "GPDISP";
  747. cb = 0; // UNDONE
  748. break;
  749. case IMAGE_REL_ALPHA_BRADDR :
  750. szName = "BRADDR";
  751. cb = sizeof(DWORD);
  752. break;
  753. case IMAGE_REL_ALPHA_HINT :
  754. szName = "HINT";
  755. cb = sizeof(DWORD);
  756. break;
  757. case IMAGE_REL_ALPHA_INLINE_REFLONG :
  758. szName = "INLINE_REFLONG";
  759. cb = sizeof(WORD); // UNDONE: There are really two discontiguous WORDs
  760. break;
  761. case IMAGE_REL_ALPHA_REFHI :
  762. szName = "REFHI";
  763. cb = sizeof(SHORT);
  764. break;
  765. case IMAGE_REL_ALPHA_REFLO :
  766. szName = "REFLO";
  767. cb = sizeof(SHORT);
  768. break;
  769. case IMAGE_REL_ALPHA_PAIR :
  770. szName = "PAIR";
  771. cb = 0;
  772. fSymValid = FALSE;
  773. break;
  774. case IMAGE_REL_ALPHA_MATCH :
  775. szName = "MATCH";
  776. cb = 0;
  777. fSymValid = FALSE;
  778. break;
  779. case IMAGE_REL_ALPHA_SECTION :
  780. szName = "SECTION";
  781. cb = sizeof(SHORT);
  782. break;
  783. case IMAGE_REL_ALPHA_SECREL :
  784. szName = "SECREL";
  785. cb = sizeof(DWORD);
  786. break;
  787. case IMAGE_REL_ALPHA_REFLONGNB :
  788. szName = "REFLONGNB";
  789. cb = sizeof(DWORD);
  790. break;
  791. case IMAGE_REL_ALPHA_SECRELHI :
  792. szName = "SECRELHI";
  793. cb = sizeof(SHORT);
  794. break;
  795. case IMAGE_REL_ALPHA_SECRELLO :
  796. szName = "SECRELLO";
  797. cb = sizeof(SHORT);
  798. break;
  799. default :
  800. szName = NULL;
  801. cb = 0;
  802. fSymValid = FALSE;
  803. break;
  804. }
  805. *pcb = cb;
  806. *pfSymValid = fSymValid;
  807. return(szName);
  808. }