ogrel.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364
  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. if AtEoF then
  572. begin
  573. result:=false;
  574. exit;
  575. end;
  576. repeat
  577. if not AtEoF then
  578. begin
  579. if not ReadChar(c) then
  580. begin
  581. result:=false;
  582. exit;
  583. end;
  584. if not (c in [#13,#10]) then
  585. s:=s+c;
  586. end;
  587. until (c in [#13,#10]) or AtEoF;
  588. if (c=#13) and not AtEoF then
  589. begin
  590. if not PeekChar(c) then
  591. begin
  592. result:=false;
  593. exit;
  594. end;
  595. if c=#10 then
  596. begin
  597. if not ReadChar(c) then
  598. begin
  599. result:=false;
  600. exit;
  601. end;
  602. end;
  603. end;
  604. result:=true;
  605. end;
  606. constructor TRelObjInput.create;
  607. begin
  608. inherited create;
  609. cobjdata:=TRelObjData;
  610. FBufSize:=0;
  611. FBufPos:=0;
  612. end;
  613. function TRelObjInput.ReadObjData(AReader: TObjectreader; out Data: TObjData): boolean;
  614. function DecodeRelFlags(n1: Word): TRelRelocationFlags;
  615. begin
  616. result:=[];
  617. if (n1 and (1 shl 0))<>0 then
  618. include(result,rrfByte);
  619. if (n1 and (1 shl 1))<>0 then
  620. include(result,rrfSymbol);
  621. if (n1 and (1 shl 2))<>0 then
  622. include(result,rrfPcRelative);
  623. if (n1 and (1 shl 3))<>0 then
  624. include(result,rrfTwoByteObjectFormatForByteData);
  625. if (n1 and (1 shl 4))<>0 then
  626. include(result,rrfUnsignedByteData);
  627. if (n1 and (1 shl 5))<>0 then
  628. include(result,rrfPage0Reference);
  629. if (n1 and (1 shl 6))<>0 then
  630. include(result,rrfPageNNNReference);
  631. if (n1 and (1 shl 7))<>0 then
  632. include(result,rrfMSBWith2ByteMode);
  633. if (n1 and (1 shl 8))<>0 then
  634. include(result,rrfThreeByteObjectFormatForByteData);
  635. if (n1 and (1 shl 9))<>0 then
  636. include(result,rrfRealMSBForThreeByteMode);
  637. if (n1 and (1 shl 10))<>0 then
  638. include(result,rrfReserved10);
  639. if (n1 and (1 shl 11))<>0 then
  640. include(result,rrfReserved11);
  641. end;
  642. function HandleTR(const T,R: string): boolean;
  643. const
  644. GenericTErrMsg='Invalid T record';
  645. GenericRErrMsg='Invalid R record';
  646. UnsupportedRelocationFlags=[rrfPcRelative,rrfUnsignedByteData,
  647. rrfPage0Reference,rrfPageNNNReference,rrfThreeByteObjectFormatForByteData,
  648. rrfRealMSBForThreeByteMode,rrfReserved10,rrfReserved11];
  649. var
  650. ArrT, ArrR: array of byte;
  651. ArrTIsRelocHiByte: array of boolean;
  652. tmpint: Longint;
  653. i: Integer;
  654. AreaIndex, AreaOffset: Word;
  655. LastDataOfsIndex: Integer;
  656. LastDataOfsValue: TObjSectionOfs;
  657. ObjSec: TObjSection;
  658. n1, xx_xx: Word;
  659. n1x, n2, RelHiByte: Byte;
  660. RelFlags: TRelRelocationFlags;
  661. reloc:TRelRelocation;
  662. RelocDataOffset: TObjSectionOfs;
  663. RelocTyp: TObjRelocationType;
  664. zeros_only: Boolean;
  665. begin
  666. result:=false;
  667. if (length(T)<5) or (((length(T)-2) mod 3)<>0) then
  668. begin
  669. InputError(GenericTErrMsg);
  670. exit;
  671. end;
  672. if (length(R)<11) or (((length(R)-2) mod 3)<>0) then
  673. begin
  674. InputError(GenericRErrMsg);
  675. exit;
  676. end;
  677. SetLength(ArrT,((length(T)-2) div 3)+1);
  678. for i:=0 to length(ArrT)-1 do
  679. begin
  680. if (i>0) and (T[i*3]<>' ') then
  681. begin
  682. InputError(GenericTErrMsg);
  683. exit;
  684. end;
  685. if not TryStrToInt('$'+copy(T,1+i*3,2),tmpint) then
  686. begin
  687. InputError(GenericTErrMsg);
  688. exit;
  689. end;
  690. if (tmpint<0) or (tmpint>255) then
  691. begin
  692. InputError(GenericTErrMsg);
  693. exit;
  694. end;
  695. ArrT[i]:=tmpint;
  696. end;
  697. SetLength(ArrR,((length(R)-2) div 3)+1);
  698. for i:=0 to length(ArrR)-1 do
  699. begin
  700. if (i>0) and (R[i*3]<>' ') then
  701. begin
  702. InputError(GenericRErrMsg);
  703. exit;
  704. end;
  705. if not TryStrToInt('$'+copy(R,1+i*3,2),tmpint) then
  706. begin
  707. InputError(GenericRErrMsg);
  708. exit;
  709. end;
  710. if (tmpint<0) or (tmpint>255) then
  711. begin
  712. InputError(GenericRErrMsg);
  713. exit;
  714. end;
  715. ArrR[i]:=tmpint;
  716. end;
  717. if (length(ArrT)<2) or (length(ArrR)<4) then
  718. internalerror(2020060201);
  719. if (ArrR[0]<>0) or (ArrR[1]<>0) then
  720. begin
  721. InputError(GenericRErrMsg);
  722. exit;
  723. end;
  724. AreaIndex:=(ArrR[3] shl 8) or ArrR[2];
  725. AreaOffset:=(ArrT[1] shl 8) or ArrT[0];
  726. if AreaIndex>=Data.ObjSectionList.Count then
  727. begin
  728. InputError('Area index in R record out of bounds');
  729. exit;
  730. end;
  731. ObjSec:=TObjSection(Data.ObjSectionList[AreaIndex]);
  732. if AreaOffset>ObjSec.Size then
  733. begin
  734. InputError('Area offset in T exceeds area size');
  735. exit;
  736. end;
  737. { section name is '_BSS'/'_STACK'/'_HEAP' and there are no relocations }
  738. if ((ObjSec.Name='_BSS') or (ObjSec.Name='_STACK') or (ObjSec.Name='_HEAP')) and
  739. (length(ArrR)=4) then
  740. begin
  741. zeros_only:=true;
  742. for i:=2 to length(ArrT)-1 do
  743. if ArrT[i]<>0 then
  744. begin
  745. zeros_only:=false;
  746. break;
  747. end;
  748. { avoid setting the oso_Data flag on .bss sections, if there are no relocations and all data is zero }
  749. if zeros_only then
  750. exit;
  751. end;
  752. { parse relocations }
  753. SetLength(ArrTIsRelocHiByte,Length(ArrT));
  754. LastDataOfsIndex:=2;
  755. LastDataOfsValue:=AreaOffset;
  756. i:=4;
  757. while i<length(ArrR) do
  758. begin
  759. n1:=ArrR[i];
  760. Inc(i);
  761. if (n1 and $F0)=$F0 then
  762. begin
  763. if i>=length(ArrR) then
  764. begin
  765. InputError(GenericRErrMsg);
  766. exit;
  767. end;
  768. n1x:=ArrR[i];
  769. Inc(i);
  770. n1:=((n1 and $0F) shl 8) or n1x;
  771. end;
  772. if (i+2)>=length(ArrR) then
  773. begin
  774. InputError(GenericRErrMsg);
  775. exit;
  776. end;
  777. n2:=ArrR[i];
  778. xx_xx:=ArrR[i+1] or (ArrR[i+2] shl 8);
  779. Inc(i,3);
  780. RelFlags:=DecodeRelFlags(n1);
  781. if ((RelFlags*UnsupportedRelocationFlags)<>[]) or
  782. ((rrfByte in RelFlags) xor (rrfTwoByteObjectFormatForByteData in RelFlags)) then
  783. begin
  784. InputError('Unsupported relocation flags ($'+HexStr(n1,3)+')');
  785. exit;
  786. end;
  787. if n2<=1 then
  788. begin
  789. InputError('Invalid relocation data offset');
  790. exit;
  791. end;
  792. if rrfByte in RelFlags then
  793. begin
  794. if rrfMSBWith2ByteMode in RelFlags then
  795. RelocTyp:=RELOC_ABSOLUTE_HI8
  796. else
  797. RelocTyp:=RELOC_ABSOLUTE_LO8;
  798. if (n2+1)>=length(ArrT) then
  799. begin
  800. InputError('Invalid relocation data offset');
  801. exit;
  802. end;
  803. ArrTIsRelocHiByte[n2+1]:=true;
  804. RelHiByte:=ArrT[n2+1];
  805. end
  806. else
  807. begin
  808. RelocTyp:=RELOC_ABSOLUTE;
  809. if n2>=length(ArrT) then
  810. begin
  811. InputError('Invalid relocation data offset');
  812. exit;
  813. end;
  814. RelHiByte:=0;
  815. end;
  816. while LastDataOfsIndex<n2 do
  817. begin
  818. if not ArrTIsRelocHiByte[LastDataOfsIndex] then
  819. Inc(LastDataOfsValue);
  820. Inc(LastDataOfsIndex);
  821. end;
  822. RelocDataOffset:=LastDataOfsValue;
  823. if rrfSymbol in RelFlags then
  824. begin
  825. if xx_xx>=Data.ObjSymbolList.Count then
  826. begin
  827. InputError('Relocation to symbol with invalid index');
  828. exit;
  829. end;
  830. reloc:=TRelRelocation.CreateSymbol(RelocDataOffset,TObjSymbol(Data.ObjSymbolList[xx_xx]),RelocTyp);
  831. end
  832. else
  833. begin
  834. if xx_xx>=Data.ObjSectionlist.Count then
  835. begin
  836. InputError('Relocation to area with invalid index');
  837. exit;
  838. end;
  839. reloc:=TRelRelocation.CreateSection(RelocDataOffset,TObjSection(Data.ObjSectionlist[xx_xx]),RelocTyp);
  840. end;
  841. reloc.RelFlags:=RelFlags;
  842. reloc.HiByte:=RelHiByte;
  843. objsec.ObjRelocations.Add(reloc);
  844. end;
  845. { read the data }
  846. objsec.SecOptions:=objsec.SecOptions+[oso_Data];
  847. objsec.Data.seek(AreaOffset);
  848. for i:=2 to length(ArrT)-1 do
  849. if not ArrTIsRelocHiByte[i] then
  850. objsec.Data.write(ArrT[i],1);
  851. result:=true;
  852. end;
  853. const
  854. GenericRelErrMsg='Error reading REL file';
  855. var
  856. s, AreaName, SymbolName: string;
  857. RecType: Char;
  858. HeaderFound: Boolean=false;
  859. ExpectedAreas,ExpectedSymbols,AreaSize,AreaFlags,AreaAddr,
  860. SymbolOfs: LongInt;
  861. tmpint: SizeInt;
  862. CurrSec: TObjSection=nil;
  863. objsym: TObjSymbol;
  864. LastT: string='';
  865. begin
  866. FReader:=AReader;
  867. InputFileName:=AReader.FileName;
  868. Data:=CObjData.Create(InputFileName);
  869. result:=false;
  870. s:='';
  871. repeat
  872. if AtEoF or not ReadLine(s) then
  873. begin
  874. InputError(GenericRelErrMsg);
  875. exit;
  876. end;
  877. s:=Trim(s);
  878. until s<>'';
  879. if s<>'XL2' then
  880. begin
  881. InputError('Invalid or unsupported REL format identifier');
  882. exit;
  883. end;
  884. while not AtEoF do
  885. begin
  886. if not ReadLine(s) then
  887. begin
  888. InputError(GenericRelErrMsg);
  889. exit;
  890. end;
  891. s:=Trim(s);
  892. if s<>'' then
  893. begin
  894. RecType:=s[1];
  895. if (length(s)<3) or (s[2]<>' ') then
  896. begin
  897. InputError('Invalid or unsupported REL record');
  898. exit;
  899. end;
  900. delete(s,1,2);
  901. case RecType of
  902. 'H': { header }
  903. begin
  904. if HeaderFound then
  905. begin
  906. InputError('Duplicated header');
  907. exit;
  908. end;
  909. HeaderFound:=true;
  910. tmpint:=Pos(' ',s);
  911. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedAreas) then
  912. begin
  913. InputError('Invalid area count in header');
  914. exit;
  915. end;
  916. delete(s,1,tmpint);
  917. if copy(s,1,6)<>'areas ' then
  918. begin
  919. InputError('Invalid header');
  920. exit;
  921. end;
  922. delete(s,1,6);
  923. tmpint:=Pos(' ',s);
  924. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedSymbols) then
  925. begin
  926. InputError('Invalid symbol count in header');
  927. exit;
  928. end;
  929. delete(s,1,tmpint);
  930. if s<>'global symbols' then
  931. begin
  932. InputError('Invalid header');
  933. exit;
  934. end;
  935. end;
  936. 'M': { module }
  937. begin
  938. { we ignore this for now }
  939. end;
  940. 'S': { symbol }
  941. begin
  942. if not HeaderFound then
  943. begin
  944. InputError('Symbol record encountered before header');
  945. exit;
  946. end;
  947. tmpint:=Pos(' ',s);
  948. if tmpint<=1 then
  949. begin
  950. InputError('Invalid symbol record');
  951. exit;
  952. end;
  953. SymbolName:=copy(s,1,tmpint-1);
  954. delete(s,1,tmpint);
  955. if Length(s)<4 then
  956. begin
  957. InputError('Invalid symbol record');
  958. exit;
  959. end;
  960. if not TryStrToInt('$'+Copy(s,4,Length(s)-3),SymbolOfs) then
  961. begin
  962. InputError('Invalid symbol offset');
  963. exit;
  964. end;
  965. case Copy(s,1,3) of
  966. 'Def':
  967. begin
  968. if CurrSec=nil then
  969. begin
  970. InputError('Public symbol defined outside any area');
  971. exit;
  972. end;
  973. if (SymbolOfs<0) or (SymbolOfs>CurrSec.Size) then
  974. begin
  975. InputError('Public symbol offset outside the range of the current area');
  976. exit;
  977. end;
  978. objsym:=Data.CreateSymbol(SymbolName);
  979. objsym.bind:=AB_GLOBAL;
  980. objsym.typ:=AT_FUNCTION;
  981. objsym.objsection:=CurrSec;
  982. objsym.offset:=SymbolOfs;
  983. objsym.size:=0;
  984. end;
  985. 'Ref':
  986. begin
  987. if CurrSec<>nil then
  988. begin
  989. InputError('External symbols must be defined before the first area');
  990. exit;
  991. end;
  992. if SymbolOfs<>0 then
  993. begin
  994. InputError('External symbols must be declared with an offset of 0');
  995. exit;
  996. end;
  997. objsym:=Data.CreateSymbol(SymbolName);
  998. objsym.bind:=AB_EXTERNAL;
  999. objsym.typ:=AT_FUNCTION;
  1000. objsym.objsection:=nil;
  1001. objsym.offset:=0;
  1002. objsym.size:=0;
  1003. end;
  1004. else
  1005. begin
  1006. InputError('Invalid or unsupported symbol record');
  1007. exit;
  1008. end;
  1009. end;
  1010. if Data.ObjSymbolList.Count>ExpectedSymbols then
  1011. begin
  1012. InputError('Number of symbols exceeds the number, declared in header');
  1013. exit;
  1014. end;
  1015. end;
  1016. 'A': { area }
  1017. begin
  1018. if not HeaderFound then
  1019. begin
  1020. InputError('Area record encountered before header');
  1021. exit;
  1022. end;
  1023. tmpint:=Pos(' ',s);
  1024. if tmpint<=1 then
  1025. begin
  1026. InputError('Invalid area record');
  1027. exit;
  1028. end;
  1029. AreaName:=copy(s,1,tmpint-1);
  1030. delete(s,1,tmpint);
  1031. if copy(s,1,5)<>'size ' then
  1032. begin
  1033. InputError('Invalid area record');
  1034. exit;
  1035. end;
  1036. delete(s,1,5);
  1037. tmpint:=Pos(' ',s);
  1038. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaSize) then
  1039. begin
  1040. InputError('Invalid area size');
  1041. exit;
  1042. end;
  1043. delete(s,1,tmpint);
  1044. if copy(s,1,6)<>'flags ' then
  1045. begin
  1046. InputError('Invalid area record');
  1047. exit;
  1048. end;
  1049. delete(s,1,6);
  1050. tmpint:=Pos(' ',s);
  1051. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaFlags) then
  1052. begin
  1053. InputError('Invalid area flags');
  1054. exit;
  1055. end;
  1056. delete(s,1,tmpint);
  1057. if copy(s,1,5)<>'addr ' then
  1058. begin
  1059. InputError('Invalid area record');
  1060. exit;
  1061. end;
  1062. delete(s,1,5);
  1063. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaAddr) then
  1064. begin
  1065. InputError('Invalid area address');
  1066. exit;
  1067. end;
  1068. if AreaFlags<>0 then
  1069. begin
  1070. InputError('Unsupported area flags ('+tostr(AreaFlags)+')');
  1071. exit;
  1072. end;
  1073. if AreaAddr<>0 then
  1074. begin
  1075. InputError('Area address<>0 not supported');
  1076. exit;
  1077. end;
  1078. CurrSec:=Data.createsection(AreaName,1,[],false);
  1079. CurrSec.alloc(AreaSize);
  1080. if Data.ObjSectionList.Count>ExpectedAreas then
  1081. begin
  1082. InputError('Number of areas exceeds the number, declared in header');
  1083. exit;
  1084. end;
  1085. end;
  1086. 'T': { T line () }
  1087. begin
  1088. if LastT<>'' then
  1089. begin
  1090. InputError('T record not followed by R record');
  1091. exit;
  1092. end;
  1093. LastT:=s;
  1094. end;
  1095. 'R': { R line (relocation information) }
  1096. begin
  1097. if LastT='' then
  1098. begin
  1099. InputError('R record without T record');
  1100. exit;
  1101. end;
  1102. if not HandleTR(LastT,s) then
  1103. exit;
  1104. LastT:='';
  1105. end;
  1106. 'P': { P line (paging information) }
  1107. begin
  1108. InputError('P line records are not supported');
  1109. exit;
  1110. end;
  1111. else
  1112. begin
  1113. InputError('Unsupported REL record type: #'+tostr(Ord(RecType)));
  1114. exit;
  1115. end;
  1116. end;
  1117. end;
  1118. end;
  1119. result:=true;
  1120. end;
  1121. class function TRelObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  1122. var
  1123. s: string;
  1124. instance: TRelObjInput;
  1125. begin
  1126. result:=false;
  1127. instance:=TRelObjInput.Create;
  1128. instance.FReader:=AReader;
  1129. with instance do
  1130. while not AtEoF do
  1131. begin
  1132. if not ReadLine(s) then
  1133. exit;
  1134. s:=Trim(s);
  1135. if s<>'' then
  1136. begin
  1137. result:=s='XL2';
  1138. break;
  1139. end;
  1140. end;
  1141. instance.Free;
  1142. end;
  1143. {*****************************************************************************
  1144. TIntelHexExeOutput
  1145. *****************************************************************************}
  1146. procedure TIntelHexExeOutput.writeString(const S: ansistring);
  1147. begin
  1148. FWriter.write(S[1],Length(S));
  1149. end;
  1150. procedure TIntelHexExeOutput.writeLine(const S: ansistring);
  1151. begin
  1152. writeString(S+#10)
  1153. end;
  1154. function TIntelHexExeOutput.writeData: boolean;
  1155. const
  1156. MaxRecLen=16;
  1157. var
  1158. exesec: TExeSection;
  1159. objsec: TObjSection;
  1160. exesec_i, objsec_i: Integer;
  1161. s: string;
  1162. blocklen, i: integer;
  1163. buf: array [0..MaxRecLen-1] of Byte;
  1164. blockaddr: Word;
  1165. checksum: Byte;
  1166. begin
  1167. result:=false;
  1168. for exesec_i:=0 to ExeSectionList.Count-1 do
  1169. begin
  1170. exesec:=TExeSection(ExeSectionList[exesec_i]);
  1171. for objsec_i:=0 to exesec.ObjSectionList.Count-1 do
  1172. begin
  1173. objsec:=TObjSection(exesec.ObjSectionList[objsec_i]);
  1174. if oso_Data in objsec.SecOptions then
  1175. begin
  1176. objsec.Data.seek(0);
  1177. while objsec.Data.Pos<objsec.Data.size do
  1178. begin
  1179. blocklen:=Min(objsec.Data.size-objsec.Data.Pos,MaxRecLen);
  1180. blockaddr:=objsec.Data.Pos+objsec.MemPos+ImageBase;
  1181. s:=':'+HexStr(blocklen,2)+HexStr(blockaddr,4)+'00';
  1182. checksum:=Byte(blocklen)+Byte(blockaddr shr 8)+Byte(blockaddr)+0;
  1183. if objsec.Data.read(buf,blocklen)<>blocklen then
  1184. internalerror(2020060301);
  1185. for i:=0 to blocklen-1 do
  1186. begin
  1187. s:=s+HexStr(buf[i],2);
  1188. checksum:=Byte(checksum+buf[i]);
  1189. end;
  1190. checksum:=$100-checksum;
  1191. s:=s+HexStr(checksum,2);
  1192. writeLine(s);
  1193. end;
  1194. end;
  1195. end;
  1196. end;
  1197. writeLine(':00000001FF');
  1198. result:=true;
  1199. end;
  1200. procedure TIntelHexExeOutput.DoRelocationFixup(objsec: TObjSection);
  1201. var
  1202. i: Integer;
  1203. objreloc: TRelRelocation;
  1204. target,w: Word;
  1205. b: Byte;
  1206. begin
  1207. for i:=0 to objsec.ObjRelocations.Count-1 do
  1208. begin
  1209. objreloc:=TRelRelocation(objsec.ObjRelocations[i]);
  1210. if assigned(objreloc.symbol) then
  1211. target:=objreloc.symbol.address+ImageBase
  1212. else if assigned(objreloc.objsection) then
  1213. target:=objreloc.objsection.MemPos+ImageBase
  1214. else
  1215. internalerror(2020060302);
  1216. case objreloc.typ of
  1217. RELOC_ABSOLUTE:
  1218. begin
  1219. objsec.Data.seek(objreloc.DataOffset);
  1220. objsec.Data.read(w,2);
  1221. w:=LEtoN(w);
  1222. Inc(w,target);
  1223. w:=LEtoN(w);
  1224. objsec.Data.seek(objreloc.DataOffset);
  1225. objsec.Data.write(w,2);
  1226. end;
  1227. RELOC_ABSOLUTE_HI8:
  1228. begin
  1229. objsec.Data.seek(objreloc.DataOffset);
  1230. objsec.Data.read(b,1);
  1231. w:=b or (objreloc.HiByte shl 8);
  1232. Inc(w,target);
  1233. b:=Byte(w shr 8);
  1234. objsec.Data.seek(objreloc.DataOffset);
  1235. objsec.Data.write(b,1);
  1236. end;
  1237. RELOC_ABSOLUTE_LO8:
  1238. begin
  1239. objsec.Data.seek(objreloc.DataOffset);
  1240. objsec.Data.read(b,1);
  1241. w:=b or (objreloc.HiByte shl 8);
  1242. Inc(w,target);
  1243. b:=Byte(w);
  1244. objsec.Data.seek(objreloc.DataOffset);
  1245. objsec.Data.write(b,1);
  1246. end;
  1247. else
  1248. internalerror(2020060303);
  1249. end;
  1250. end;
  1251. end;
  1252. constructor TIntelHexExeOutput.create;
  1253. begin
  1254. inherited create;
  1255. CObjData:=TRelObjData;
  1256. MaxMemPos:=$FFFF;
  1257. end;
  1258. {*****************************************************************************
  1259. TZXSpectrumIntelHexExeOutput
  1260. *****************************************************************************}
  1261. constructor TZXSpectrumIntelHexExeOutput.create;
  1262. begin
  1263. inherited create;
  1264. { The ZX Spectrum RTL switches to interrupt mode 2, and install an
  1265. interrupt handler + table, starting at address $FDFD, so we must limit
  1266. program size to $FDFC }
  1267. MaxMemPos:=$FDFC;
  1268. end;
  1269. {*****************************************************************************
  1270. Initialize
  1271. *****************************************************************************}
  1272. const
  1273. as_z80_rel_info : tasminfo =
  1274. (
  1275. id : as_z80_rel;
  1276. idtxt : 'REL';
  1277. asmbin : '';
  1278. asmcmd : '';
  1279. supported_targets : [system_z80_embedded,system_z80_zxspectrum,system_z80_msxdos];
  1280. flags : [af_outputbinary,af_smartlink_sections];
  1281. labelprefix : '..@';
  1282. labelmaxlen : 79;
  1283. comment : '; ';
  1284. dollarsign: '$';
  1285. );
  1286. initialization
  1287. RegisterAssembler(as_z80_rel_info,TRelAssembler);
  1288. end.