ogrel.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391
  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. '.note'
  287. );
  288. begin
  289. if atype=sec_user then
  290. result:=aname
  291. else
  292. result:=secnames[atype];
  293. end;
  294. function TRelObjData.sectiontype2align(atype:TAsmSectiontype):longint;
  295. begin
  296. result:=1;
  297. end;
  298. procedure TRelObjData.writeReloc(Data: TRelocDataInt; len: aword; p: TObjSymbol; Reloctype: TObjRelocationType);
  299. var
  300. bytes: array [0..7] of Byte;
  301. symaddr: QWord;
  302. objreloc: TRelRelocation;
  303. begin
  304. if CurrObjSec=nil then
  305. internalerror(200403072);
  306. objreloc:=nil;
  307. if assigned(p) then
  308. begin
  309. { real address of the symbol }
  310. symaddr:=p.address;
  311. if p.bind=AB_EXTERNAL then
  312. begin
  313. objreloc:=TRelRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  314. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  315. objreloc.HiByte:=Byte(Data shr 8);
  316. CurrObjSec.ObjRelocations.Add(objreloc);
  317. end
  318. { relative relocations within the same section can be calculated directly,
  319. without the need to emit a relocation entry }
  320. else if (p.objsection=CurrObjSec) and
  321. (p.bind<>AB_COMMON) and
  322. (Reloctype=RELOC_RELATIVE) then
  323. {$push} {$R-}{$Q-}
  324. begin
  325. data:=data+symaddr-len-CurrObjSec.Size;
  326. end
  327. {$pop}
  328. else
  329. begin
  330. objreloc:=TRelRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  331. inc(data,symaddr);
  332. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  333. objreloc.HiByte:=Byte(Data shr 8);
  334. CurrObjSec.ObjRelocations.Add(objreloc);
  335. end;
  336. end;
  337. case len of
  338. 8:
  339. begin
  340. bytes[0]:=Byte(Data);
  341. bytes[1]:=Byte(Data shr 8);
  342. bytes[2]:=Byte(Data shr 16);
  343. bytes[3]:=Byte(Data shr 24);
  344. bytes[4]:=0;
  345. bytes[5]:=0;
  346. bytes[6]:=0;
  347. bytes[7]:=0;
  348. writebytes(bytes,8);
  349. end;
  350. 4:
  351. begin
  352. bytes[0]:=Byte(Data);
  353. bytes[1]:=Byte(Data shr 8);
  354. bytes[2]:=Byte(Data shr 16);
  355. bytes[3]:=Byte(Data shr 24);
  356. writebytes(bytes,4);
  357. end;
  358. 2:
  359. begin
  360. bytes[0]:=Byte(Data);
  361. bytes[1]:=Byte(Data shr 8);
  362. writebytes(bytes,2);
  363. end;
  364. 1:
  365. begin
  366. bytes[0]:=Byte(Data);
  367. writebytes(bytes,1);
  368. end;
  369. else
  370. internalerror(2020050423);
  371. end;
  372. end;
  373. {*****************************************************************************
  374. TRelObjOutput
  375. *****************************************************************************}
  376. procedure TRelObjOutput.writeString(const S: ansistring);
  377. begin
  378. FWriter.write(S[1],Length(S));
  379. end;
  380. procedure TRelObjOutput.writeLine(const S: ansistring);
  381. begin
  382. writeString(S+#10)
  383. end;
  384. procedure TRelObjOutput.WriteAreaContentAndRelocations(sec: TObjSection);
  385. const
  386. MaxChunkSize={14}7;
  387. var
  388. ChunkStart,ChunkLen, i: LongWord;
  389. ChunkFixupStart,ChunkFixupEnd, j, st_ofs: Integer;
  390. st,sr: ansistring;
  391. buf: array [0..MaxChunkSize-1] of Byte;
  392. reloc: TRelRelocation;
  393. begin
  394. if (oso_data in sec.SecOptions) and (sec.Data=nil) then
  395. internalerror(200403073);
  396. if assigned(sec.data) then
  397. sec.data.seek(0);
  398. ChunkFixupStart:=0;
  399. ChunkFixupEnd:=-1;
  400. ChunkStart:=0;
  401. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  402. while ChunkLen>0 do
  403. begin
  404. { find last fixup in the chunk }
  405. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  406. (TRelRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  407. inc(ChunkFixupEnd);
  408. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  409. if (ChunkFixupEnd>=ChunkFixupStart) and
  410. ((TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  411. TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).size)>(ChunkStart+ChunkLen)) then
  412. begin
  413. ChunkLen:=TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  414. Dec(ChunkFixupEnd);
  415. end;
  416. if ChunkLen>SizeOf(buf) then
  417. internalerror(2020050501);
  418. st:='T '+HexStr(Byte(ChunkStart),2)+' '+HexStr(Byte(ChunkStart shr 8),2);
  419. sr:='R 00 00 '+HexStr(Byte(sec.SecSymIdx),2)+' '+HexStr(Byte(sec.SecSymIdx shr 8),2);
  420. if assigned(sec.Data) then
  421. sec.Data.read(buf,ChunkLen)
  422. else
  423. FillChar(buf,ChunkLen,0);
  424. st_ofs:=1;
  425. { relocations present in the current chunk? }
  426. if ChunkFixupEnd>=ChunkFixupStart then
  427. begin
  428. j:=ChunkFixupStart;
  429. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  430. end
  431. else
  432. begin
  433. j:=-1;
  434. reloc:=nil;
  435. end;
  436. for i:=0 to ChunkLen-1 do
  437. begin
  438. st:=st+' '+HexStr(buf[i],2);
  439. Inc(st_ofs);
  440. if assigned(reloc) then
  441. begin
  442. { advance to the current relocation }
  443. while (reloc.DataOffset<(ChunkStart+i)) and (j<ChunkFixupEnd) do
  444. begin
  445. Inc(j);
  446. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  447. end;
  448. { is there a relocation at the current position? }
  449. if reloc.DataOffset=(ChunkStart+i) then
  450. begin
  451. sr:=sr+' '+reloc.EncodeFlags+' '+HexStr(st_ofs,2)+' '+HexStr(Byte(reloc.SecOrSymIdx),2)+' '+HexStr(Byte(reloc.SecOrSymIdx shr 8),2);
  452. if reloc.typ in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  453. begin
  454. st:=st+' '+HexStr(reloc.HiByte,2);
  455. Inc(st_ofs);
  456. end;
  457. end;
  458. end;
  459. end;
  460. writeLine(st);
  461. writeLine(sr);
  462. { prepare next chunk }
  463. Inc(ChunkStart, ChunkLen);
  464. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  465. ChunkFixupStart:=ChunkFixupEnd+1;
  466. end;
  467. end;
  468. function TRelObjOutput.writeData(Data: TObjData): boolean;
  469. var
  470. global_symbols_count: Integer = 0;
  471. secidx, idx, i, j: Integer;
  472. objsym: TObjSymbol;
  473. objsec: TObjSection;
  474. begin
  475. global_symbols_count:=0;
  476. for i:=0 to Data.ObjSymbolList.Count-1 do
  477. begin
  478. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  479. if objsym.bind in [AB_EXTERNAL,AB_GLOBAL] then
  480. Inc(global_symbols_count);
  481. end;
  482. writeLine('XL2');
  483. writeLine('H '+tohex(data.ObjSectionList.Count)+' areas '+tohex(global_symbols_count)+' global symbols');
  484. idx:=0;
  485. for i:=0 to Data.ObjSymbolList.Count-1 do
  486. begin
  487. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  488. if objsym.bind=AB_EXTERNAL then
  489. begin
  490. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Ref0000');
  491. objsym.symidx:=idx;
  492. Inc(idx);
  493. end;
  494. end;
  495. secidx:=0;
  496. for i:=0 to Data.ObjSectionList.Count-1 do
  497. begin
  498. objsec:=TObjSection(Data.ObjSectionList[i]);
  499. writeLine('A '+objsec.Name+' size '+tohex(objsec.Size)+' flags 0 addr 0');
  500. objsec.SecSymIdx:=secidx;
  501. Inc(secidx);
  502. for j:=0 to Data.ObjSymbolList.Count-1 do
  503. begin
  504. objsym:=TObjSymbol(Data.ObjSymbolList[j]);
  505. if (objsym.bind=AB_GLOBAL) and (objsym.objsection=objsec) then
  506. begin
  507. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Def'+HexStr(objsym.offset,4));
  508. objsym.symidx:=idx;
  509. Inc(idx);
  510. end;
  511. end;
  512. end;
  513. for i:=0 to Data.ObjSectionList.Count-1 do
  514. begin
  515. objsec:=TObjSection(Data.ObjSectionList[i]);
  516. WriteAreaContentAndRelocations(objsec);
  517. end;
  518. result:=true;
  519. end;
  520. constructor TRelObjOutput.create(AWriter: TObjectWriter);
  521. begin
  522. inherited;
  523. cobjdata:=TRelObjData;
  524. end;
  525. {*****************************************************************************
  526. TRelAssembler
  527. *****************************************************************************}
  528. constructor TRelAssembler.create(info: pasminfo; smart: boolean);
  529. begin
  530. inherited;
  531. CObjOutput:=TRelObjOutput;
  532. CInternalAr:=tarobjectwriter;
  533. end;
  534. {*****************************************************************************
  535. TRelObjInput
  536. *****************************************************************************}
  537. function TRelObjInput.FillBuf: boolean;
  538. begin
  539. FBufPos:=0;
  540. FBufSize:=min(FReader.size-FReader.Pos,MaxBufSize);
  541. if FBufSize>0 then
  542. result:=FReader.read(FBuf,FBufSize)
  543. else
  544. result:=true;
  545. end;
  546. function TRelObjInput.AtEndOfBuf: boolean;
  547. begin
  548. result:=FBufPos=FBufSize;
  549. end;
  550. function TRelObjInput.AtEoF: boolean;
  551. begin
  552. result:=AtEndOfBuf and (FReader.Pos=FReader.size);
  553. end;
  554. function TRelObjInput.ReadChar(out c: char): boolean;
  555. begin
  556. c:=#0;
  557. if AtEndOfBuf then
  558. begin
  559. result:=FillBuf;
  560. if not result then
  561. exit;
  562. end;
  563. if not AtEndOfBuf then
  564. begin
  565. c:=FBuf[FBufPos];
  566. Inc(FBufPos);
  567. result:=true;
  568. end
  569. else
  570. result:=false;
  571. end;
  572. function TRelObjInput.PeekChar(out c: char): boolean;
  573. begin
  574. c:=#0;
  575. if AtEndOfBuf then
  576. begin
  577. result:=FillBuf;
  578. if not result then
  579. exit;
  580. end;
  581. if not AtEndOfBuf then
  582. begin
  583. c:=FBuf[FBufPos];
  584. result:=true;
  585. end
  586. else
  587. result:=false;
  588. end;
  589. function TRelObjInput.ReadLine(out s: string): boolean;
  590. var
  591. c: Char;
  592. begin
  593. s:='';
  594. c:=#0;
  595. if AtEoF then
  596. begin
  597. result:=false;
  598. exit;
  599. end;
  600. repeat
  601. if not AtEoF then
  602. begin
  603. if not ReadChar(c) then
  604. begin
  605. result:=false;
  606. exit;
  607. end;
  608. if not (c in [#13,#10]) then
  609. s:=s+c;
  610. end;
  611. until (c in [#13,#10]) or AtEoF;
  612. if (c=#13) and not AtEoF then
  613. begin
  614. if not PeekChar(c) then
  615. begin
  616. result:=false;
  617. exit;
  618. end;
  619. if c=#10 then
  620. begin
  621. if not ReadChar(c) then
  622. begin
  623. result:=false;
  624. exit;
  625. end;
  626. end;
  627. end;
  628. result:=true;
  629. end;
  630. constructor TRelObjInput.create;
  631. begin
  632. inherited create;
  633. cobjdata:=TRelObjData;
  634. FBufSize:=0;
  635. FBufPos:=0;
  636. end;
  637. function TRelObjInput.ReadObjData(AReader: TObjectreader; out Data: TObjData): boolean;
  638. function DecodeRelFlags(n1: Word): TRelRelocationFlags;
  639. begin
  640. result:=[];
  641. if (n1 and (1 shl 0))<>0 then
  642. include(result,rrfByte);
  643. if (n1 and (1 shl 1))<>0 then
  644. include(result,rrfSymbol);
  645. if (n1 and (1 shl 2))<>0 then
  646. include(result,rrfPcRelative);
  647. if (n1 and (1 shl 3))<>0 then
  648. include(result,rrfTwoByteObjectFormatForByteData);
  649. if (n1 and (1 shl 4))<>0 then
  650. include(result,rrfUnsignedByteData);
  651. if (n1 and (1 shl 5))<>0 then
  652. include(result,rrfPage0Reference);
  653. if (n1 and (1 shl 6))<>0 then
  654. include(result,rrfPageNNNReference);
  655. if (n1 and (1 shl 7))<>0 then
  656. include(result,rrfMSBWith2ByteMode);
  657. if (n1 and (1 shl 8))<>0 then
  658. include(result,rrfThreeByteObjectFormatForByteData);
  659. if (n1 and (1 shl 9))<>0 then
  660. include(result,rrfRealMSBForThreeByteMode);
  661. if (n1 and (1 shl 10))<>0 then
  662. include(result,rrfReserved10);
  663. if (n1 and (1 shl 11))<>0 then
  664. include(result,rrfReserved11);
  665. end;
  666. function HandleTR(const T,R: string): boolean;
  667. const
  668. GenericTErrMsg='Invalid T record';
  669. GenericRErrMsg='Invalid R record';
  670. UnsupportedRelocationFlags=[rrfPcRelative,rrfUnsignedByteData,
  671. rrfPage0Reference,rrfPageNNNReference,rrfThreeByteObjectFormatForByteData,
  672. rrfRealMSBForThreeByteMode,rrfReserved10,rrfReserved11];
  673. var
  674. ArrT, ArrR: array of byte;
  675. ArrTIsRelocHiByte: array of boolean;
  676. tmpint: Longint;
  677. i: Integer;
  678. AreaIndex, AreaOffset: Word;
  679. LastDataOfsIndex: Integer;
  680. LastDataOfsValue: TObjSectionOfs;
  681. ObjSec: TObjSection;
  682. n1, xx_xx: Word;
  683. n1x, n2, RelHiByte: Byte;
  684. RelFlags: TRelRelocationFlags;
  685. reloc:TRelRelocation;
  686. RelocDataOffset: TObjSectionOfs;
  687. RelocTyp: TObjRelocationType;
  688. zeros_only: Boolean;
  689. begin
  690. result:=false;
  691. if (length(T)<5) or (((length(T)-2) mod 3)<>0) then
  692. begin
  693. InputError(GenericTErrMsg);
  694. exit;
  695. end;
  696. if (length(R)<11) or (((length(R)-2) mod 3)<>0) then
  697. begin
  698. InputError(GenericRErrMsg);
  699. exit;
  700. end;
  701. SetLength(ArrT,((length(T)-2) div 3)+1);
  702. for i:=0 to length(ArrT)-1 do
  703. begin
  704. if (i>0) and (T[i*3]<>' ') then
  705. begin
  706. InputError(GenericTErrMsg);
  707. exit;
  708. end;
  709. if not TryStrToInt('$'+copy(T,1+i*3,2),tmpint) then
  710. begin
  711. InputError(GenericTErrMsg);
  712. exit;
  713. end;
  714. if (tmpint<0) or (tmpint>255) then
  715. begin
  716. InputError(GenericTErrMsg);
  717. exit;
  718. end;
  719. ArrT[i]:=tmpint;
  720. end;
  721. SetLength(ArrR,((length(R)-2) div 3)+1);
  722. for i:=0 to length(ArrR)-1 do
  723. begin
  724. if (i>0) and (R[i*3]<>' ') then
  725. begin
  726. InputError(GenericRErrMsg);
  727. exit;
  728. end;
  729. if not TryStrToInt('$'+copy(R,1+i*3,2),tmpint) then
  730. begin
  731. InputError(GenericRErrMsg);
  732. exit;
  733. end;
  734. if (tmpint<0) or (tmpint>255) then
  735. begin
  736. InputError(GenericRErrMsg);
  737. exit;
  738. end;
  739. ArrR[i]:=tmpint;
  740. end;
  741. if (length(ArrT)<2) or (length(ArrR)<4) then
  742. internalerror(2020060201);
  743. if (ArrR[0]<>0) or (ArrR[1]<>0) then
  744. begin
  745. InputError(GenericRErrMsg);
  746. exit;
  747. end;
  748. AreaIndex:=(ArrR[3] shl 8) or ArrR[2];
  749. AreaOffset:=(ArrT[1] shl 8) or ArrT[0];
  750. if AreaIndex>=Data.ObjSectionList.Count then
  751. begin
  752. InputError('Area index in R record out of bounds');
  753. exit;
  754. end;
  755. ObjSec:=TObjSection(Data.ObjSectionList[AreaIndex]);
  756. if AreaOffset>ObjSec.Size then
  757. begin
  758. InputError('Area offset in T exceeds area size');
  759. exit;
  760. end;
  761. { section name is '_BSS'/'_STACK'/'_HEAP' and there are no relocations }
  762. if ((ObjSec.Name='_BSS') or (ObjSec.Name='_STACK') or (ObjSec.Name='_HEAP')) and
  763. (length(ArrR)=4) then
  764. begin
  765. zeros_only:=true;
  766. for i:=2 to length(ArrT)-1 do
  767. if ArrT[i]<>0 then
  768. begin
  769. zeros_only:=false;
  770. break;
  771. end;
  772. { avoid setting the oso_Data flag on .bss sections, if there are no relocations and all data is zero }
  773. if zeros_only then
  774. exit;
  775. end;
  776. { parse relocations }
  777. SetLength(ArrTIsRelocHiByte,Length(ArrT));
  778. LastDataOfsIndex:=2;
  779. LastDataOfsValue:=AreaOffset;
  780. i:=4;
  781. while i<length(ArrR) do
  782. begin
  783. n1:=ArrR[i];
  784. Inc(i);
  785. if (n1 and $F0)=$F0 then
  786. begin
  787. if i>=length(ArrR) then
  788. begin
  789. InputError(GenericRErrMsg);
  790. exit;
  791. end;
  792. n1x:=ArrR[i];
  793. Inc(i);
  794. n1:=((n1 and $0F) shl 8) or n1x;
  795. end;
  796. if (i+2)>=length(ArrR) then
  797. begin
  798. InputError(GenericRErrMsg);
  799. exit;
  800. end;
  801. n2:=ArrR[i];
  802. xx_xx:=ArrR[i+1] or (ArrR[i+2] shl 8);
  803. Inc(i,3);
  804. RelFlags:=DecodeRelFlags(n1);
  805. if ((RelFlags*UnsupportedRelocationFlags)<>[]) or
  806. ((rrfByte in RelFlags) xor (rrfTwoByteObjectFormatForByteData in RelFlags)) then
  807. begin
  808. InputError('Unsupported relocation flags ($'+HexStr(n1,3)+')');
  809. exit;
  810. end;
  811. if n2<=1 then
  812. begin
  813. InputError('Invalid relocation data offset');
  814. exit;
  815. end;
  816. if rrfByte in RelFlags then
  817. begin
  818. if rrfMSBWith2ByteMode in RelFlags then
  819. RelocTyp:=RELOC_ABSOLUTE_HI8
  820. else
  821. RelocTyp:=RELOC_ABSOLUTE_LO8;
  822. if (n2+1)>=length(ArrT) then
  823. begin
  824. InputError('Invalid relocation data offset');
  825. exit;
  826. end;
  827. ArrTIsRelocHiByte[n2+1]:=true;
  828. RelHiByte:=ArrT[n2+1];
  829. end
  830. else
  831. begin
  832. RelocTyp:=RELOC_ABSOLUTE;
  833. if n2>=length(ArrT) then
  834. begin
  835. InputError('Invalid relocation data offset');
  836. exit;
  837. end;
  838. RelHiByte:=0;
  839. end;
  840. while LastDataOfsIndex<n2 do
  841. begin
  842. if not ArrTIsRelocHiByte[LastDataOfsIndex] then
  843. Inc(LastDataOfsValue);
  844. Inc(LastDataOfsIndex);
  845. end;
  846. RelocDataOffset:=LastDataOfsValue;
  847. if rrfSymbol in RelFlags then
  848. begin
  849. if xx_xx>=Data.ObjSymbolList.Count then
  850. begin
  851. InputError('Relocation to symbol with invalid index');
  852. exit;
  853. end;
  854. reloc:=TRelRelocation.CreateSymbol(RelocDataOffset,TObjSymbol(Data.ObjSymbolList[xx_xx]),RelocTyp);
  855. end
  856. else
  857. begin
  858. if xx_xx>=Data.ObjSectionlist.Count then
  859. begin
  860. InputError('Relocation to area with invalid index');
  861. exit;
  862. end;
  863. reloc:=TRelRelocation.CreateSection(RelocDataOffset,TObjSection(Data.ObjSectionlist[xx_xx]),RelocTyp);
  864. end;
  865. reloc.RelFlags:=RelFlags;
  866. reloc.HiByte:=RelHiByte;
  867. objsec.ObjRelocations.Add(reloc);
  868. end;
  869. { read the data }
  870. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  871. objsec.Data.seek(AreaOffset);
  872. for i:=2 to length(ArrT)-1 do
  873. if not ArrTIsRelocHiByte[i] then
  874. objsec.Data.write(ArrT[i],1);
  875. result:=true;
  876. end;
  877. const
  878. GenericRelErrMsg='Error reading REL file';
  879. var
  880. s, AreaName, SymbolName: string;
  881. RecType: Char;
  882. HeaderFound: Boolean=false;
  883. ExpectedAreas,ExpectedSymbols,AreaSize,AreaFlags,AreaAddr,
  884. SymbolOfs: LongInt;
  885. tmpint: SizeInt;
  886. CurrSec: TObjSection=nil;
  887. objsym: TObjSymbol;
  888. LastT: string='';
  889. begin
  890. FReader:=AReader;
  891. InputFileName:=AReader.FileName;
  892. Data:=CObjData.Create(InputFileName);
  893. ExpectedAreas:=-1;
  894. ExpectedSymbols:=-1;
  895. result:=false;
  896. s:='';
  897. repeat
  898. if AtEoF or not ReadLine(s) then
  899. begin
  900. InputError(GenericRelErrMsg);
  901. exit;
  902. end;
  903. s:=Trim(s);
  904. until s<>'';
  905. if s<>'XL2' then
  906. begin
  907. InputError('Invalid or unsupported REL format identifier');
  908. exit;
  909. end;
  910. while not AtEoF do
  911. begin
  912. if not ReadLine(s) then
  913. begin
  914. InputError(GenericRelErrMsg);
  915. exit;
  916. end;
  917. s:=Trim(s);
  918. if s<>'' then
  919. begin
  920. RecType:=s[1];
  921. if (length(s)<3) or (s[2]<>' ') then
  922. begin
  923. InputError('Invalid or unsupported REL record');
  924. exit;
  925. end;
  926. delete(s,1,2);
  927. case RecType of
  928. 'H': { header }
  929. begin
  930. if HeaderFound then
  931. begin
  932. InputError('Duplicated header');
  933. exit;
  934. end;
  935. HeaderFound:=true;
  936. tmpint:=Pos(' ',s);
  937. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedAreas) then
  938. begin
  939. InputError('Invalid area count in header');
  940. exit;
  941. end;
  942. delete(s,1,tmpint);
  943. if copy(s,1,6)<>'areas ' then
  944. begin
  945. InputError('Invalid header');
  946. exit;
  947. end;
  948. delete(s,1,6);
  949. tmpint:=Pos(' ',s);
  950. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedSymbols) then
  951. begin
  952. InputError('Invalid symbol count in header');
  953. exit;
  954. end;
  955. delete(s,1,tmpint);
  956. if s<>'global symbols' then
  957. begin
  958. InputError('Invalid header');
  959. exit;
  960. end;
  961. end;
  962. 'M': { module }
  963. begin
  964. { we ignore this for now }
  965. end;
  966. 'S': { symbol }
  967. begin
  968. if not HeaderFound then
  969. begin
  970. InputError('Symbol record encountered before header');
  971. exit;
  972. end;
  973. tmpint:=Pos(' ',s);
  974. if tmpint<=1 then
  975. begin
  976. InputError('Invalid symbol record');
  977. exit;
  978. end;
  979. SymbolName:=copy(s,1,tmpint-1);
  980. delete(s,1,tmpint);
  981. if Length(s)<4 then
  982. begin
  983. InputError('Invalid symbol record');
  984. exit;
  985. end;
  986. if not TryStrToInt('$'+Copy(s,4,Length(s)-3),SymbolOfs) then
  987. begin
  988. InputError('Invalid symbol offset');
  989. exit;
  990. end;
  991. case Copy(s,1,3) of
  992. 'Def':
  993. begin
  994. if CurrSec=nil then
  995. begin
  996. InputError('Public symbol defined outside any area');
  997. exit;
  998. end;
  999. if (SymbolOfs<0) or (SymbolOfs>CurrSec.Size) then
  1000. begin
  1001. InputError('Public symbol offset outside the range of the current area');
  1002. exit;
  1003. end;
  1004. objsym:=Data.CreateSymbol(SymbolName);
  1005. objsym.bind:=AB_GLOBAL;
  1006. objsym.typ:=AT_FUNCTION;
  1007. objsym.objsection:=CurrSec;
  1008. objsym.offset:=SymbolOfs;
  1009. objsym.size:=0;
  1010. end;
  1011. 'Ref':
  1012. begin
  1013. if CurrSec<>nil then
  1014. begin
  1015. InputError('External symbols must be defined before the first area');
  1016. exit;
  1017. end;
  1018. if SymbolOfs<>0 then
  1019. begin
  1020. InputError('External symbols must be declared with an offset of 0');
  1021. exit;
  1022. end;
  1023. objsym:=Data.CreateSymbol(SymbolName);
  1024. objsym.bind:=AB_EXTERNAL;
  1025. objsym.typ:=AT_FUNCTION;
  1026. objsym.objsection:=nil;
  1027. objsym.offset:=0;
  1028. objsym.size:=0;
  1029. end;
  1030. else
  1031. begin
  1032. InputError('Invalid or unsupported symbol record');
  1033. exit;
  1034. end;
  1035. end;
  1036. if Data.ObjSymbolList.Count>ExpectedSymbols then
  1037. begin
  1038. InputError('Number of symbols exceeds the number, declared in header');
  1039. exit;
  1040. end;
  1041. end;
  1042. 'A': { area }
  1043. begin
  1044. if not HeaderFound then
  1045. begin
  1046. InputError('Area record encountered before header');
  1047. exit;
  1048. end;
  1049. tmpint:=Pos(' ',s);
  1050. if tmpint<=1 then
  1051. begin
  1052. InputError('Invalid area record');
  1053. exit;
  1054. end;
  1055. AreaName:=copy(s,1,tmpint-1);
  1056. delete(s,1,tmpint);
  1057. if copy(s,1,5)<>'size ' then
  1058. begin
  1059. InputError('Invalid area record');
  1060. exit;
  1061. end;
  1062. delete(s,1,5);
  1063. tmpint:=Pos(' ',s);
  1064. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaSize) then
  1065. begin
  1066. InputError('Invalid area size');
  1067. exit;
  1068. end;
  1069. delete(s,1,tmpint);
  1070. if copy(s,1,6)<>'flags ' then
  1071. begin
  1072. InputError('Invalid area record');
  1073. exit;
  1074. end;
  1075. delete(s,1,6);
  1076. tmpint:=Pos(' ',s);
  1077. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaFlags) then
  1078. begin
  1079. InputError('Invalid area flags');
  1080. exit;
  1081. end;
  1082. delete(s,1,tmpint);
  1083. if copy(s,1,5)<>'addr ' then
  1084. begin
  1085. InputError('Invalid area record');
  1086. exit;
  1087. end;
  1088. delete(s,1,5);
  1089. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaAddr) then
  1090. begin
  1091. InputError('Invalid area address');
  1092. exit;
  1093. end;
  1094. if AreaFlags<>0 then
  1095. begin
  1096. InputError('Unsupported area flags ('+tostr(AreaFlags)+')');
  1097. exit;
  1098. end;
  1099. if AreaAddr<>0 then
  1100. begin
  1101. InputError('Area address<>0 not supported');
  1102. exit;
  1103. end;
  1104. CurrSec:=Data.createsection(AreaName,1,[],false);
  1105. CurrSec.alloc(AreaSize);
  1106. if Data.ObjSectionList.Count>ExpectedAreas then
  1107. begin
  1108. InputError('Number of areas exceeds the number, declared in header');
  1109. exit;
  1110. end;
  1111. end;
  1112. 'T': { T line () }
  1113. begin
  1114. if LastT<>'' then
  1115. begin
  1116. InputError('T record not followed by R record');
  1117. exit;
  1118. end;
  1119. LastT:=s;
  1120. end;
  1121. 'R': { R line (relocation information) }
  1122. begin
  1123. if LastT='' then
  1124. begin
  1125. InputError('R record without T record');
  1126. exit;
  1127. end;
  1128. if not HandleTR(LastT,s) then
  1129. exit;
  1130. LastT:='';
  1131. end;
  1132. 'P': { P line (paging information) }
  1133. begin
  1134. InputError('P line records are not supported');
  1135. exit;
  1136. end;
  1137. else
  1138. begin
  1139. InputError('Unsupported REL record type: #'+tostr(Ord(RecType)));
  1140. exit;
  1141. end;
  1142. end;
  1143. end;
  1144. end;
  1145. result:=true;
  1146. end;
  1147. class function TRelObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  1148. var
  1149. s: string;
  1150. instance: TRelObjInput;
  1151. begin
  1152. result:=false;
  1153. instance:=TRelObjInput.Create;
  1154. instance.FReader:=AReader;
  1155. with instance do
  1156. while not AtEoF do
  1157. begin
  1158. if not ReadLine(s) then
  1159. exit;
  1160. s:=Trim(s);
  1161. if s<>'' then
  1162. begin
  1163. result:=s='XL2';
  1164. break;
  1165. end;
  1166. end;
  1167. instance.Free;
  1168. instance := nil;
  1169. end;
  1170. {*****************************************************************************
  1171. TIntelHexExeOutput
  1172. *****************************************************************************}
  1173. procedure TIntelHexExeOutput.writeString(const S: ansistring);
  1174. begin
  1175. FWriter.write(S[1],Length(S));
  1176. end;
  1177. procedure TIntelHexExeOutput.writeLine(const S: ansistring);
  1178. begin
  1179. writeString(S+#10)
  1180. end;
  1181. function TIntelHexExeOutput.writeData: boolean;
  1182. const
  1183. MaxRecLen=16;
  1184. var
  1185. exesec: TExeSection;
  1186. objsec: TObjSection;
  1187. exesec_i, objsec_i: Integer;
  1188. s: string;
  1189. blocklen, i: integer;
  1190. buf: array [0..MaxRecLen-1] of Byte;
  1191. blockaddr: Word;
  1192. checksum: Byte;
  1193. begin
  1194. result:=false;
  1195. for exesec_i:=0 to ExeSectionList.Count-1 do
  1196. begin
  1197. exesec:=TExeSection(ExeSectionList[exesec_i]);
  1198. for objsec_i:=0 to exesec.ObjSectionList.Count-1 do
  1199. begin
  1200. objsec:=TObjSection(exesec.ObjSectionList[objsec_i]);
  1201. if oso_Data in objsec.SecOptions then
  1202. begin
  1203. objsec.Data.seek(0);
  1204. while objsec.Data.Pos<objsec.Data.size do
  1205. begin
  1206. blocklen:=Min(objsec.Data.size-objsec.Data.Pos,MaxRecLen);
  1207. blockaddr:=objsec.Data.Pos+objsec.MemPos+ImageBase;
  1208. s:=':'+HexStr(blocklen,2)+HexStr(blockaddr,4)+'00';
  1209. checksum:=Byte(blocklen)+Byte(blockaddr shr 8)+Byte(blockaddr)+0;
  1210. if objsec.Data.read(buf,blocklen)<>blocklen then
  1211. internalerror(2020060301);
  1212. for i:=0 to blocklen-1 do
  1213. begin
  1214. s:=s+HexStr(buf[i],2);
  1215. checksum:=Byte(checksum+buf[i]);
  1216. end;
  1217. checksum:=$100-checksum;
  1218. s:=s+HexStr(checksum,2);
  1219. writeLine(s);
  1220. end;
  1221. end;
  1222. end;
  1223. end;
  1224. writeLine(':00000001FF');
  1225. result:=true;
  1226. end;
  1227. procedure TIntelHexExeOutput.DoRelocationFixup(objsec: TObjSection);
  1228. var
  1229. i: Integer;
  1230. objreloc: TRelRelocation;
  1231. target,w: Word;
  1232. b: Byte;
  1233. begin
  1234. for i:=0 to objsec.ObjRelocations.Count-1 do
  1235. begin
  1236. objreloc:=TRelRelocation(objsec.ObjRelocations[i]);
  1237. if assigned(objreloc.symbol) then
  1238. target:=objreloc.symbol.address+ImageBase
  1239. else if assigned(objreloc.objsection) then
  1240. target:=objreloc.objsection.MemPos+ImageBase
  1241. else
  1242. internalerror(2020060302);
  1243. case objreloc.typ of
  1244. RELOC_ABSOLUTE:
  1245. begin
  1246. objsec.Data.seek(objreloc.DataOffset);
  1247. objsec.Data.read(w,2);
  1248. w:=LEtoN(w);
  1249. Inc(w,target);
  1250. w:=LEtoN(w);
  1251. objsec.Data.seek(objreloc.DataOffset);
  1252. objsec.Data.write(w,2);
  1253. end;
  1254. RELOC_ABSOLUTE_HI8:
  1255. begin
  1256. objsec.Data.seek(objreloc.DataOffset);
  1257. objsec.Data.read(b,1);
  1258. w:=b or (objreloc.HiByte shl 8);
  1259. Inc(w,target);
  1260. b:=Byte(w shr 8);
  1261. objsec.Data.seek(objreloc.DataOffset);
  1262. objsec.Data.write(b,1);
  1263. end;
  1264. RELOC_ABSOLUTE_LO8:
  1265. begin
  1266. objsec.Data.seek(objreloc.DataOffset);
  1267. objsec.Data.read(b,1);
  1268. w:=b or (objreloc.HiByte shl 8);
  1269. Inc(w,target);
  1270. b:=Byte(w);
  1271. objsec.Data.seek(objreloc.DataOffset);
  1272. objsec.Data.write(b,1);
  1273. end;
  1274. else
  1275. internalerror(2020060303);
  1276. end;
  1277. end;
  1278. end;
  1279. constructor TIntelHexExeOutput.create;
  1280. begin
  1281. inherited create;
  1282. CObjData:=TRelObjData;
  1283. MaxMemPos:=$FFFF;
  1284. end;
  1285. {*****************************************************************************
  1286. TZXSpectrumIntelHexExeOutput
  1287. *****************************************************************************}
  1288. constructor TZXSpectrumIntelHexExeOutput.create;
  1289. begin
  1290. inherited create;
  1291. { The ZX Spectrum RTL switches to interrupt mode 2, and install an
  1292. interrupt handler + table, starting at address $FDFD, so we must limit
  1293. program size to $FDFC }
  1294. MaxMemPos:=$FDFC;
  1295. end;
  1296. {*****************************************************************************
  1297. Initialize
  1298. *****************************************************************************}
  1299. const
  1300. as_z80_rel_info : tasminfo =
  1301. (
  1302. id : as_z80_rel;
  1303. idtxt : 'REL';
  1304. asmbin : '';
  1305. asmcmd : '';
  1306. supported_targets : [system_z80_embedded,system_z80_zxspectrum,system_z80_msxdos];
  1307. flags : [af_outputbinary,af_smartlink_sections];
  1308. labelprefix : '..@';
  1309. labelmaxlen : 79;
  1310. comment : '; ';
  1311. dollarsign: '$';
  1312. );
  1313. initialization
  1314. RegisterAssembler(as_z80_rel_info,TRelAssembler);
  1315. end.