obj2ti.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244
  1. // Written by Julien Muchembled.
  2. // Fixed by Romain Lievin for Linux.
  3. // Further modifications by Sebastian Reichelt, Kevin Kofler and Paul Froissart.
  4. // Copyright (c) 2001-2002. All rights reserved.
  5. // default: don't include AmigaOS support
  6. //#define SUPPORT_AMIGA
  7. // This needs to be defined BEFORE including obj2ti.h, since it is used in
  8. // that header.
  9. #include "obj2ti.h"
  10. // default: don't print out extra debugging information
  11. //#define TEXT_DEBUG
  12. #ifdef TEXT_DEBUG
  13. # define DEBUG_PRINT(str...) (printf (str))
  14. #else
  15. # define DEBUG_PRINT(str...)
  16. #endif
  17. // default: catch symbols with unknown class
  18. #define CHECK_SYMBOLS
  19. #define MAX_VAR_SIZE 65517
  20. __inline unsigned short br2 (void *pp)
  21. {
  22. unsigned char *p = (unsigned char *) pp;
  23. return ((unsigned short) p[0] << 8) + (unsigned short) p[1];
  24. }
  25. __inline unsigned long br4 (void *pp)
  26. {
  27. unsigned char *p = (unsigned char *) pp;
  28. return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16)
  29. + ((unsigned long) p[2] << 8) + (unsigned long) p[3];
  30. }
  31. __inline void bw2 (void *pp, unsigned short w)
  32. {
  33. unsigned char *p = (unsigned char *) pp;
  34. *p++ = (unsigned char)(w>>8);
  35. *p = (unsigned char) w;
  36. }
  37. __inline void bw4 (void *pp, unsigned long dw)
  38. {
  39. unsigned char *p = (unsigned char *) pp;
  40. *p++ = (unsigned char)(dw>>24);
  41. *p++ = (unsigned char)(dw>>16);
  42. *p++ = (unsigned char)(dw>>8);
  43. *p = (unsigned char) dw;
  44. }
  45. __inline void ba4 (void *p, unsigned long dw)
  46. { bw4 (p, br4 (p) + dw); }
  47. __inline unsigned short lr2 (void *pp)
  48. {
  49. unsigned char *p = (unsigned char *) pp;
  50. return (unsigned short) p[0] + ((unsigned short) p[1] << 8);
  51. }
  52. __inline unsigned long lr4 (void *pp)
  53. {
  54. unsigned char *p = (unsigned char *) pp;
  55. return (unsigned long) p[0] + ((unsigned long) p[1] << 8)
  56. + ((unsigned long) p[2] << 16) + ((unsigned long) p[3] << 24);
  57. }
  58. __inline void lw2 (void *pp, unsigned short w)
  59. {
  60. unsigned char *p = (unsigned char *) pp;
  61. *p++ = (unsigned char) w;
  62. *p = (unsigned char)(w>>8);
  63. }
  64. __inline void lw4 (void *pp, unsigned long dw)
  65. {
  66. unsigned char *p = (unsigned char *) pp;
  67. *p++ = (unsigned char) dw;
  68. *p++ = (unsigned char)(dw>>=8);
  69. *p++ = (unsigned char)(dw>>=8);
  70. *p = (unsigned char)(dw>>8);
  71. }
  72. __inline void la4 (void *p, unsigned long dw)
  73. { lw4 (p, lr4 (p) + dw); }
  74. void Object::AllocExt (int CurHunk, Import **Imp16, Import **Imp32, Export **Exports)
  75. {
  76. if (Hunk[CurHunk].nImp16)
  77. *Imp16 = Hunk[CurHunk].Imp16 = new Import[Hunk[CurHunk].nImp16];
  78. if (Hunk[CurHunk].nImp32)
  79. *Imp32 = Hunk[CurHunk].Imp32 = new Import[Hunk[CurHunk].nImp32];
  80. if (Hunk[CurHunk].nExports)
  81. *Exports = Hunk[CurHunk].Exports = new Export[Hunk[CurHunk].nExports];
  82. }
  83. #ifdef SUPPORT_AMIGA
  84. ObjErr Object::ReadAmiga ()
  85. {
  86. int CurHunk=-1; unsigned long *am = o32, size, *Ext[3]={NULL,NULL,NULL};
  87. bBadExport = true;
  88. for (size=Size>>2; size>0; size--) {
  89. DWORD n, HunkType = br4(am++);
  90. n = br4 (am);
  91. switch (HunkType) {
  92. default: return OBJERR_HunkType;
  93. case HunkUnit:
  94. case HunkName:
  95. case HunkDbg:
  96. size -= ++n; am += n;
  97. case HunkEnd: break;
  98. case HunkCode:
  99. if (CodeHunk >= 0) return OBJERR_NbScns;
  100. else {
  101. CodeHunk = ++CurHunk;
  102. Hunk[CurHunk].size = n << 2;
  103. Hunk[CurHunk].o32 = ++am;
  104. am += n; size -= n+1;
  105. } break;
  106. case HunkData:
  107. if (DataHunk >= 0) return OBJERR_NbScns;
  108. else {
  109. DataHunk = ++CurHunk;
  110. Hunk[CurHunk].size = n << 2;
  111. Hunk[CurHunk].o32 = ++am;
  112. am += n; size -= n+1;
  113. } break;
  114. case HunkBSS:
  115. if (BSSHunk >= 0) return OBJERR_NbScns;
  116. else Hunk[BSSHunk = ++CurHunk].size = n << 2, am++, size--;
  117. break;
  118. case HunkR16:
  119. fprintf (stderr, "Warning: 16-bit relocations are unsupported.\n");
  120. for (; size>0 && n; n=br4 (am))
  121. n += 2, am += n, size -= n;
  122. am++; size--; break;
  123. case HunkR32:
  124. if (CurHunk < 0) return OBJERR_R32Hunk;
  125. else {
  126. for (; size>0 && n; n=br4 (am)) {
  127. DWORD k = br4 (++am);
  128. if (k < 3 && !Hunk[CurHunk].R32[k]) {
  129. unsigned long *R32;
  130. Hunk[CurHunk].nR32[k] = n;
  131. Hunk[CurHunk].R32[k] = R32 = new unsigned long [n];
  132. for (am++; n--; size--) *R32++ = br4 (am++);
  133. size -= 2;
  134. } else return OBJERR_R32Hunk;
  135. } am++; size--;
  136. } break;
  137. case HunkExt:
  138. if (CurHunk < 0 || Ext[CurHunk]) return OBJERR_ExtHunk;
  139. else {
  140. unsigned char type; unsigned long nExtRefs=0, nImports=0;
  141. Ext[CurHunk] = am;
  142. do {
  143. n = (br4 (am) & 0xFFFFFF) + 1;
  144. switch (type = *(unsigned char *)am++) {
  145. default: return OBJERR_ExtType;
  146. case TypeEnd: break;
  147. case TypeImport32:
  148. Hunk[CurHunk].nImp32++;
  149. case TypeImport16:
  150. case TypeImport16Alt:
  151. am += n; size -= n;
  152. n = br4 (am-1);
  153. nImports++;
  154. case TypeExport:
  155. am += n; size -= n; nExtRefs++;
  156. } } while (size-- > 0 && type != TypeEnd);
  157. if (!nExtRefs) Ext[CurHunk] = NULL;
  158. else {
  159. Hunk[CurHunk].nExports = nExtRefs - nImports;
  160. Hunk[CurHunk].nImp16 = nImports - Hunk[CurHunk].nImp32;
  161. } } } }
  162. if (size) return OBJERR_Size;
  163. if (CurHunk < 0) return OBJERR_NbScns;
  164. nscns = CurHunk+1;
  165. for (CurHunk=0; (unsigned int)CurHunk<nscns; CurHunk++)
  166. if ((am = Ext[CurHunk])) {
  167. unsigned char type;
  168. Import *Imp16, *Imp32; Export *Exports;
  169. AllocExt (CurHunk, &Imp16, &Imp32, &Exports);
  170. while ((type = *(unsigned char *)am) != TypeEnd) {
  171. unsigned long *rlc, n = br4 (am++) & 0xFFFFFF;
  172. switch (type) {
  173. case TypeImport32:
  174. Imp32->name = (char *)am;
  175. am += n; n = br4 (am++);
  176. Imp32->nrlcs = n;
  177. Imp32->rlc = rlc = new unsigned long [n];
  178. while (n--) *rlc++ = br4 (am++);
  179. Imp32++;
  180. break;
  181. case TypeImport16:
  182. case TypeImport16Alt:
  183. Imp16->name = (char *)am;
  184. am += n; n = br4 (am++);
  185. Imp16->nrlcs = n;
  186. Imp16->rlc = rlc = new unsigned long [n];
  187. while (n--) *rlc++ = br4 (am++);
  188. Imp16++;
  189. break;
  190. case TypeExport:
  191. Exports->name = (char *)am; am += n;
  192. //Exports->size = 0;
  193. Exports->value = br4 (am++);
  194. Exports++;
  195. } } }
  196. return OBJERR_OK;
  197. }
  198. #endif
  199. char *Object::COFF_ReadName (SYMENT *sym, char *Str)
  200. {
  201. return br4 (sym->e.e.e_zeroes) ?
  202. sym->e.e_name :
  203. &Str[br4 (sym->e.e.e_offset)];
  204. }
  205. ObjErr Object::ReadCOFF ()
  206. {
  207. int CurHunk=BSSHunk=0; SCNHDR *scn = (SCNHDR *)&o8[sizeof(FILHDR)];
  208. RELOC *Relocs[2]; unsigned short nrlcs[2];
  209. unsigned long i, nSyms, s_vaddr[3];
  210. nscns = br2 (filhdr->f_nscns);
  211. if (nscns < 3) return OBJERR_NbScns;
  212. if (nscns > 3) {
  213. fprintf (stderr, "Warning: More than 3 COFF sections. Excess sections ignored.\n");
  214. nscns = 3;
  215. }
  216. if (br2 (filhdr->f_opthdr)) return OBJERR_OptHdr;
  217. s_vaddr[0] = 0;
  218. for (i=0; i<nscns; i++)
  219. switch (br4 (scn[i].s_flags) & (STYP_TEXT | STYP_DATA | STYP_BSS)) {
  220. default: return OBJERR_ScnType;
  221. case STYP_TEXT | STYP_DATA:
  222. case STYP_TEXT:
  223. if (CodeHunk >= 0) return OBJERR_NbScns;
  224. else {
  225. Relocs[CurHunk] = (RELOC *)&o8[br4 (scn[i].s_relptr)];
  226. nrlcs[CurHunk] = br2 (scn[i].s_nreloc);
  227. Hunk[CodeHunk = ++CurHunk].o8 = &o8[br4 (scn[i].s_scnptr)];
  228. Hunk[CurHunk].size = br4 (scn[i].s_size);
  229. s_vaddr[CurHunk] = br4 (scn[i].s_vaddr);
  230. }
  231. break;
  232. case STYP_BSS:
  233. // This program can only work properly if the BSS section is the last
  234. // one.
  235. if (CurHunk != (int) nscns - 1) return OBJERR_NbScns;
  236. else {
  237. // Objcopy produces real BSS sections, while the GNU assembler
  238. // simply leaves an empty section.
  239. // Both versions will work here, since the relocs are different
  240. // (section 0 (none) vs. section 3).
  241. Hunk[0].size = br4 (scn[i].s_size);
  242. // This is just a stupid number which has to be subtracted from all
  243. // relocs.
  244. s_vaddr[0] = br4 (scn[i].s_vaddr);
  245. }
  246. break;
  247. case STYP_DATA:
  248. if (DataHunk >= 0) return OBJERR_NbScns;
  249. else {
  250. Relocs[CurHunk] = (RELOC *)&o8[br4 (scn[i].s_relptr)];
  251. nrlcs[CurHunk] = br2 (scn[i].s_nreloc);
  252. Hunk[DataHunk = ++CurHunk].o8 = &o8[br4 (scn[i].s_scnptr)];
  253. Hunk[CurHunk].size = br4 (scn[i].s_size);
  254. s_vaddr[CurHunk] = br4 (scn[i].s_vaddr);
  255. }
  256. break;
  257. }
  258. SYMENT *sym, *Sym = (SYMENT *)&o8[br4 (filhdr->f_symptr)];
  259. char *Str = (char *)&Sym[nSyms = br4 (filhdr->f_nsyms)];
  260. struct SYMNFO {
  261. unsigned char ok;
  262. unsigned char R32;
  263. unsigned char IsBSSSymbol;
  264. unsigned short hunk;
  265. struct {
  266. unsigned short n16;
  267. unsigned short n32;
  268. } Hunk[2];
  269. } *SymNfo = (SYMNFO *)_alloca (nSyms*sizeof(SYMNFO));
  270. unsigned long *R32[2][3];
  271. memset (&R32, 0, sizeof (R32)); memset (SymNfo, 0, nSyms*sizeof(SYMNFO));
  272. /************************************\
  273. | Basic symbol and relocation info |
  274. \************************************/
  275. // Read in the symbol table and build the SymNfo table with additional
  276. // information.
  277. // FIXME: Imported symbols shouldn't be considered as exports as well.
  278. for (sym=Sym,i=0; i<nSyms; sym++,i++) {
  279. DEBUG_PRINT ("Symbol %ld: Type 0x%lx; Section %ld; Value 0x%lx\n", (long) i, (long) (br2 (sym->e_sclass)), (long) (short) (br2 (sym->e_scnum)), (long) (br4 (sym->e_value)));
  280. #ifdef CHECK_SYMBOLS
  281. switch (br2 (sym->e_sclass)) {
  282. // All non-standard symbols are not 'ok'.
  283. case 0x200:
  284. case 0x201:
  285. case 0x300:
  286. case 0x301:
  287. #endif
  288. { unsigned int hunk = br2 (sym->e_scnum);
  289. if (hunk == nscns) {
  290. // It is a symbol in the BSS section, as objcopy produces them.
  291. // This program assumes that the BSS section is the last one.
  292. // This could be greatly simplified if we assume that there is
  293. // always just one single symbol (called '.bss') at the start of
  294. // the BSS section.
  295. SymNfo[i].IsBSSSymbol = 1;
  296. SymNfo[i].R32 = 1;
  297. ba4 (sym->e_value, (DWORD)-(long)s_vaddr[0]);
  298. }
  299. if (hunk >= nscns) hunk = 0;
  300. Hunk[SymNfo[i].hunk = hunk].nExports++;
  301. SymNfo[i].ok = 1;
  302. }
  303. #ifdef CHECK_SYMBOLS
  304. }
  305. #endif
  306. }
  307. // Here the number of imports and relocations is read in. No relocation is
  308. // actually done.
  309. for (CurHunk=1; (unsigned int)CurHunk<nscns; CurHunk++) {
  310. unsigned short j; RELOC *rlc = Relocs[CurHunk-1];
  311. for (j=nrlcs[CurHunk-1]; j; rlc++,j--) {
  312. unsigned long i = br4 (rlc->r_symndx);
  313. sym = &Sym[i];
  314. if (SymNfo[i].ok) {
  315. unsigned long value = br4 (sym->e_value);
  316. DEBUG_PRINT ("Reloc %ld: Type 0x%lx; Section %ld; Address 0x%lx\n", (long) (nrlcs[CurHunk-1] - j + 1), (long) (br2 (rlc->r_type)), (long) CurHunk, (long) (long) (br4 (rlc->r_vaddr)));
  317. DEBUG_PRINT (" Symbol %ld (%s)\n", (long) i, COFF_ReadName (sym, Str));
  318. switch (br2 (rlc->r_type)) {
  319. default:
  320. return OBJERR_RlcType;
  321. case 0x10:
  322. case 0x13:
  323. DEBUG_PRINT (" 16-bit reloc\n");
  324. if (!value && !SymNfo[i].hunk) {
  325. DEBUG_PRINT (" Normal reloc: Section %ld; Address 0x%lx\n", (long) SymNfo[i].hunk, (long) (br4 (sym->e_value)));
  326. if (!SymNfo[i].Hunk[CurHunk-1].n16++) Hunk[CurHunk].nImp16++;
  327. }
  328. break;
  329. case 0x11:
  330. case 0x14:
  331. // Warning: BSSHunk is 0.
  332. // And 0 is also used for imported symbols, which don't have a
  333. // section they reside in.
  334. // Luckily however, we can decide by looking at the value:
  335. // If it's 0, it's an import, like a ROM_CALL or RAM_CALL.
  336. // Otherwise, we have a BSS entry. The value then marks the size
  337. // of the entry, in bytes.
  338. // That means we simply replace the value by an offset into the
  339. // BSS section (plus s_vaddr, because COFF requires it). Since
  340. // this offset can be 0 for the first symbol in the BSS section,
  341. // we sign a special flag.
  342. if (SymNfo[i].hunk==0) {
  343. DEBUG_PRINT (" Symbol has section 0\n");
  344. DEBUG_PRINT (" Value: %ld (marked as BSS: %ld)\n", (long) value, (long) SymNfo[i].IsBSSSymbol);
  345. if (value || SymNfo[i].IsBSSSymbol) {
  346. DEBUG_PRINT (" Inserting reloc into BSS section (0)\n");
  347. Hunk[CurHunk].nR32[0]++;
  348. if (!SymNfo[i].R32) {
  349. unsigned long blocksize = value;
  350. SymNfo[i].R32 = 1;
  351. SymNfo[i].IsBSSSymbol = 1;
  352. bw4 (sym->e_value, value = s_vaddr[0] + Hunk[0].size);
  353. Hunk[0].size += blocksize;
  354. DEBUG_PRINT (" New BSS size: %ld\n", (long) Hunk[0].size);
  355. DEBUG_PRINT (" New value for symbol: %ld\n", (long) value);
  356. }
  357. } else {
  358. DEBUG_PRINT (" Adding import\n");
  359. if (!SymNfo[i].Hunk[CurHunk-1].n32++) Hunk[CurHunk].nImp32++;
  360. }
  361. } else {
  362. DEBUG_PRINT (" Normal reloc: Section %ld; Address 0x%lx\n", (long) SymNfo[i].hunk, (long) (br4 (sym->e_value)));
  363. Hunk[CurHunk].nR32[SymNfo[i].hunk]++;
  364. SymNfo[i].R32 = 1;
  365. } }
  366. } else {
  367. fprintf (stderr, "Warning: Removing reloc to unsupported symbol '%s'.\n", COFF_ReadName (sym, Str));
  368. } } }
  369. /*****************************************************\
  370. | Allocation of export, import, and relocation tables |
  371. \*****************************************************/
  372. // All tables are built up using the results from the counting above.
  373. Export *Exports[3]={NULL,NULL,NULL};
  374. unsigned long **Imp16rlc[3], **Imp32rlc[3];
  375. for (i=0; i<nscns; i++) {
  376. Import *Imp16=NULL, *Imp32=NULL;
  377. // Allocate imports and exports for hunk i using its nImp16 etc. values.
  378. AllocExt (i, &Imp16, &Imp32, &Exports[i]);
  379. if (i) {
  380. unsigned int n16=0, n32=0;
  381. unsigned long j, **pImp16rlc, **pImp32rlc;
  382. pImp16rlc = Imp16rlc[i] = Hunk[i].nImp16 ? new unsigned long *[Hunk[i].nImp16] : NULL;
  383. pImp32rlc = Imp32rlc[i] = Hunk[i].nImp32 ? new unsigned long *[Hunk[i].nImp32] : NULL;
  384. for (sym=Sym,j=0; j<nSyms; sym++,j++)
  385. if (!SymNfo[j].hunk) {
  386. if (SymNfo[j].Hunk[i-1].n16) {
  387. Imp16->name = COFF_ReadName (sym, Str);
  388. Imp16->nrlcs = SymNfo[j].Hunk[i-1].n16;
  389. Imp16->rlc = *pImp16rlc++ = new unsigned long [Imp16->nrlcs];
  390. Imp16++; SymNfo[j].Hunk[i-1].n16 = ++n16;
  391. }
  392. if (SymNfo[j].Hunk[i-1].n32) {
  393. Imp32->name = COFF_ReadName (sym, Str);
  394. Imp32->nrlcs = SymNfo[j].Hunk[i-1].n32;
  395. Imp32->rlc = *pImp32rlc++ = new unsigned long [Imp32->nrlcs];
  396. Imp32++; SymNfo[j].Hunk[i-1].n32 = ++n32;
  397. } }
  398. // Allocate the relocation tables.
  399. for (j=0; j<nscns; j++) if (Hunk[i].nR32[j])
  400. R32[i-1][j] = Hunk[i].R32[j] = new unsigned long [Hunk[i].nR32[j]];
  401. } }
  402. /******************************\
  403. | Initialization of all tables |
  404. \******************************/
  405. // Initialize export tables.
  406. for (sym=Sym,i=0; i<nSyms; sym++,i++)
  407. if (SymNfo[i].ok) {
  408. Exports[SymNfo[i].hunk]->name = COFF_ReadName (sym, Str);
  409. Exports[SymNfo[i].hunk]->value = br4 (sym->e_value);
  410. Exports[SymNfo[i].hunk]++;
  411. }
  412. // Initialize import and relocation tables, and relocate.
  413. for (CurHunk=1; (unsigned int)CurHunk<nscns; CurHunk++) {
  414. unsigned long j; RELOC *rlc = Relocs[CurHunk-1];
  415. for (j=nrlcs[CurHunk-1]; j; rlc++,j--) {
  416. unsigned long i = br4 (rlc->r_symndx);
  417. if (SymNfo[i].ok) {
  418. int k; unsigned long ofs;
  419. ofs = br4 (rlc->r_vaddr) - s_vaddr[CurHunk];
  420. switch (br2 (rlc->r_type)) {
  421. case 0x10:
  422. case 0x13:
  423. if ((k = SymNfo[i].Hunk[CurHunk-1].n16))
  424. *Imp16rlc[CurHunk][k-1]++ = ofs;
  425. break;
  426. case 0x11:
  427. case 0x14:
  428. if (SymNfo[i].R32) {
  429. *R32[CurHunk-1][SymNfo[i].hunk]++ = ofs;
  430. DEBUG_PRINT ("Relocating 32 bits at offset 0x%lx in section %ld\n", (long) ofs, (long) CurHunk);
  431. DEBUG_PRINT (" Old value: 0x%lx\n", (long) br4 (&Hunk[CurHunk].o8[ofs]));
  432. ba4 (&Hunk[CurHunk].o8[ofs], (SymNfo[i].IsBSSSymbol ? br4 (Sym[i].e_value) : 0) + ((DWORD)-(long)s_vaddr[SymNfo[i].hunk]));
  433. DEBUG_PRINT (" New value: 0x%lx\n", (long) br4 (&Hunk[CurHunk].o8[ofs]));
  434. } else if ((k = SymNfo[i].Hunk[CurHunk-1].n32))
  435. *Imp32rlc[CurHunk][k-1]++ = ofs;
  436. } } }
  437. Delete (Imp16rlc[CurHunk]);
  438. Delete (Imp32rlc[CurHunk]);
  439. }
  440. return OBJERR_OK;
  441. }
  442. ObjErr Object::Read (char *FileName)
  443. {
  444. long size = 0;
  445. FILE *f = fopen (FileName, "rb");
  446. if (!f) return OBJERR_Open;
  447. fseek (f, 0, SEEK_END);
  448. Size = ftell (f); rewind (f);
  449. if ((o0 = malloc (Size)))
  450. size = fread (o0, 1, Size, f);
  451. fclose (f);
  452. if (!o0) return OBJERR_Mem;
  453. if (size != Size) return OBJERR_Read;
  454. switch (br2 (o0)) {
  455. #ifdef SUPPORT_AMIGA
  456. case 0:
  457. ObjFmt = OBJFMT_Amiga;
  458. return ReadAmiga ();
  459. #endif
  460. case 0x150:
  461. ObjFmt = OBJFMT_COFF;
  462. return ReadCOFF ();
  463. }
  464. return OBJERR_Unknown;
  465. }
  466. void Object::MergeImp (
  467. unsigned long nImp1, Import * Imp1,
  468. unsigned long &nImp2, Import * &Imp2,
  469. unsigned long size)
  470. {
  471. unsigned long n; Import *imp2 = Imp2;
  472. for (n=0; n<nImp2; imp2++,n++) {
  473. unsigned long k, *rlc = imp2->rlc;
  474. for (k=imp2->nrlcs; k--; rlc++) *rlc += size;
  475. Import *imp1 = Imp1;
  476. for (k=nImp1; k--; imp1++)
  477. if (!strcmp (imp1->name, imp2->name)) {
  478. unsigned long i, j;
  479. i = imp1->nrlcs; j = imp2->nrlcs;
  480. rlc = new unsigned long [i+j];
  481. memcpy (rlc, imp1->rlc, i * sizeof (long));
  482. memcpy (&rlc[i], imp2->rlc, j * sizeof (long));
  483. Delete (imp1->rlc); Delete (imp2->rlc);
  484. imp1->rlc = rlc; imp1->nrlcs += j;
  485. if (!--nImp2) Delete (Imp2);
  486. else {
  487. memmove (imp2, imp2+1, (nImp2-n--) * sizeof (Import));
  488. imp2--;
  489. } break;
  490. } }
  491. }
  492. void Object::Merge2 (
  493. unsigned long &n1, void * &p1,
  494. unsigned long &n2, void * &p2,
  495. unsigned long SizeOf)
  496. {
  497. if (n2) {
  498. unsigned char *p = new unsigned char [(n1+n2)*SizeOf];
  499. memcpy (p, p1, n1 * SizeOf);
  500. memcpy (&p[n1*SizeOf], p2, n2 * SizeOf);
  501. DeleteCast (unsigned char **, p1);
  502. DeleteCast (unsigned char **, p2);
  503. n1 += n2; n2 = 0;
  504. p1 = p;
  505. }
  506. }
  507. void Object::Merge (int &First, int &Second)
  508. {
  509. int first, second;
  510. if ((unsigned int)(second=Second) < nscns) {
  511. if ((unsigned int)(first=First) < nscns) {
  512. int hunk; unsigned long size = Hunk[first].size;
  513. for (hunk=0; hunk<(int)nscns; hunk++) if (hunk != second) {
  514. unsigned long i, *R32 = Hunk[second].R32[hunk];
  515. for (i=Hunk[second].nR32[hunk]; i--; R32++) *R32 += size;
  516. }
  517. MergeImp (
  518. Hunk[first].nImp16, Hunk[first].Imp16,
  519. Hunk[second].nImp16, Hunk[second].Imp16,
  520. size);
  521. MergeImp (
  522. Hunk[first].nImp32, Hunk[first].Imp32,
  523. Hunk[second].nImp32, Hunk[second].Imp32,
  524. size);
  525. {
  526. unsigned long i; Export *exp = Hunk[second].Exports;
  527. for (i=Hunk[second].nExports; i--; exp++) exp->value += size;
  528. }
  529. for (hunk=0; hunk<(int)nscns; hunk++) {
  530. unsigned long i, j, *R32_1, *R32_2;
  531. i = Hunk[hunk].nR32[first]; j = Hunk[hunk].nR32[second];
  532. Hunk[hunk].nR32[first] += j; Hunk[hunk].nR32[second] = 0;
  533. R32_1 = new unsigned long [i+j];
  534. memcpy (R32_1, Hunk[hunk].R32[first], i*sizeof(long));
  535. Delete (Hunk[hunk].R32[first]);
  536. Hunk[hunk].R32[first] = R32_1; R32_1 += i;
  537. R32_2 = Hunk[hunk].R32[second];
  538. for (; j--; R32_1++) {
  539. ba4 (&Hunk[hunk].o8[*R32_1 = *R32_2++], size);
  540. if (hunk == second) *R32_1 += size;
  541. }
  542. Delete (Hunk[hunk].R32[second]);
  543. }
  544. for (hunk=0; hunk<(int)nscns; hunk++) if (hunk != second) {
  545. unsigned long i, j, *R32;
  546. i = Hunk[first].nR32[hunk]; j = Hunk[second].nR32[hunk];
  547. Hunk[first].nR32[hunk] += j; Hunk[second].nR32[hunk] = 0;
  548. R32 = new unsigned long [i+j];
  549. memcpy (R32, Hunk[first].R32[hunk], i*sizeof(long));
  550. memcpy (&R32[i], Hunk[second].R32[hunk], j*sizeof(long));
  551. Delete (Hunk[first].R32[hunk]);
  552. Delete (Hunk[second].R32[hunk]);
  553. Hunk[first].R32[hunk] = R32;
  554. }
  555. Merge2 (Hunk[first].nImp16, (void * &) Hunk[first].Imp16, Hunk[second].nImp16, (void * &) Hunk[second].Imp16, sizeof (Import));
  556. Merge2 (Hunk[first].nImp32, (void * &) Hunk[first].Imp32, Hunk[second].nImp32, (void * &) Hunk[second].Imp32, sizeof (Import));
  557. Merge2 (Hunk[first].nExports, (void * &) Hunk[first].Exports, Hunk[second].nExports, (void * &) Hunk[second].Exports, sizeof (Export));
  558. unsigned size2 = Hunk[second].size;
  559. Hunk[first].size += size2; Hunk[second].size = 0;
  560. unsigned char *o8 = new unsigned char [size + size2];
  561. memcpy (o8, Hunk[first].o0, size);
  562. memcpy (&o8[size], Hunk[second].o0, size2);
  563. if (Hunk[second].DelDat)
  564. DeleteCast (unsigned char **, Hunk[second].o0);
  565. if (Hunk[first].DelDat)
  566. DeleteCast (unsigned char **, Hunk[first].o0);
  567. else Hunk[first].DelDat = true;
  568. Hunk[first].o8 = o8;
  569. } else First = second, Second = first;
  570. }
  571. }
  572. #define CONFLICT "%s is incompatible with %s"
  573. TI68kErr TI68k::Conflict (TI68kType Type2)
  574. {
  575. if (szErr) {
  576. Delete (szErr[TI68kERR_Conflict-1]);
  577. char *msg = szErr[TI68kERR_Conflict-1] = new char [
  578. sizeof(CONFLICT) - 4
  579. + strlen(szTI68kType[Type2-1])
  580. + strlen(szTI68kType[Type-1])];
  581. sprintf (msg, CONFLICT, szTI68kType[Type2-1], szTI68kType[Type-1]);
  582. } return TI68kERR_Conflict;
  583. }
  584. void TI68k::UndefRef (Import *imp)
  585. {
  586. fprintf (stderr, "Error: %lu undefined reference(s) to '%s'.\n", imp->nrlcs, imp->name);
  587. }
  588. enum { RAM32, eRAM32, RAM16, eRAM16, ROM, LIBS };
  589. TI68kErr TI68k::MakeDoorsOS ()
  590. {
  591. bool bErr=false; Import *imp;
  592. int i, *lens, n16, n32, *ndx, nExtra16=0, nLibs=LIBS, nRAM16=0;
  593. n16 = (signed)Hunk[CodeHunk].nImp16;
  594. n32 = (signed)Hunk[CodeHunk].nImp32;
  595. lens = (int *)_alloca (n32 * sizeof (int));
  596. ndx = (int *)_alloca (n32 * sizeof (int));
  597. for (imp=Hunk[CodeHunk].Imp32,i=0; i<n32; imp++,i++) {
  598. char *p = strrchr (&imp->name[1], '@');
  599. if ((!p) && ((*imp->name)!='_') && strncmp(imp->name,"L__",3)) {
  600. p = strstr (&imp->name[1], "__");
  601. }
  602. if (p) {
  603. lens[i] = p - imp->name;
  604. if (lens[i] > 8 && strncmp (imp->name, "_extraramaddr@", 14))
  605. lens[i] = 0;
  606. } else if (!strncmp (imp->name, "_RAM_CALL_", 10)
  607. || !strncmp (imp->name, "_ROM_CALL_", 10))
  608. lens[i] = 9;
  609. else if (!strncmp (imp->name, "_extraramaddr_", 14))
  610. lens[i] = 13;
  611. else lens[i] = 0;
  612. if (!lens[i]) UndefRef (imp), bErr = true;
  613. else {
  614. int j; Import *imp2 = Hunk[CodeHunk].Imp32;
  615. for (j=0; j<i; imp2++, j++)
  616. if (lens[i] == lens[j])
  617. if (!strncmp (imp2->name, imp->name, lens[i]))
  618. lens[i] = -lens[i], ndx[i] = ndx[j], j = i;
  619. if (j == i) {
  620. if (lens[i] <= 8) ndx[i] = nLibs++;
  621. else switch (imp->name[2]) {
  622. case 'A': ndx[i] = RAM32; break;
  623. case 'O': ndx[i] = ROM; break;
  624. default: ndx[i] = eRAM32;
  625. } } } }
  626. for (imp = Hunk[CodeHunk].Imp16,i=0; i<n16; imp++, i++) {
  627. if (!strncmp (imp->name, "_extraramaddr", 13)) nExtra16++;
  628. else if (!strncmp (imp->name, "_RAM_CALL_", 10)) nRAM16++;
  629. else UndefRef (imp), bErr = true;
  630. }
  631. if (bErr) return TI68kERR_DoorsOSUndef;
  632. struct LibRef {
  633. unsigned short ord, nrlcs;
  634. unsigned long *rlc;
  635. } **Refs = (LibRef **)_alloca (nLibs * sizeof (LibRef *));
  636. struct Lib {
  637. char name[9];
  638. unsigned char minVersion /*__attribute__ ((packed))*/;
  639. union {
  640. unsigned short nRefs;
  641. unsigned short nExps;
  642. };
  643. union {
  644. LibRef *Refs;
  645. unsigned short *Exps;
  646. };
  647. } Exp, *Libs = (Lib *)_alloca (nLibs * sizeof (Lib));
  648. memset (Libs, 0, nLibs * sizeof (Lib));
  649. Libs[RAM16].nRefs = nRAM16; Libs[eRAM16].nRefs = nExtra16;
  650. struct {
  651. unsigned short code, comment, main, exit, extra;
  652. } Ofs = { 0, 0, 0, 0, 0};
  653. unsigned short HeaderSize = 40 + (nLibs-LIBS) * 12 + 2 *
  654. (unsigned short)(Hunk[CodeHunk].nR32[CodeHunk] + Hunk[CodeHunk].nR32[BSSHunk]);
  655. if (!(Hunk[BSSHunk].size)) HeaderSize-=6;
  656. for (imp=Hunk[CodeHunk].Imp32,i=0; i<n32; imp++,i++) {
  657. if (lens[i] > 0 && ndx[i] >= LIBS)
  658. strncpy (Libs[ndx[i]].name, imp->name, lens[i]);
  659. Libs[ndx[i]].nRefs++;
  660. }
  661. if (Libs[ROM].nRefs) HeaderSize += 2;
  662. if (Libs[RAM32].nRefs || Libs[eRAM32].nRefs
  663. || Libs[RAM16].nRefs || Libs[eRAM16].nRefs)
  664. HeaderSize += 2;
  665. for (i=0; i<nLibs; i++) {
  666. Libs[i].Refs = Refs[i]
  667. = (LibRef *)_alloca (Libs[i].nRefs * sizeof (LibRef));
  668. HeaderSize += Libs[i].nRefs * 4;
  669. }
  670. for (imp=Hunk[CodeHunk].Imp32,i=0; i<n32; imp++,i++) {
  671. char *p; LibRef **refs = &Refs[ndx[i]];
  672. (*refs)->ord = (unsigned short)
  673. strtoul (&imp->name[abs(lens[i])+(((imp->name[abs(lens[i])]=='_')&&(imp->name[abs(lens[i])+1]=='_'))?2:1)], &p, 16);
  674. HeaderSize += ((*refs)->nrlcs = (unsigned short) imp->nrlcs) * 2;
  675. (*refs)->rlc = imp->rlc; (*refs)++;
  676. }
  677. nRAM16 = nExtra16 = 0;
  678. for (imp = Hunk[CodeHunk].Imp16,i=0; i<n16; imp++, i++) {
  679. LibRef *refs; int len; char *p;
  680. if (!strncmp (imp->name, "_RAM_CALL_", 10))
  681. len = 10, refs = &Libs[RAM16].Refs[nRAM16++];
  682. else len = 14, refs = &Libs[eRAM16].Refs[nExtra16++];
  683. refs->ord = (unsigned short)strtoul (&imp->name[len], &p, 16);
  684. if (*p) UndefRef (imp), bErr = true;
  685. HeaderSize += (refs->nrlcs = (unsigned short) imp->nrlcs) * 2;
  686. refs->rlc = imp->rlc;
  687. }
  688. if (bErr) return TI68kERR_DoorsOSUndef;
  689. Export *exp = Hunk[CodeHunk].Exports; Exp.nRefs = 0;
  690. for (i=(int)Hunk[CodeHunk].nExports; i--; exp++) {
  691. if (!strcmp (exp->name, "_comment"))
  692. Ofs.comment = (unsigned short)exp->value;
  693. else if (!strcmp (exp->name, "_main"))
  694. Ofs.main = (unsigned short)exp->value;
  695. else if (!strcmp (exp->name, "_exit"))
  696. Ofs.exit = (unsigned short)exp->value;
  697. else if (!strcmp (exp->name, "_extraram"))
  698. Ofs.extra = (unsigned short)exp->value;
  699. else {
  700. char *p = strrchr (&exp->name[1], '@');
  701. if ((!p) && ((*exp->name)!='_') && strncmp(exp->name,"L__",3)) {
  702. p = strstr (&exp->name[1], "__");
  703. }
  704. if (p) {
  705. if (!strncmp(p+((*p=='_')?2:1),"version",7)) {
  706. int len = p - exp->name;
  707. if (len > 8) return TI68kERR_BadExport;
  708. unsigned long j = strtoul (p+((*p=='_')?9:8), &p, 16);
  709. if ((*p) || (j > 255ul)) return TI68kERR_BadExport; else {
  710. for (int ii=0; ii<nLibs; ii++) {
  711. if (!strncmp(Libs[ii].name,exp->name,len)) Libs[ii].minVersion=j;
  712. }
  713. }} else {
  714. int len = p - exp->name;
  715. if (len > 8) return TI68kERR_BadExport;
  716. if (!Exp.nRefs) {
  717. strncpy (Exp.name, exp->name, len);
  718. Exp.name[len] = 0;
  719. } else if (strncmp (Exp.name, exp->name, len))
  720. return TI68kERR_BadExport;
  721. Exp.nRefs++;
  722. }
  723. } } }
  724. if (Exp.nRefs) {
  725. HeaderSize += 4 + 2 * Exp.nRefs;
  726. Exp.Refs = (LibRef *)_alloca (Exp.nRefs * sizeof (short));
  727. memset (Exp.Refs, -1, Exp.nRefs * sizeof (short));
  728. exp = Hunk[CodeHunk].Exports;
  729. for (i=(int)Hunk[CodeHunk].nExports; i--; exp++) {
  730. char *p = strrchr (&exp->name[1], '@');
  731. if ((!p) && ((*exp->name)!='_') && strncmp(exp->name,"L__",3)) {
  732. p = strstr (&exp->name[1], "__");
  733. if (p) p++;
  734. }
  735. if (p++) {
  736. if (strncmp(p,"version",7)) {
  737. unsigned long j = strtoul (p, &p, 16);
  738. if (*p || j >= Exp.nExps || (short)Exp.Exps[j] != -1)
  739. return TI68kERR_BadExport;
  740. Exp.Exps[j] = (unsigned short)exp->value;
  741. }
  742. } } }
  743. union {
  744. void *o0;
  745. unsigned char *o8;
  746. unsigned short *o16;
  747. unsigned long *o32;
  748. };
  749. Ofs.code = HeaderSize + (Type == TI68k_68kP ? sizeof (PrgmStub) : sizeof (LibStub));
  750. o8 = dat = new unsigned char [size = Ofs.code + Hunk[CodeHunk].size + 3];
  751. bw2 (o16++, 0x6100);
  752. bw2 (o16++, HeaderSize-2);
  753. bw4 (o32++, ('6'<<24)+('8'<<16)+('k'<<8)+(Type==TI68k_68kP?'P':'L'));
  754. *o16++ = 0;
  755. bw2 (o16++, Ofs.comment ? Ofs.comment + Ofs.code : 0);
  756. bw2 (o16++, Type == TI68k_68kP ? Ofs.main + Ofs.code : 0);
  757. bw2 (o16++, Ofs.exit ? Ofs.exit + Ofs.code : 0);
  758. bw2 (o16++, Flags);
  759. *o16++ = 0; *o32++ = 0;
  760. bw2 (o16++, Ofs.extra ? Ofs.extra + Ofs.code : 0);
  761. bw2 (o16++, nLibs-LIBS);
  762. for (i=LIBS; i<nLibs; o8+=10,i++)
  763. memcpy (o0, Libs[i].name, 10);
  764. for (i=LIBS; i<nLibs; i++) {
  765. int j = Libs[i].nRefs; bw2 (o16++, --j);
  766. LibRef *Refs = Libs[i].Refs;
  767. do {
  768. bw2 (o16++, Refs->ord);
  769. unsigned long *rlc = Refs->rlc;
  770. unsigned short k=Refs++->nrlcs;
  771. while (k--) bw2 (o16++, Ofs.code + (unsigned short)*rlc++);
  772. *o16++ = 0;
  773. } while (j--);
  774. }
  775. if (!Libs[ROM].nRefs) *o16++ = 0;
  776. else {
  777. bw2 (o16++, (unsigned short)-1);
  778. int j = Libs[ROM].nRefs; bw2 (o16++, --j);
  779. LibRef *Refs = Libs[ROM].Refs;
  780. do {
  781. bw2 (o16++, Refs->ord);
  782. unsigned long *rlc = Refs->rlc;
  783. unsigned short k=Refs++->nrlcs;
  784. while (k--) bw2 (o16++, Ofs.code + (unsigned short)*rlc++);
  785. *o16++ = 0;
  786. } while (j--);
  787. }
  788. i = Libs[RAM32].nRefs + Libs[eRAM32].nRefs
  789. + Libs[RAM16].nRefs + Libs[eRAM16].nRefs;
  790. if (!i--) *o16++ = 0;
  791. else {
  792. bw2 (o16++, (unsigned short)-1); bw2 (o16++, i);
  793. for (i=RAM32; i<=eRAM16; i++) {
  794. int j; LibRef *Refs = Libs[i].Refs;
  795. for (j=Libs[i].nRefs; j; j--) {
  796. bw2 (o16++, Refs->ord + (unsigned short)(i<<14));
  797. unsigned long *rlc = Refs->rlc;
  798. unsigned short k=Refs++->nrlcs;
  799. while (k--) bw2 (o16++, Ofs.code + (unsigned short)*rlc++);
  800. *o16++ = 0;
  801. } } }
  802. unsigned long *R32 = Hunk[CodeHunk].R32[CodeHunk];
  803. for (i=(int)Hunk[CodeHunk].nR32[CodeHunk]; i; i--)
  804. bw2 (o16++, Ofs.code + (unsigned short)*R32++);
  805. *o16++ = 0;
  806. if (Hunk[BSSHunk].size) {
  807. bw2 (&dat[0x14], (unsigned short)(o8-dat));
  808. bw4 (o32++, Hunk[BSSHunk].size);
  809. R32 = Hunk[CodeHunk].R32[BSSHunk];
  810. for (i=(int)Hunk[CodeHunk].nR32[BSSHunk]; i; i--)
  811. bw2 (o16++, Ofs.code + (unsigned short)*R32++);
  812. *o16++ = 0;
  813. } else bw2 (&dat[0x14], (unsigned short)0);
  814. if (Exp.nRefs) {
  815. bw2 (&dat[0x16], (unsigned short)(o8-dat));
  816. bw2 (o16++, Exp.nRefs);
  817. for (i=0; i<Exp.nRefs; i++)
  818. bw2 (o16++, Ofs.code + (unsigned short)Exp.Exps[i]);
  819. *o16++ = 0;
  820. }
  821. if (Type == TI68k_68kP)
  822. memcpy (o0, PrgmStub, sizeof (PrgmStub)), o8 += sizeof (PrgmStub);
  823. else memcpy (o0, LibStub, sizeof (LibStub)), o8 += sizeof (LibStub);
  824. memcpy (o0, Hunk[CodeHunk].o0, Hunk[CodeHunk].size);
  825. o8 += Hunk[CodeHunk].size;
  826. R32 = Hunk[CodeHunk].R32[CodeHunk];
  827. for (i=(int)Hunk[CodeHunk].nR32[CodeHunk]; i; i--)
  828. ba4 (&dat[Ofs.code+(unsigned short)*R32++], Ofs.code);
  829. *o16++ = 0; *o8 = 0xF3;
  830. return TI68kERR_OK;
  831. }
  832. bool TI68k::NostubImp (unsigned long n, Import *imp)
  833. {
  834. if (!n) return false;
  835. for (; n--; imp++) UndefRef (imp);
  836. return true;
  837. }
  838. TI68kErr TI68k::MakeNostub ()
  839. {
  840. if (BSSHunk >= 0) if (Hunk[BSSHunk].size) {
  841. Hunk[BSSHunk].o8 = new unsigned char [Hunk[BSSHunk].size];
  842. Hunk[BSSHunk].DelDat = true;
  843. memset (Hunk[BSSHunk].o8, 0, Hunk[BSSHunk].size);
  844. Merge (CodeHunk, BSSHunk);
  845. }
  846. if (!NostubImp (Hunk[CodeHunk].nImp16, Hunk[CodeHunk].Imp16)
  847. && !NostubImp (Hunk[CodeHunk].nImp32, Hunk[CodeHunk].Imp32)) {
  848. unsigned long n = Hunk[CodeHunk].nR32[CodeHunk];
  849. unsigned long *R32 = Hunk[CodeHunk].R32[CodeHunk];
  850. size = Hunk[CodeHunk].size + 4 * n + 3;
  851. dat = new unsigned char [size];
  852. memcpy (dat, Hunk[CodeHunk].o0, Hunk[CodeHunk].size);
  853. unsigned short *o16 = (unsigned short *)&dat[size-1];
  854. *(unsigned char *)o16-- = 0xF3;
  855. for (; n--; R32++) {
  856. bw2 (o16--, (unsigned short)*R32);
  857. bw2 (o16--, (unsigned short)br4 (&dat[*R32]));
  858. } *o16 = 0;
  859. return TI68kERR_OK;
  860. } else return TI68kERR_NostubUndef;
  861. }
  862. bool TI68k::ExtImp (unsigned long n, Import *imp)
  863. {
  864. if (!n) return false;
  865. for (; n--; imp++) UndefRef (imp);
  866. return true;
  867. }
  868. char *OutputName2=0;
  869. bool InList(char *str, char *list) {
  870. if (!*list) return true;
  871. while (*list)
  872. if (!strcmp(str,list)) return true;
  873. else while (*list++);
  874. return false;
  875. }
  876. void maj_conv(char *s) {
  877. char c;
  878. while ((c=*s++))
  879. if (c>='A' && c<='Z')
  880. memmove(s+1,s,strlen(s)+1), *s='-';
  881. }
  882. TI68kErr TI68k::MakeExt ()
  883. {
  884. /* TODO (?) : BSS aren't supported */
  885. if (BSSHunk >= 0) if (Hunk[BSSHunk].size) {
  886. Hunk[BSSHunk].o8 = new unsigned char [Hunk[BSSHunk].size];
  887. Hunk[BSSHunk].DelDat = true;
  888. memset (Hunk[BSSHunk].o8, 0, Hunk[BSSHunk].size);
  889. Merge (CodeHunk, BSSHunk);
  890. }
  891. char *ExportList;
  892. FILE *ex_fp=fopen("export.dat","rb");
  893. if (!ex_fp) ExportList="";
  894. else ExportList = new char [300000], fread(ExportList,300000,1,ex_fp), fclose(ex_fp);
  895. FILE *def_fp=fopen("deflt.txt","a+");
  896. unsigned long nExp = 0, szExpN = 0;
  897. int n=Hunk[CodeHunk].nExports; Export *exp = Hunk[CodeHunk].Exports;
  898. unsigned long *expOffs = new unsigned long [n]; char **expName = new char * [n];
  899. for (; n--; exp++) {
  900. if (InList(exp->name, ExportList)) {
  901. char buf[200];
  902. sprintf(buf,"%s.ref",exp->name);
  903. maj_conv(buf);
  904. FILE *fp=fopen(buf,"w");
  905. if (!fp) { printf("Couldn't open '%s' !\n",buf); return TI68kERR_Unknown; }
  906. sprintf(buf,"%s.ext",OutputName2);
  907. fputs(buf,fp);
  908. fclose(fp);
  909. if (def_fp) fprintf(def_fp,"#var %s\n",exp->name);
  910. expOffs[nExp] = exp->value, expName[nExp] = exp->name,
  911. szExpN += strlen(exp->name)+1, nExp++;
  912. }
  913. }
  914. if (def_fp) fclose(def_fp);
  915. unsigned long nRef0 = 0, nRef = 0, nImp = 0, szImpN = 0; int i;
  916. int n32=Hunk[CodeHunk].nImp32, n16=Hunk[CodeHunk].nImp16;
  917. Import *imp32 = Hunk[CodeHunk].Imp32, *imp16 = Hunk[CodeHunk].Imp16, *imp;
  918. for (n=n16,imp=imp16; n--; imp++)
  919. nRef0+=imp->nrlcs+1;
  920. for (n=n32,imp=imp32; n--; imp++)
  921. nRef0+=imp->nrlcs+1;
  922. unsigned long *impOffs = new unsigned long [nRef0];
  923. char **impName = new char * [n16+n32];
  924. for (n=n16,imp=imp16; n--; imp++) {
  925. for (i=imp->nrlcs;i--;)
  926. impOffs[nRef] = imp->rlc[i]-2, nRef++;
  927. impOffs[nRef] = -2ul, nRef++;
  928. impName[nImp] = imp->name, szImpN += strlen(imp->name)+1, nImp++;
  929. }
  930. for (n=n32,imp=imp32; n--; imp++) {
  931. for (i=imp->nrlcs;i--;)
  932. impOffs[nRef] = imp->rlc[i], nRef++;
  933. impOffs[nRef] = -2ul, nRef++;
  934. impName[nImp] = imp->name, szImpN += strlen(imp->name)+1, nImp++;
  935. }
  936. unsigned long nInt = Hunk[CodeHunk].nR32[CodeHunk];
  937. unsigned long *R32 = Hunk[CodeHunk].R32[CodeHunk];
  938. size = (2+Hunk[CodeHunk].size) + (2*nInt+2) + (2*nExp+2+szExpN) + (szExpN&1) + (2*nRef+2+szImpN) + (szImpN&1) + (2);
  939. dat = new unsigned char [size];
  940. memset (dat, 0, size);
  941. unsigned char *p8 = dat;
  942. #define w16(x) (bw2(p8,(unsigned short)(x)), p8+=2)
  943. w16(2+Hunk[CodeHunk].size);
  944. memcpy (p8, Hunk[CodeHunk].o0, Hunk[CodeHunk].size), p8+=Hunk[CodeHunk].size;
  945. /* Relocation section */
  946. for (n=nInt; n--; R32++) {
  947. w16(2+(unsigned short)*R32);
  948. }
  949. w16(0);
  950. /* Export section */
  951. for (n=nExp;n--;)
  952. w16(2+expOffs[n]);
  953. w16(0);
  954. for (n=nExp;n--;)
  955. strcpy((char *)p8, expName[n]), p8+=strlen(expName[n])+1;
  956. if (szExpN&1) *p8++=0;
  957. /* Import section */
  958. for (i=0;i<(int)nRef;i++)
  959. w16(2+impOffs[i]);
  960. w16(0);
  961. for (i=0;i<(int)nImp;i++)
  962. strcpy((char *)p8, impName[i]), p8+=strlen(impName[i])+1;
  963. if (szImpN&1) *p8++=0;
  964. /* BSS section */
  965. w16(0);
  966. #ifndef NDEBUG
  967. if (p8!=&dat[size]) { printf("Size mismatch!\n"); return TI68kERR_Unknown; }
  968. #endif
  969. return TI68kERR_OK;
  970. }
  971. TI68kErr TI68k::Make ()
  972. {
  973. int hunk;
  974. for (hunk=0; hunk<3; hunk++) {
  975. unsigned long i; Export *exp = Hunk[hunk].Exports;
  976. for (i=Hunk[hunk].nExports; i; exp++,i--) {
  977. if (!strcmp (exp->name, szTI68kType[TI68k_68kL-1])) {
  978. if (Type == TI68k_none) Type = TI68k_68kL;
  979. else return Conflict (TI68k_68kL);
  980. }
  981. else if (!strcmp (exp->name, szTI68kType[TI68k_68kP-1])) {
  982. if (Type == TI68k_none) Type = TI68k_68kP;
  983. else if (Type != TI68k_nostub)
  984. return Conflict (TI68k_68kP);
  985. }
  986. else if (!strcmp (exp->name, szTI68kType[TI68k_ext-1])) {
  987. if (Type == TI68k_none) Type = TI68k_ext;
  988. else
  989. return Conflict (TI68k_ext);
  990. }
  991. else if (!strcmp (exp->name, szTI68kType[TI68k_nostub-1])) {
  992. if (Type == TI68k_none || Type == TI68k_68kP)
  993. Type = TI68k_nostub;
  994. else if (Type != TI68k_nostub_dll)
  995. return Conflict (TI68k_nostub);
  996. }
  997. else if (!strcmp (exp->name, szTI68kType[TI68k_nostub_dll-1])) {
  998. if (Type == TI68k_none || Type == TI68k_68kP || Type == TI68k_nostub)
  999. Type = TI68k_nostub_dll;
  1000. else return Conflict (TI68k_nostub_dll);
  1001. }
  1002. else if (!strcmp (exp->name, szTI68kType[TI68k_prosit-1]))
  1003. return TI68kERR_prosit;
  1004. else if (!strcmp (exp->name, "_ti89"))
  1005. Output89 = 1;
  1006. else if (!strcmp(exp->name, "_ti92plus"))
  1007. Output92p = 1;
  1008. else if (!strncmp(exp->name, "_flag_", 6))
  1009. Flags |= 1 << strtoul (&exp->name[6], NULL, 10);
  1010. else if (!strncmp(exp->name, "_version", 6))
  1011. LibVersion = strtoul (&exp->name[8], NULL, 16);
  1012. else if (bBadExport
  1013. && strcmp (exp->name, "_comment")
  1014. && strcmp (exp->name, "_exit")
  1015. && strcmp (exp->name, "_extraram")) {
  1016. char *p = strrchr (&exp->name[1], '@');
  1017. if (p) if (p[1]) {
  1018. strtoul (&p[1], &p, 16);
  1019. if (*p) p = NULL;
  1020. }
  1021. if (!p) return TI68kERR_BadExport;
  1022. } } }
  1023. if (!Output89 && !Output92p && Type!=TI68k_ext) return TI68kERR_NoOutput;
  1024. Merge (CodeHunk, DataHunk);
  1025. switch (Type) {
  1026. case TI68k_ext:
  1027. return MakeExt ();
  1028. case TI68k_nostub:
  1029. case TI68k_nostub_dll:
  1030. return MakeNostub ();
  1031. default:
  1032. return MakeDoorsOS ();
  1033. }
  1034. return TI68kERR_Unknown;
  1035. }
  1036. TI68kErr TI68k::DoSave (char *FileName, char *ext, char *Header, unsigned long HeaderSize, unsigned short chksum)
  1037. {
  1038. if (strlen (FileName) + strlen (ext) < _MAX_PATH) {
  1039. unsigned char buf[2]; char FullName[_MAX_PATH]; FILE *f;
  1040. f = fopen (strcat (strcpy (FullName, FileName), ext), "wb");
  1041. if (HeaderSize) fwrite (Header, 1, HeaderSize, f);
  1042. bw2 (buf, (unsigned short)size);
  1043. fwrite (buf, 1, 2, f);
  1044. fwrite (dat, 1, size, f);
  1045. if (HeaderSize) lw2 (buf, chksum), fwrite (buf, 1, 2, f);
  1046. fclose (f);
  1047. }
  1048. return TI68kERR_OK;
  1049. }
  1050. TI68kErr TI68k::Save (char *FileName, bool outputbin, bool quiet)
  1051. {
  1052. static char Header[]=
  1053. "**TI92P*\001\0main\0\0\0\0"
  1054. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  1055. "\001\0R\0\0\0\0\0\0\0\0\0\0\0!\0\0\0\0\0\0\0¥Z\0\0\0";
  1056. #define HeaderSize (sizeof (Header))
  1057. char AMSname[9], *p; unsigned short chksum;
  1058. if (GetExeSize () > MAX_VAR_SIZE)
  1059. return TI68kERR_TooLarge;
  1060. AMSname[8] = 0; p = strrchr (FileName, '\\');
  1061. _strlwr (strncpy (AMSname, p ? p + 1 : FileName, 8));
  1062. strncpy (&Header[0x40], AMSname, 8);
  1063. lw4 (&Header[0x4C], size + HeaderSize + 4);
  1064. if (outputbin || Type == TI68k_nostub_dll || Type == TI68k_ext) {
  1065. if (Type == TI68k_nostub_dll && !outputbin)
  1066. DoSave (FileName, ".ndl", NULL, 0, 0);
  1067. else if (Type == TI68k_ext && !outputbin)
  1068. DoSave (FileName, ".ext", NULL, 0, 0);
  1069. else
  1070. DoSave (FileName, ".bin", NULL, 0, 0);
  1071. if (!quiet) {
  1072. if (Output89) printf ("Linked for TI-89\n");
  1073. if (Output92p) printf ("Linked for TI-92 Plus\n");
  1074. }
  1075. } else {
  1076. chksum = LOBYTE (size) + HIBYTE (size);
  1077. unsigned long i;
  1078. for (i=0; i<size; i++) chksum += (unsigned short)dat[i];
  1079. if (Output89) DoSave (FileName, ".89z", strncpy (Header, "**TI89**", 8), HeaderSize, chksum);
  1080. if (Output92p) DoSave (FileName, ".9xz", strncpy (Header, "**TI92P*", 8), HeaderSize, chksum);
  1081. }
  1082. return TI68kERR_OK;
  1083. }
  1084. int main (int argc, char **argv)
  1085. {
  1086. bool help, outputbin=false, quiet=false, ver=false;
  1087. int err = 0; char *ObjFile=NULL, *OutputName=NULL;
  1088. TI68kType Type = TI68k_none;
  1089. for (help=!--argc; argc && !err; argc--) {
  1090. char *p = *++argv;
  1091. if (*p++ == '-') {
  1092. do switch (*p++) {
  1093. case 'o':
  1094. if (!OutputName) {
  1095. OutputName = *++argv;
  1096. if (--argc) break;
  1097. }
  1098. default: err = -1; break;
  1099. case '?':
  1100. case 'h': help = true; break;
  1101. case 'O': outputbin = true; break;
  1102. case 'q': quiet = true; break;
  1103. case 'v': ver = true; break;
  1104. case 'x': Type = TI68k_ext; break;
  1105. case '-':
  1106. if (!strcmp (p, "help")) help = true;
  1107. else if (!strcmp (p, "version")) ver = true;
  1108. else if (!strcmp (p, "quiet")) quiet = true;
  1109. else if (!strcmp (p, "outputbin")) outputbin = true;
  1110. else if (!strcmp (p, "output") && !OutputName && --argc) OutputName = *++argv;
  1111. else if (!strcmp (p, "ext")) Type = TI68k_ext;
  1112. else err = -1;
  1113. case 0:
  1114. p = NULL;
  1115. } while (p);
  1116. } else if (ObjFile) err = -1;
  1117. else ObjFile = *argv;
  1118. }
  1119. if (err) {
  1120. fputs ("Invalid command line.\n", stderr);
  1121. help = true;
  1122. } else if (ver) puts (
  1123. "Obj2Ti 1.01f by Julien Muchembled <julien.muchembled@netcourrier.com>\n"
  1124. "Modified by: Romain Lievin <rlievin@mail.com>\n"
  1125. " Sebastian Reichelt <Sebastian@tigcc.ticalc.org>\n"
  1126. " Kevin Kofler <Kevin@tigcc.ticalc.org>\n"
  1127. " and Paul Froissart\n"
  1128. );
  1129. if (help) puts (
  1130. "Usage: obj2ti [options] file\n"
  1131. "Options:\n"
  1132. " -h --help\tDisplay this information\n"
  1133. " -o --output\tFollowed by project name\n"
  1134. " -O --outputbin\tOutput a binary file, not a calc file\n"
  1135. " -q --quiet\tLink without displaying extra verbose information\n"
  1136. " -v --version\tDisplay program version number\n"
  1137. " -x --ext\tOutput a .ext object suitable for GTC\n"
  1138. );
  1139. else if (ObjFile) {
  1140. TI68k *ti = new TI68k (szErr, Type);
  1141. err = ti->Read (ObjFile);
  1142. if (!err) {
  1143. char *ext = strrchr (OutputName2 = ObjFile, '.');
  1144. if (ext && (!strcmp(ext,".o") || !strcmp(ext,".O")))
  1145. *ext = 0;
  1146. err = ti->Make ();
  1147. if (!err) {
  1148. if (!OutputName) {
  1149. char *ext = strrchr (OutputName = ObjFile, '.');
  1150. if (ext) if (!_stricmp (ext, ".o")) *ext = 0;
  1151. } err = ti->Save (OutputName, outputbin, quiet);
  1152. if (!err && !quiet) printf ("Linked %s - Size: %lu bytes\n", OutputName, ti->GetExeSize ());
  1153. } }
  1154. if (err) {
  1155. if (err == TI68kERR_TooLarge)
  1156. fprintf (stderr, "Error: Size of %lu bytes exceeds maximum by %lu.\n", ti->GetExeSize (), ti->GetExeSize () - MAX_VAR_SIZE);
  1157. else if (szErr[err-1])
  1158. fprintf (stderr, "%s.\n", szErr[err-1]);
  1159. }
  1160. delete ti;
  1161. }
  1162. return err;
  1163. }