ogrel.pas 47 KB

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