2
0

ogrel.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. {
  2. Copyright (c) 2020 by Nikolay Nikolov
  3. Contains the ASCII relocatable object file format (*.rel) reader and writer
  4. This is the object format used on the Z80 platforms.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ogrel;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. { common }
  23. cclasses,globtype,
  24. { target }
  25. systems,
  26. { assembler }
  27. cpuinfo,cpubase,aasmbase,assemble,link,
  28. { output }
  29. ogbase,
  30. owbase;
  31. type
  32. TRelRelocationFlag=(
  33. rrfByte, { bit 0 }
  34. rrfSymbol, { bit 1 }
  35. rrfPcRelative, { bit 2 }
  36. rrfTwoByteObjectFormatForByteData, { bit 3 }
  37. rrfUnsignedByteData, { bit 4 }
  38. rrfPage0Reference, { bit 5 }
  39. rrfPageNNNReference, { bit 6 }
  40. rrfMSBWith2ByteMode, { bit 7 }
  41. rrfThreeByteObjectFormatForByteData, { bit 8 }
  42. rrfRealMSBForThreeByteMode, { bit 9 }
  43. rrfReserved10, { bit 10 }
  44. rrfReserved11); { bit 11 }
  45. TRelRelocationFlags=set of TRelRelocationFlag;
  46. { TRelRelocation }
  47. TRelRelocation = class(TObjRelocation)
  48. private
  49. function GetSecOrSymIdx: longint;
  50. public
  51. RelFlags: TRelRelocationFlags;
  52. HiByte: Byte;
  53. constructor CreateSymbol(ADataOffset:TObjSectionOfs;s:TObjSymbol;Atyp:TObjRelocationType);
  54. constructor CreateSection(ADataOffset:TObjSectionOfs;aobjsec:TObjSection;Atyp:TObjRelocationType);
  55. function EncodeFlags: string;
  56. property SecOrSymIdx: longint read GetSecOrSymIdx;
  57. end;
  58. { TRelObjData }
  59. TRelObjData = class(TObjData)
  60. public
  61. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  62. function sectiontype2align(atype:TAsmSectiontype):longint;override;
  63. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  64. end;
  65. { TRelObjOutput }
  66. TRelObjOutput = class(tObjOutput)
  67. private
  68. procedure writeString(const S: ansistring);
  69. procedure writeLine(const S: ansistring);
  70. procedure WriteAreaContentAndRelocations(sec: TObjSection);
  71. protected
  72. function writeData(Data:TObjData):boolean;override;
  73. public
  74. constructor create(AWriter:TObjectWriter);override;
  75. end;
  76. { TRelAssembler }
  77. TRelAssembler = class(tinternalassembler)
  78. constructor create(info: pasminfo; smart:boolean);override;
  79. end;
  80. { TRelObjInput }
  81. TRelObjInput = class(TObjInput)
  82. private const
  83. MaxBufSize=512;
  84. private
  85. FBuf: array [0..MaxBufSize-1] of Char;
  86. FBufSize: Integer;
  87. FBufPos: Integer;
  88. function FillBuf: boolean;
  89. function AtEndOfBuf: boolean;
  90. function AtEoF: boolean;
  91. function ReadChar(out c: char): boolean;
  92. function PeekChar(out c: char): boolean;
  93. function ReadLine(out s: string): boolean;
  94. public
  95. constructor create;override;
  96. function ReadObjData(AReader:TObjectreader;out Data:TObjData):boolean;override;
  97. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  98. end;
  99. { TIntelHexExeOutput }
  100. TIntelHexExeOutput = class(TExeOutput)
  101. private
  102. procedure writeString(const S: ansistring);
  103. procedure writeLine(const S: ansistring);
  104. protected
  105. function writeData:boolean;override;
  106. procedure DoRelocationFixup(objsec:TObjSection);override;
  107. public
  108. constructor create;override;
  109. end;
  110. { TZXSpectrumIntelHexExeOutput }
  111. TZXSpectrumIntelHexExeOutput = class(TIntelHexExeOutput)
  112. public
  113. constructor create;override;
  114. end;
  115. implementation
  116. uses
  117. SysUtils,
  118. cutils,verbose,globals,
  119. fmodule,aasmtai,aasmdata,
  120. ogmap,owar,
  121. version
  122. ;
  123. function tohex(q: qword): string;
  124. begin
  125. result:=HexStr(q,16);
  126. while (Length(result)>1) and (result[1]='0') do
  127. delete(result,1,1);
  128. end;
  129. {*****************************************************************************
  130. TRelRelocation
  131. *****************************************************************************}
  132. function TRelRelocation.GetSecOrSymIdx: longint;
  133. begin
  134. if assigned(symbol) then
  135. result:=symbol.symidx
  136. else if assigned(objsection) then
  137. result:=objsection.SecSymIdx
  138. else
  139. internalerror(2020050502);
  140. end;
  141. constructor TRelRelocation.CreateSymbol(ADataOffset: TObjSectionOfs; s: TObjSymbol; Atyp: TObjRelocationType);
  142. begin
  143. inherited;
  144. case Atyp of
  145. RELOC_ABSOLUTE_HI8:
  146. begin
  147. size:=1;
  148. RelFlags:=[rrfSymbol,rrfByte,rrfTwoByteObjectFormatForByteData,rrfMSBWith2ByteMode];
  149. end;
  150. RELOC_ABSOLUTE_LO8:
  151. begin
  152. size:=1;
  153. RelFlags:=[rrfSymbol,rrfByte,rrfTwoByteObjectFormatForByteData];
  154. end;
  155. RELOC_ABSOLUTE:
  156. begin
  157. size:=2;
  158. RelFlags:=[rrfSymbol];
  159. end;
  160. else
  161. internalerror(2020050601);
  162. end;
  163. end;
  164. constructor TRelRelocation.CreateSection(ADataOffset: TObjSectionOfs; aobjsec: TObjSection; Atyp: TObjRelocationType);
  165. begin
  166. inherited;
  167. case Atyp of
  168. RELOC_ABSOLUTE_HI8:
  169. begin
  170. size:=1;
  171. RelFlags:=[rrfByte,rrfTwoByteObjectFormatForByteData,rrfMSBWith2ByteMode];
  172. end;
  173. RELOC_ABSOLUTE_LO8:
  174. begin
  175. size:=1;
  176. RelFlags:=[rrfByte,rrfTwoByteObjectFormatForByteData];
  177. end;
  178. RELOC_ABSOLUTE:
  179. begin
  180. size:=2;
  181. RelFlags:=[];
  182. end;
  183. else
  184. internalerror(2020050613);
  185. end;
  186. end;
  187. function TRelRelocation.EncodeFlags: string;
  188. var
  189. FlagsWord: Word;
  190. begin
  191. FlagsWord:=0;
  192. if rrfByte in RelFlags then
  193. Inc(FlagsWord,1);
  194. if rrfSymbol in RelFlags then
  195. Inc(FlagsWord,2);
  196. if rrfPcRelative in RelFlags then
  197. Inc(FlagsWord,4);
  198. if rrfTwoByteObjectFormatForByteData in RelFlags then
  199. Inc(FlagsWord,8);
  200. if rrfUnsignedByteData in RelFlags then
  201. Inc(FlagsWord,16);
  202. if rrfPage0Reference in RelFlags then
  203. Inc(FlagsWord,32);
  204. if rrfPageNNNReference in RelFlags then
  205. Inc(FlagsWord,64);
  206. if rrfMSBWith2ByteMode in RelFlags then
  207. Inc(FlagsWord,128);
  208. if rrfThreeByteObjectFormatForByteData in RelFlags then
  209. Inc(FlagsWord,256);
  210. if rrfRealMSBForThreeByteMode in RelFlags then
  211. Inc(FlagsWord,512);
  212. if rrfReserved10 in RelFlags then
  213. Inc(FlagsWord,1024);
  214. if rrfReserved11 in RelFlags then
  215. Inc(FlagsWord,2048);
  216. if (FlagsWord<=255) and ((FlagsWord and $F0)<>$F0) then
  217. Result:=HexStr(FlagsWord,2)
  218. else
  219. Result:=HexStr($F0 or Byte(FlagsWord shr 8),2)+' '+HexStr(Byte(FlagsWord),2);
  220. end;
  221. {*****************************************************************************
  222. TRelObjData
  223. *****************************************************************************}
  224. function TRelObjData.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
  225. const
  226. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  227. '_CODE',
  228. '_DATA',
  229. '_DATA',
  230. '_DATA',
  231. '_BSS',
  232. '.threadvar',
  233. '.pdata',
  234. '', { stubs }
  235. '__DATA,__nl_symbol_ptr',
  236. '__DATA,__la_symbol_ptr',
  237. '__DATA,__mod_init_func',
  238. '__DATA,__mod_term_func',
  239. '.stab',
  240. '.stabstr',
  241. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  242. '.eh_frame',
  243. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges','.debug_loc','.debug_loclists',
  244. '.fpc',
  245. '.toc',
  246. '.init',
  247. '.fini',
  248. '.objc_class',
  249. '.objc_meta_class',
  250. '.objc_cat_cls_meth',
  251. '.objc_cat_inst_meth',
  252. '.objc_protocol',
  253. '.objc_string_object',
  254. '.objc_cls_meth',
  255. '.objc_inst_meth',
  256. '.objc_cls_refs',
  257. '.objc_message_refs',
  258. '.objc_symbols',
  259. '.objc_category',
  260. '.objc_class_vars',
  261. '.objc_instance_vars',
  262. '.objc_module_info',
  263. '.objc_class_names',
  264. '.objc_meth_var_types',
  265. '.objc_meth_var_names',
  266. '.objc_selector_strs',
  267. '.objc_protocol_ext',
  268. '.objc_class_ext',
  269. '.objc_property',
  270. '.objc_image_info',
  271. '.objc_cstring_object',
  272. '.objc_sel_fixup',
  273. '__DATA,__objc_data',
  274. '__DATA,__objc_const',
  275. '.objc_superrefs',
  276. '__DATA, __datacoal_nt,coalesced',
  277. '.objc_classlist',
  278. '.objc_nlclasslist',
  279. '.objc_catlist',
  280. '.obcj_nlcatlist',
  281. '.objc_protolist',
  282. '_STACK',
  283. '_HEAP',
  284. '.gcc_except_table',
  285. '.ARM.attributes'
  286. );
  287. begin
  288. if atype=sec_user then
  289. result:=aname
  290. else
  291. result:=secnames[atype];
  292. end;
  293. function TRelObjData.sectiontype2align(atype:TAsmSectiontype):longint;
  294. begin
  295. result:=1;
  296. end;
  297. procedure TRelObjData.writeReloc(Data: TRelocDataInt; len: aword; p: TObjSymbol; Reloctype: TObjRelocationType);
  298. var
  299. bytes: array [0..7] of Byte;
  300. symaddr: QWord;
  301. objreloc: TRelRelocation;
  302. begin
  303. if CurrObjSec=nil then
  304. internalerror(200403072);
  305. objreloc:=nil;
  306. if assigned(p) then
  307. begin
  308. { real address of the symbol }
  309. symaddr:=p.address;
  310. if p.bind=AB_EXTERNAL then
  311. begin
  312. objreloc:=TRelRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  313. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  314. objreloc.HiByte:=Byte(Data shr 8);
  315. CurrObjSec.ObjRelocations.Add(objreloc);
  316. end
  317. { relative relocations within the same section can be calculated directly,
  318. without the need to emit a relocation entry }
  319. else if (p.objsection=CurrObjSec) and
  320. (p.bind<>AB_COMMON) and
  321. (Reloctype=RELOC_RELATIVE) then
  322. {$push} {$R-}{$Q-}
  323. begin
  324. data:=data+symaddr-len-CurrObjSec.Size;
  325. end
  326. {$pop}
  327. else
  328. begin
  329. objreloc:=TRelRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  330. inc(data,symaddr);
  331. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  332. objreloc.HiByte:=Byte(Data shr 8);
  333. CurrObjSec.ObjRelocations.Add(objreloc);
  334. end;
  335. end;
  336. case len of
  337. 8:
  338. begin
  339. bytes[0]:=Byte(Data);
  340. bytes[1]:=Byte(Data shr 8);
  341. bytes[2]:=Byte(Data shr 16);
  342. bytes[3]:=Byte(Data shr 24);
  343. bytes[4]:=0;
  344. bytes[5]:=0;
  345. bytes[6]:=0;
  346. bytes[7]:=0;
  347. writebytes(bytes,8);
  348. end;
  349. 4:
  350. begin
  351. bytes[0]:=Byte(Data);
  352. bytes[1]:=Byte(Data shr 8);
  353. bytes[2]:=Byte(Data shr 16);
  354. bytes[3]:=Byte(Data shr 24);
  355. writebytes(bytes,4);
  356. end;
  357. 2:
  358. begin
  359. bytes[0]:=Byte(Data);
  360. bytes[1]:=Byte(Data shr 8);
  361. writebytes(bytes,2);
  362. end;
  363. 1:
  364. begin
  365. bytes[0]:=Byte(Data);
  366. writebytes(bytes,1);
  367. end;
  368. else
  369. internalerror(2020050423);
  370. end;
  371. end;
  372. {*****************************************************************************
  373. TRelObjOutput
  374. *****************************************************************************}
  375. procedure TRelObjOutput.writeString(const S: ansistring);
  376. begin
  377. FWriter.write(S[1],Length(S));
  378. end;
  379. procedure TRelObjOutput.writeLine(const S: ansistring);
  380. begin
  381. writeString(S+#10)
  382. end;
  383. procedure TRelObjOutput.WriteAreaContentAndRelocations(sec: TObjSection);
  384. const
  385. MaxChunkSize={14}7;
  386. var
  387. ChunkStart,ChunkLen, i: LongWord;
  388. ChunkFixupStart,ChunkFixupEnd, j, st_ofs: Integer;
  389. st,sr: ansistring;
  390. buf: array [0..MaxChunkSize-1] of Byte;
  391. reloc: TRelRelocation;
  392. begin
  393. if (oso_data in sec.SecOptions) and (sec.Data=nil) then
  394. internalerror(200403073);
  395. if assigned(sec.data) then
  396. sec.data.seek(0);
  397. ChunkFixupStart:=0;
  398. ChunkFixupEnd:=-1;
  399. ChunkStart:=0;
  400. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  401. while ChunkLen>0 do
  402. begin
  403. { find last fixup in the chunk }
  404. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  405. (TRelRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  406. inc(ChunkFixupEnd);
  407. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  408. if (ChunkFixupEnd>=ChunkFixupStart) and
  409. ((TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  410. TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).size)>(ChunkStart+ChunkLen)) then
  411. begin
  412. ChunkLen:=TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  413. Dec(ChunkFixupEnd);
  414. end;
  415. if ChunkLen>SizeOf(buf) then
  416. internalerror(2020050501);
  417. st:='T '+HexStr(Byte(ChunkStart),2)+' '+HexStr(Byte(ChunkStart shr 8),2);
  418. sr:='R 00 00 '+HexStr(Byte(sec.SecSymIdx),2)+' '+HexStr(Byte(sec.SecSymIdx shr 8),2);
  419. if assigned(sec.Data) then
  420. sec.Data.read(buf,ChunkLen)
  421. else
  422. FillChar(buf,ChunkLen,0);
  423. st_ofs:=1;
  424. { relocations present in the current chunk? }
  425. if ChunkFixupEnd>=ChunkFixupStart then
  426. begin
  427. j:=ChunkFixupStart;
  428. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  429. end
  430. else
  431. begin
  432. j:=-1;
  433. reloc:=nil;
  434. end;
  435. for i:=0 to ChunkLen-1 do
  436. begin
  437. st:=st+' '+HexStr(buf[i],2);
  438. Inc(st_ofs);
  439. if assigned(reloc) then
  440. begin
  441. { advance to the current relocation }
  442. while (reloc.DataOffset<(ChunkStart+i)) and (j<ChunkFixupEnd) do
  443. begin
  444. Inc(j);
  445. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  446. end;
  447. { is there a relocation at the current position? }
  448. if reloc.DataOffset=(ChunkStart+i) then
  449. begin
  450. sr:=sr+' '+reloc.EncodeFlags+' '+HexStr(st_ofs,2)+' '+HexStr(Byte(reloc.SecOrSymIdx),2)+' '+HexStr(Byte(reloc.SecOrSymIdx shr 8),2);
  451. if reloc.typ in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  452. begin
  453. st:=st+' '+HexStr(reloc.HiByte,2);
  454. Inc(st_ofs);
  455. end;
  456. end;
  457. end;
  458. end;
  459. writeLine(st);
  460. writeLine(sr);
  461. { prepare next chunk }
  462. Inc(ChunkStart, ChunkLen);
  463. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  464. ChunkFixupStart:=ChunkFixupEnd+1;
  465. end;
  466. end;
  467. function TRelObjOutput.writeData(Data: TObjData): boolean;
  468. var
  469. global_symbols_count: Integer = 0;
  470. secidx, idx, i, j: Integer;
  471. objsym: TObjSymbol;
  472. objsec: TObjSection;
  473. begin
  474. global_symbols_count:=0;
  475. for i:=0 to Data.ObjSymbolList.Count-1 do
  476. begin
  477. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  478. if objsym.bind in [AB_EXTERNAL,AB_GLOBAL] then
  479. Inc(global_symbols_count);
  480. end;
  481. writeLine('XL2');
  482. writeLine('H '+tohex(data.ObjSectionList.Count)+' areas '+tohex(global_symbols_count)+' global symbols');
  483. idx:=0;
  484. for i:=0 to Data.ObjSymbolList.Count-1 do
  485. begin
  486. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  487. if objsym.bind=AB_EXTERNAL then
  488. begin
  489. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Ref0000');
  490. objsym.symidx:=idx;
  491. Inc(idx);
  492. end;
  493. end;
  494. secidx:=0;
  495. for i:=0 to Data.ObjSectionList.Count-1 do
  496. begin
  497. objsec:=TObjSection(Data.ObjSectionList[i]);
  498. writeLine('A '+objsec.Name+' size '+tohex(objsec.Size)+' flags 0 addr 0');
  499. objsec.SecSymIdx:=secidx;
  500. Inc(secidx);
  501. for j:=0 to Data.ObjSymbolList.Count-1 do
  502. begin
  503. objsym:=TObjSymbol(Data.ObjSymbolList[j]);
  504. if (objsym.bind=AB_GLOBAL) and (objsym.objsection=objsec) then
  505. begin
  506. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Def'+HexStr(objsym.offset,4));
  507. objsym.symidx:=idx;
  508. Inc(idx);
  509. end;
  510. end;
  511. end;
  512. for i:=0 to Data.ObjSectionList.Count-1 do
  513. begin
  514. objsec:=TObjSection(Data.ObjSectionList[i]);
  515. WriteAreaContentAndRelocations(objsec);
  516. end;
  517. result:=true;
  518. end;
  519. constructor TRelObjOutput.create(AWriter: TObjectWriter);
  520. begin
  521. inherited;
  522. cobjdata:=TRelObjData;
  523. end;
  524. {*****************************************************************************
  525. TRelAssembler
  526. *****************************************************************************}
  527. constructor TRelAssembler.create(info: pasminfo; smart: boolean);
  528. begin
  529. inherited;
  530. CObjOutput:=TRelObjOutput;
  531. CInternalAr:=tarobjectwriter;
  532. end;
  533. {*****************************************************************************
  534. TRelObjInput
  535. *****************************************************************************}
  536. function TRelObjInput.FillBuf: boolean;
  537. begin
  538. FBufPos:=0;
  539. FBufSize:=min(FReader.size-FReader.Pos,MaxBufSize);
  540. if FBufSize>0 then
  541. result:=FReader.read(FBuf,FBufSize)
  542. else
  543. result:=true;
  544. end;
  545. function TRelObjInput.AtEndOfBuf: boolean;
  546. begin
  547. result:=FBufPos=FBufSize;
  548. end;
  549. function TRelObjInput.AtEoF: boolean;
  550. begin
  551. result:=AtEndOfBuf and (FReader.Pos=FReader.size);
  552. end;
  553. function TRelObjInput.ReadChar(out c: char): boolean;
  554. begin
  555. c:=#0;
  556. if AtEndOfBuf then
  557. begin
  558. result:=FillBuf;
  559. if not result then
  560. exit;
  561. end;
  562. if not AtEndOfBuf then
  563. begin
  564. c:=FBuf[FBufPos];
  565. Inc(FBufPos);
  566. result:=true;
  567. end
  568. else
  569. result:=false;
  570. end;
  571. function TRelObjInput.PeekChar(out c: char): boolean;
  572. begin
  573. c:=#0;
  574. if AtEndOfBuf then
  575. begin
  576. result:=FillBuf;
  577. if not result then
  578. exit;
  579. end;
  580. if not AtEndOfBuf then
  581. begin
  582. c:=FBuf[FBufPos];
  583. result:=true;
  584. end
  585. else
  586. result:=false;
  587. end;
  588. function TRelObjInput.ReadLine(out s: string): boolean;
  589. var
  590. c: Char;
  591. begin
  592. s:='';
  593. c:=#0;
  594. if AtEoF then
  595. begin
  596. result:=false;
  597. exit;
  598. end;
  599. repeat
  600. if not AtEoF then
  601. begin
  602. if not ReadChar(c) then
  603. begin
  604. result:=false;
  605. exit;
  606. end;
  607. if not (c in [#13,#10]) then
  608. s:=s+c;
  609. end;
  610. until (c in [#13,#10]) or AtEoF;
  611. if (c=#13) and not AtEoF then
  612. begin
  613. if not PeekChar(c) then
  614. begin
  615. result:=false;
  616. exit;
  617. end;
  618. if c=#10 then
  619. begin
  620. if not ReadChar(c) then
  621. begin
  622. result:=false;
  623. exit;
  624. end;
  625. end;
  626. end;
  627. result:=true;
  628. end;
  629. constructor TRelObjInput.create;
  630. begin
  631. inherited create;
  632. cobjdata:=TRelObjData;
  633. FBufSize:=0;
  634. FBufPos:=0;
  635. end;
  636. function TRelObjInput.ReadObjData(AReader: TObjectreader; out Data: TObjData): boolean;
  637. function DecodeRelFlags(n1: Word): TRelRelocationFlags;
  638. begin
  639. result:=[];
  640. if (n1 and (1 shl 0))<>0 then
  641. include(result,rrfByte);
  642. if (n1 and (1 shl 1))<>0 then
  643. include(result,rrfSymbol);
  644. if (n1 and (1 shl 2))<>0 then
  645. include(result,rrfPcRelative);
  646. if (n1 and (1 shl 3))<>0 then
  647. include(result,rrfTwoByteObjectFormatForByteData);
  648. if (n1 and (1 shl 4))<>0 then
  649. include(result,rrfUnsignedByteData);
  650. if (n1 and (1 shl 5))<>0 then
  651. include(result,rrfPage0Reference);
  652. if (n1 and (1 shl 6))<>0 then
  653. include(result,rrfPageNNNReference);
  654. if (n1 and (1 shl 7))<>0 then
  655. include(result,rrfMSBWith2ByteMode);
  656. if (n1 and (1 shl 8))<>0 then
  657. include(result,rrfThreeByteObjectFormatForByteData);
  658. if (n1 and (1 shl 9))<>0 then
  659. include(result,rrfRealMSBForThreeByteMode);
  660. if (n1 and (1 shl 10))<>0 then
  661. include(result,rrfReserved10);
  662. if (n1 and (1 shl 11))<>0 then
  663. include(result,rrfReserved11);
  664. end;
  665. function HandleTR(const T,R: string): boolean;
  666. const
  667. GenericTErrMsg='Invalid T record';
  668. GenericRErrMsg='Invalid R record';
  669. UnsupportedRelocationFlags=[rrfPcRelative,rrfUnsignedByteData,
  670. rrfPage0Reference,rrfPageNNNReference,rrfThreeByteObjectFormatForByteData,
  671. rrfRealMSBForThreeByteMode,rrfReserved10,rrfReserved11];
  672. var
  673. ArrT, ArrR: array of byte;
  674. ArrTIsRelocHiByte: array of boolean;
  675. tmpint: Longint;
  676. i: Integer;
  677. AreaIndex, AreaOffset: Word;
  678. LastDataOfsIndex: Integer;
  679. LastDataOfsValue: TObjSectionOfs;
  680. ObjSec: TObjSection;
  681. n1, xx_xx: Word;
  682. n1x, n2, RelHiByte: Byte;
  683. RelFlags: TRelRelocationFlags;
  684. reloc:TRelRelocation;
  685. RelocDataOffset: TObjSectionOfs;
  686. RelocTyp: TObjRelocationType;
  687. zeros_only: Boolean;
  688. begin
  689. result:=false;
  690. if (length(T)<5) or (((length(T)-2) mod 3)<>0) then
  691. begin
  692. InputError(GenericTErrMsg);
  693. exit;
  694. end;
  695. if (length(R)<11) or (((length(R)-2) mod 3)<>0) then
  696. begin
  697. InputError(GenericRErrMsg);
  698. exit;
  699. end;
  700. SetLength(ArrT,((length(T)-2) div 3)+1);
  701. for i:=0 to length(ArrT)-1 do
  702. begin
  703. if (i>0) and (T[i*3]<>' ') then
  704. begin
  705. InputError(GenericTErrMsg);
  706. exit;
  707. end;
  708. if not TryStrToInt('$'+copy(T,1+i*3,2),tmpint) then
  709. begin
  710. InputError(GenericTErrMsg);
  711. exit;
  712. end;
  713. if (tmpint<0) or (tmpint>255) then
  714. begin
  715. InputError(GenericTErrMsg);
  716. exit;
  717. end;
  718. ArrT[i]:=tmpint;
  719. end;
  720. SetLength(ArrR,((length(R)-2) div 3)+1);
  721. for i:=0 to length(ArrR)-1 do
  722. begin
  723. if (i>0) and (R[i*3]<>' ') then
  724. begin
  725. InputError(GenericRErrMsg);
  726. exit;
  727. end;
  728. if not TryStrToInt('$'+copy(R,1+i*3,2),tmpint) then
  729. begin
  730. InputError(GenericRErrMsg);
  731. exit;
  732. end;
  733. if (tmpint<0) or (tmpint>255) then
  734. begin
  735. InputError(GenericRErrMsg);
  736. exit;
  737. end;
  738. ArrR[i]:=tmpint;
  739. end;
  740. if (length(ArrT)<2) or (length(ArrR)<4) then
  741. internalerror(2020060201);
  742. if (ArrR[0]<>0) or (ArrR[1]<>0) then
  743. begin
  744. InputError(GenericRErrMsg);
  745. exit;
  746. end;
  747. AreaIndex:=(ArrR[3] shl 8) or ArrR[2];
  748. AreaOffset:=(ArrT[1] shl 8) or ArrT[0];
  749. if AreaIndex>=Data.ObjSectionList.Count then
  750. begin
  751. InputError('Area index in R record out of bounds');
  752. exit;
  753. end;
  754. ObjSec:=TObjSection(Data.ObjSectionList[AreaIndex]);
  755. if AreaOffset>ObjSec.Size then
  756. begin
  757. InputError('Area offset in T exceeds area size');
  758. exit;
  759. end;
  760. { section name is '_BSS'/'_STACK'/'_HEAP' and there are no relocations }
  761. if ((ObjSec.Name='_BSS') or (ObjSec.Name='_STACK') or (ObjSec.Name='_HEAP')) and
  762. (length(ArrR)=4) then
  763. begin
  764. zeros_only:=true;
  765. for i:=2 to length(ArrT)-1 do
  766. if ArrT[i]<>0 then
  767. begin
  768. zeros_only:=false;
  769. break;
  770. end;
  771. { avoid setting the oso_Data flag on .bss sections, if there are no relocations and all data is zero }
  772. if zeros_only then
  773. exit;
  774. end;
  775. { parse relocations }
  776. SetLength(ArrTIsRelocHiByte,Length(ArrT));
  777. LastDataOfsIndex:=2;
  778. LastDataOfsValue:=AreaOffset;
  779. i:=4;
  780. while i<length(ArrR) do
  781. begin
  782. n1:=ArrR[i];
  783. Inc(i);
  784. if (n1 and $F0)=$F0 then
  785. begin
  786. if i>=length(ArrR) then
  787. begin
  788. InputError(GenericRErrMsg);
  789. exit;
  790. end;
  791. n1x:=ArrR[i];
  792. Inc(i);
  793. n1:=((n1 and $0F) shl 8) or n1x;
  794. end;
  795. if (i+2)>=length(ArrR) then
  796. begin
  797. InputError(GenericRErrMsg);
  798. exit;
  799. end;
  800. n2:=ArrR[i];
  801. xx_xx:=ArrR[i+1] or (ArrR[i+2] shl 8);
  802. Inc(i,3);
  803. RelFlags:=DecodeRelFlags(n1);
  804. if ((RelFlags*UnsupportedRelocationFlags)<>[]) or
  805. ((rrfByte in RelFlags) xor (rrfTwoByteObjectFormatForByteData in RelFlags)) then
  806. begin
  807. InputError('Unsupported relocation flags ($'+HexStr(n1,3)+')');
  808. exit;
  809. end;
  810. if n2<=1 then
  811. begin
  812. InputError('Invalid relocation data offset');
  813. exit;
  814. end;
  815. if rrfByte in RelFlags then
  816. begin
  817. if rrfMSBWith2ByteMode in RelFlags then
  818. RelocTyp:=RELOC_ABSOLUTE_HI8
  819. else
  820. RelocTyp:=RELOC_ABSOLUTE_LO8;
  821. if (n2+1)>=length(ArrT) then
  822. begin
  823. InputError('Invalid relocation data offset');
  824. exit;
  825. end;
  826. ArrTIsRelocHiByte[n2+1]:=true;
  827. RelHiByte:=ArrT[n2+1];
  828. end
  829. else
  830. begin
  831. RelocTyp:=RELOC_ABSOLUTE;
  832. if n2>=length(ArrT) then
  833. begin
  834. InputError('Invalid relocation data offset');
  835. exit;
  836. end;
  837. RelHiByte:=0;
  838. end;
  839. while LastDataOfsIndex<n2 do
  840. begin
  841. if not ArrTIsRelocHiByte[LastDataOfsIndex] then
  842. Inc(LastDataOfsValue);
  843. Inc(LastDataOfsIndex);
  844. end;
  845. RelocDataOffset:=LastDataOfsValue;
  846. if rrfSymbol in RelFlags then
  847. begin
  848. if xx_xx>=Data.ObjSymbolList.Count then
  849. begin
  850. InputError('Relocation to symbol with invalid index');
  851. exit;
  852. end;
  853. reloc:=TRelRelocation.CreateSymbol(RelocDataOffset,TObjSymbol(Data.ObjSymbolList[xx_xx]),RelocTyp);
  854. end
  855. else
  856. begin
  857. if xx_xx>=Data.ObjSectionlist.Count then
  858. begin
  859. InputError('Relocation to area with invalid index');
  860. exit;
  861. end;
  862. reloc:=TRelRelocation.CreateSection(RelocDataOffset,TObjSection(Data.ObjSectionlist[xx_xx]),RelocTyp);
  863. end;
  864. reloc.RelFlags:=RelFlags;
  865. reloc.HiByte:=RelHiByte;
  866. objsec.ObjRelocations.Add(reloc);
  867. end;
  868. { read the data }
  869. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  870. objsec.Data.seek(AreaOffset);
  871. for i:=2 to length(ArrT)-1 do
  872. if not ArrTIsRelocHiByte[i] then
  873. objsec.Data.write(ArrT[i],1);
  874. result:=true;
  875. end;
  876. const
  877. GenericRelErrMsg='Error reading REL file';
  878. var
  879. s, AreaName, SymbolName: string;
  880. RecType: Char;
  881. HeaderFound: Boolean=false;
  882. ExpectedAreas,ExpectedSymbols,AreaSize,AreaFlags,AreaAddr,
  883. SymbolOfs: LongInt;
  884. tmpint: SizeInt;
  885. CurrSec: TObjSection=nil;
  886. objsym: TObjSymbol;
  887. LastT: string='';
  888. begin
  889. FReader:=AReader;
  890. InputFileName:=AReader.FileName;
  891. Data:=CObjData.Create(InputFileName);
  892. ExpectedAreas:=-1;
  893. ExpectedSymbols:=-1;
  894. result:=false;
  895. s:='';
  896. repeat
  897. if AtEoF or not ReadLine(s) then
  898. begin
  899. InputError(GenericRelErrMsg);
  900. exit;
  901. end;
  902. s:=Trim(s);
  903. until s<>'';
  904. if s<>'XL2' then
  905. begin
  906. InputError('Invalid or unsupported REL format identifier');
  907. exit;
  908. end;
  909. while not AtEoF do
  910. begin
  911. if not ReadLine(s) then
  912. begin
  913. InputError(GenericRelErrMsg);
  914. exit;
  915. end;
  916. s:=Trim(s);
  917. if s<>'' then
  918. begin
  919. RecType:=s[1];
  920. if (length(s)<3) or (s[2]<>' ') then
  921. begin
  922. InputError('Invalid or unsupported REL record');
  923. exit;
  924. end;
  925. delete(s,1,2);
  926. case RecType of
  927. 'H': { header }
  928. begin
  929. if HeaderFound then
  930. begin
  931. InputError('Duplicated header');
  932. exit;
  933. end;
  934. HeaderFound:=true;
  935. tmpint:=Pos(' ',s);
  936. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedAreas) then
  937. begin
  938. InputError('Invalid area count in header');
  939. exit;
  940. end;
  941. delete(s,1,tmpint);
  942. if copy(s,1,6)<>'areas ' then
  943. begin
  944. InputError('Invalid header');
  945. exit;
  946. end;
  947. delete(s,1,6);
  948. tmpint:=Pos(' ',s);
  949. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedSymbols) then
  950. begin
  951. InputError('Invalid symbol count in header');
  952. exit;
  953. end;
  954. delete(s,1,tmpint);
  955. if s<>'global symbols' then
  956. begin
  957. InputError('Invalid header');
  958. exit;
  959. end;
  960. end;
  961. 'M': { module }
  962. begin
  963. { we ignore this for now }
  964. end;
  965. 'S': { symbol }
  966. begin
  967. if not HeaderFound then
  968. begin
  969. InputError('Symbol record encountered before header');
  970. exit;
  971. end;
  972. tmpint:=Pos(' ',s);
  973. if tmpint<=1 then
  974. begin
  975. InputError('Invalid symbol record');
  976. exit;
  977. end;
  978. SymbolName:=copy(s,1,tmpint-1);
  979. delete(s,1,tmpint);
  980. if Length(s)<4 then
  981. begin
  982. InputError('Invalid symbol record');
  983. exit;
  984. end;
  985. if not TryStrToInt('$'+Copy(s,4,Length(s)-3),SymbolOfs) then
  986. begin
  987. InputError('Invalid symbol offset');
  988. exit;
  989. end;
  990. case Copy(s,1,3) of
  991. 'Def':
  992. begin
  993. if CurrSec=nil then
  994. begin
  995. InputError('Public symbol defined outside any area');
  996. exit;
  997. end;
  998. if (SymbolOfs<0) or (SymbolOfs>CurrSec.Size) then
  999. begin
  1000. InputError('Public symbol offset outside the range of the current area');
  1001. exit;
  1002. end;
  1003. objsym:=Data.CreateSymbol(SymbolName);
  1004. objsym.bind:=AB_GLOBAL;
  1005. objsym.typ:=AT_FUNCTION;
  1006. objsym.objsection:=CurrSec;
  1007. objsym.offset:=SymbolOfs;
  1008. objsym.size:=0;
  1009. end;
  1010. 'Ref':
  1011. begin
  1012. if CurrSec<>nil then
  1013. begin
  1014. InputError('External symbols must be defined before the first area');
  1015. exit;
  1016. end;
  1017. if SymbolOfs<>0 then
  1018. begin
  1019. InputError('External symbols must be declared with an offset of 0');
  1020. exit;
  1021. end;
  1022. objsym:=Data.CreateSymbol(SymbolName);
  1023. objsym.bind:=AB_EXTERNAL;
  1024. objsym.typ:=AT_FUNCTION;
  1025. objsym.objsection:=nil;
  1026. objsym.offset:=0;
  1027. objsym.size:=0;
  1028. end;
  1029. else
  1030. begin
  1031. InputError('Invalid or unsupported symbol record');
  1032. exit;
  1033. end;
  1034. end;
  1035. if Data.ObjSymbolList.Count>ExpectedSymbols then
  1036. begin
  1037. InputError('Number of symbols exceeds the number, declared in header');
  1038. exit;
  1039. end;
  1040. end;
  1041. 'A': { area }
  1042. begin
  1043. if not HeaderFound then
  1044. begin
  1045. InputError('Area record encountered before header');
  1046. exit;
  1047. end;
  1048. tmpint:=Pos(' ',s);
  1049. if tmpint<=1 then
  1050. begin
  1051. InputError('Invalid area record');
  1052. exit;
  1053. end;
  1054. AreaName:=copy(s,1,tmpint-1);
  1055. delete(s,1,tmpint);
  1056. if copy(s,1,5)<>'size ' then
  1057. begin
  1058. InputError('Invalid area record');
  1059. exit;
  1060. end;
  1061. delete(s,1,5);
  1062. tmpint:=Pos(' ',s);
  1063. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaSize) then
  1064. begin
  1065. InputError('Invalid area size');
  1066. exit;
  1067. end;
  1068. delete(s,1,tmpint);
  1069. if copy(s,1,6)<>'flags ' then
  1070. begin
  1071. InputError('Invalid area record');
  1072. exit;
  1073. end;
  1074. delete(s,1,6);
  1075. tmpint:=Pos(' ',s);
  1076. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaFlags) then
  1077. begin
  1078. InputError('Invalid area flags');
  1079. exit;
  1080. end;
  1081. delete(s,1,tmpint);
  1082. if copy(s,1,5)<>'addr ' then
  1083. begin
  1084. InputError('Invalid area record');
  1085. exit;
  1086. end;
  1087. delete(s,1,5);
  1088. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaAddr) then
  1089. begin
  1090. InputError('Invalid area address');
  1091. exit;
  1092. end;
  1093. if AreaFlags<>0 then
  1094. begin
  1095. InputError('Unsupported area flags ('+tostr(AreaFlags)+')');
  1096. exit;
  1097. end;
  1098. if AreaAddr<>0 then
  1099. begin
  1100. InputError('Area address<>0 not supported');
  1101. exit;
  1102. end;
  1103. CurrSec:=Data.createsection(AreaName,1,[],false);
  1104. CurrSec.alloc(AreaSize);
  1105. if Data.ObjSectionList.Count>ExpectedAreas then
  1106. begin
  1107. InputError('Number of areas exceeds the number, declared in header');
  1108. exit;
  1109. end;
  1110. end;
  1111. 'T': { T line () }
  1112. begin
  1113. if LastT<>'' then
  1114. begin
  1115. InputError('T record not followed by R record');
  1116. exit;
  1117. end;
  1118. LastT:=s;
  1119. end;
  1120. 'R': { R line (relocation information) }
  1121. begin
  1122. if LastT='' then
  1123. begin
  1124. InputError('R record without T record');
  1125. exit;
  1126. end;
  1127. if not HandleTR(LastT,s) then
  1128. exit;
  1129. LastT:='';
  1130. end;
  1131. 'P': { P line (paging information) }
  1132. begin
  1133. InputError('P line records are not supported');
  1134. exit;
  1135. end;
  1136. else
  1137. begin
  1138. InputError('Unsupported REL record type: #'+tostr(Ord(RecType)));
  1139. exit;
  1140. end;
  1141. end;
  1142. end;
  1143. end;
  1144. result:=true;
  1145. end;
  1146. class function TRelObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  1147. var
  1148. s: string;
  1149. instance: TRelObjInput;
  1150. begin
  1151. result:=false;
  1152. instance:=TRelObjInput.Create;
  1153. instance.FReader:=AReader;
  1154. with instance do
  1155. while not AtEoF do
  1156. begin
  1157. if not ReadLine(s) then
  1158. exit;
  1159. s:=Trim(s);
  1160. if s<>'' then
  1161. begin
  1162. result:=s='XL2';
  1163. break;
  1164. end;
  1165. end;
  1166. instance.Free;
  1167. end;
  1168. {*****************************************************************************
  1169. TIntelHexExeOutput
  1170. *****************************************************************************}
  1171. procedure TIntelHexExeOutput.writeString(const S: ansistring);
  1172. begin
  1173. FWriter.write(S[1],Length(S));
  1174. end;
  1175. procedure TIntelHexExeOutput.writeLine(const S: ansistring);
  1176. begin
  1177. writeString(S+#10)
  1178. end;
  1179. function TIntelHexExeOutput.writeData: boolean;
  1180. const
  1181. MaxRecLen=16;
  1182. var
  1183. exesec: TExeSection;
  1184. objsec: TObjSection;
  1185. exesec_i, objsec_i: Integer;
  1186. s: string;
  1187. blocklen, i: integer;
  1188. buf: array [0..MaxRecLen-1] of Byte;
  1189. blockaddr: Word;
  1190. checksum: Byte;
  1191. begin
  1192. result:=false;
  1193. for exesec_i:=0 to ExeSectionList.Count-1 do
  1194. begin
  1195. exesec:=TExeSection(ExeSectionList[exesec_i]);
  1196. for objsec_i:=0 to exesec.ObjSectionList.Count-1 do
  1197. begin
  1198. objsec:=TObjSection(exesec.ObjSectionList[objsec_i]);
  1199. if oso_Data in objsec.SecOptions then
  1200. begin
  1201. objsec.Data.seek(0);
  1202. while objsec.Data.Pos<objsec.Data.size do
  1203. begin
  1204. blocklen:=Min(objsec.Data.size-objsec.Data.Pos,MaxRecLen);
  1205. blockaddr:=objsec.Data.Pos+objsec.MemPos+ImageBase;
  1206. s:=':'+HexStr(blocklen,2)+HexStr(blockaddr,4)+'00';
  1207. checksum:=Byte(blocklen)+Byte(blockaddr shr 8)+Byte(blockaddr)+0;
  1208. if objsec.Data.read(buf,blocklen)<>blocklen then
  1209. internalerror(2020060301);
  1210. for i:=0 to blocklen-1 do
  1211. begin
  1212. s:=s+HexStr(buf[i],2);
  1213. checksum:=Byte(checksum+buf[i]);
  1214. end;
  1215. checksum:=$100-checksum;
  1216. s:=s+HexStr(checksum,2);
  1217. writeLine(s);
  1218. end;
  1219. end;
  1220. end;
  1221. end;
  1222. writeLine(':00000001FF');
  1223. result:=true;
  1224. end;
  1225. procedure TIntelHexExeOutput.DoRelocationFixup(objsec: TObjSection);
  1226. var
  1227. i: Integer;
  1228. objreloc: TRelRelocation;
  1229. target,w: Word;
  1230. b: Byte;
  1231. begin
  1232. for i:=0 to objsec.ObjRelocations.Count-1 do
  1233. begin
  1234. objreloc:=TRelRelocation(objsec.ObjRelocations[i]);
  1235. if assigned(objreloc.symbol) then
  1236. target:=objreloc.symbol.address+ImageBase
  1237. else if assigned(objreloc.objsection) then
  1238. target:=objreloc.objsection.MemPos+ImageBase
  1239. else
  1240. internalerror(2020060302);
  1241. case objreloc.typ of
  1242. RELOC_ABSOLUTE:
  1243. begin
  1244. objsec.Data.seek(objreloc.DataOffset);
  1245. objsec.Data.read(w,2);
  1246. w:=LEtoN(w);
  1247. Inc(w,target);
  1248. w:=LEtoN(w);
  1249. objsec.Data.seek(objreloc.DataOffset);
  1250. objsec.Data.write(w,2);
  1251. end;
  1252. RELOC_ABSOLUTE_HI8:
  1253. begin
  1254. objsec.Data.seek(objreloc.DataOffset);
  1255. objsec.Data.read(b,1);
  1256. w:=b or (objreloc.HiByte shl 8);
  1257. Inc(w,target);
  1258. b:=Byte(w shr 8);
  1259. objsec.Data.seek(objreloc.DataOffset);
  1260. objsec.Data.write(b,1);
  1261. end;
  1262. RELOC_ABSOLUTE_LO8:
  1263. begin
  1264. objsec.Data.seek(objreloc.DataOffset);
  1265. objsec.Data.read(b,1);
  1266. w:=b or (objreloc.HiByte shl 8);
  1267. Inc(w,target);
  1268. b:=Byte(w);
  1269. objsec.Data.seek(objreloc.DataOffset);
  1270. objsec.Data.write(b,1);
  1271. end;
  1272. else
  1273. internalerror(2020060303);
  1274. end;
  1275. end;
  1276. end;
  1277. constructor TIntelHexExeOutput.create;
  1278. begin
  1279. inherited create;
  1280. CObjData:=TRelObjData;
  1281. MaxMemPos:=$FFFF;
  1282. end;
  1283. {*****************************************************************************
  1284. TZXSpectrumIntelHexExeOutput
  1285. *****************************************************************************}
  1286. constructor TZXSpectrumIntelHexExeOutput.create;
  1287. begin
  1288. inherited create;
  1289. { The ZX Spectrum RTL switches to interrupt mode 2, and install an
  1290. interrupt handler + table, starting at address $FDFD, so we must limit
  1291. program size to $FDFC }
  1292. MaxMemPos:=$FDFC;
  1293. end;
  1294. {*****************************************************************************
  1295. Initialize
  1296. *****************************************************************************}
  1297. const
  1298. as_z80_rel_info : tasminfo =
  1299. (
  1300. id : as_z80_rel;
  1301. idtxt : 'REL';
  1302. asmbin : '';
  1303. asmcmd : '';
  1304. supported_targets : [system_z80_embedded,system_z80_zxspectrum,system_z80_msxdos];
  1305. flags : [af_outputbinary,af_smartlink_sections];
  1306. labelprefix : '..@';
  1307. labelmaxlen : 79;
  1308. comment : '; ';
  1309. dollarsign: '$';
  1310. );
  1311. initialization
  1312. RegisterAssembler(as_z80_rel_info,TRelAssembler);
  1313. end.