ogrel.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  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. protected
  102. function writeData:boolean;override;
  103. procedure DoRelocationFixup(objsec:TObjSection);override;
  104. public
  105. constructor create;override;
  106. end;
  107. implementation
  108. uses
  109. SysUtils,
  110. cutils,verbose,globals,
  111. fmodule,aasmtai,aasmdata,
  112. ogmap,owar,
  113. version
  114. ;
  115. function tohex(q: qword): string;
  116. begin
  117. result:=HexStr(q,16);
  118. while (Length(result)>1) and (result[1]='0') do
  119. delete(result,1,1);
  120. end;
  121. {*****************************************************************************
  122. TRelRelocation
  123. *****************************************************************************}
  124. function TRelRelocation.GetSecOrSymIdx: longint;
  125. begin
  126. if assigned(symbol) then
  127. result:=symbol.symidx
  128. else if assigned(objsection) then
  129. result:=objsection.SecSymIdx
  130. else
  131. internalerror(2020050502);
  132. end;
  133. constructor TRelRelocation.CreateSymbol(ADataOffset: TObjSectionOfs; s: TObjSymbol; Atyp: TObjRelocationType);
  134. begin
  135. inherited;
  136. case Atyp of
  137. RELOC_ABSOLUTE_HI8:
  138. begin
  139. size:=1;
  140. RelFlags:=[rrfSymbol,rrfByte,rrfTwoByteObjectFormatForByteData,rrfMSBWith2ByteMode];
  141. end;
  142. RELOC_ABSOLUTE_LO8:
  143. begin
  144. size:=1;
  145. RelFlags:=[rrfSymbol,rrfByte,rrfTwoByteObjectFormatForByteData];
  146. end;
  147. RELOC_ABSOLUTE:
  148. begin
  149. size:=2;
  150. RelFlags:=[rrfSymbol];
  151. end;
  152. else
  153. internalerror(2020050601);
  154. end;
  155. end;
  156. constructor TRelRelocation.CreateSection(ADataOffset: TObjSectionOfs; aobjsec: TObjSection; Atyp: TObjRelocationType);
  157. begin
  158. inherited;
  159. case Atyp of
  160. RELOC_ABSOLUTE_HI8:
  161. begin
  162. size:=1;
  163. RelFlags:=[rrfByte,rrfTwoByteObjectFormatForByteData,rrfMSBWith2ByteMode];
  164. end;
  165. RELOC_ABSOLUTE_LO8:
  166. begin
  167. size:=1;
  168. RelFlags:=[rrfByte,rrfTwoByteObjectFormatForByteData];
  169. end;
  170. RELOC_ABSOLUTE:
  171. begin
  172. size:=2;
  173. RelFlags:=[];
  174. end;
  175. else
  176. internalerror(2020050601);
  177. end;
  178. end;
  179. function TRelRelocation.EncodeFlags: string;
  180. var
  181. FlagsWord: Word;
  182. begin
  183. FlagsWord:=0;
  184. if rrfByte in RelFlags then
  185. Inc(FlagsWord,1);
  186. if rrfSymbol in RelFlags then
  187. Inc(FlagsWord,2);
  188. if rrfPcRelative in RelFlags then
  189. Inc(FlagsWord,4);
  190. if rrfTwoByteObjectFormatForByteData in RelFlags then
  191. Inc(FlagsWord,8);
  192. if rrfUnsignedByteData in RelFlags then
  193. Inc(FlagsWord,16);
  194. if rrfPage0Reference in RelFlags then
  195. Inc(FlagsWord,32);
  196. if rrfPageNNNReference in RelFlags then
  197. Inc(FlagsWord,64);
  198. if rrfMSBWith2ByteMode in RelFlags then
  199. Inc(FlagsWord,128);
  200. if rrfThreeByteObjectFormatForByteData in RelFlags then
  201. Inc(FlagsWord,256);
  202. if rrfRealMSBForThreeByteMode in RelFlags then
  203. Inc(FlagsWord,512);
  204. if rrfReserved10 in RelFlags then
  205. Inc(FlagsWord,1024);
  206. if rrfReserved11 in RelFlags then
  207. Inc(FlagsWord,2048);
  208. if (FlagsWord<=255) and ((FlagsWord and $F0)<>$F0) then
  209. Result:=HexStr(FlagsWord,2)
  210. else
  211. Result:=HexStr($F0 or Byte(FlagsWord shr 8),2)+' '+HexStr(Byte(FlagsWord),2);
  212. end;
  213. {*****************************************************************************
  214. TRelObjData
  215. *****************************************************************************}
  216. function TRelObjData.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
  217. const
  218. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  219. '_CODE',
  220. '_DATA',
  221. '_DATA',
  222. '.rodata',
  223. '.bss',
  224. '.threadvar',
  225. '.pdata',
  226. '', { stubs }
  227. '__DATA,__nl_symbol_ptr',
  228. '__DATA,__la_symbol_ptr',
  229. '__DATA,__mod_init_func',
  230. '__DATA,__mod_term_func',
  231. '.stab',
  232. '.stabstr',
  233. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  234. '.eh_frame',
  235. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  236. '.fpc',
  237. '.toc',
  238. '.init',
  239. '.fini',
  240. '.objc_class',
  241. '.objc_meta_class',
  242. '.objc_cat_cls_meth',
  243. '.objc_cat_inst_meth',
  244. '.objc_protocol',
  245. '.objc_string_object',
  246. '.objc_cls_meth',
  247. '.objc_inst_meth',
  248. '.objc_cls_refs',
  249. '.objc_message_refs',
  250. '.objc_symbols',
  251. '.objc_category',
  252. '.objc_class_vars',
  253. '.objc_instance_vars',
  254. '.objc_module_info',
  255. '.objc_class_names',
  256. '.objc_meth_var_types',
  257. '.objc_meth_var_names',
  258. '.objc_selector_strs',
  259. '.objc_protocol_ext',
  260. '.objc_class_ext',
  261. '.objc_property',
  262. '.objc_image_info',
  263. '.objc_cstring_object',
  264. '.objc_sel_fixup',
  265. '__DATA,__objc_data',
  266. '__DATA,__objc_const',
  267. '.objc_superrefs',
  268. '__DATA, __datacoal_nt,coalesced',
  269. '.objc_classlist',
  270. '.objc_nlclasslist',
  271. '.objc_catlist',
  272. '.obcj_nlcatlist',
  273. '.objc_protolist',
  274. '.stack',
  275. '.heap',
  276. '.gcc_except_table',
  277. '.ARM.attributes'
  278. );
  279. begin
  280. result:=secnames[atype];
  281. end;
  282. function TRelObjData.sectiontype2align(atype:TAsmSectiontype):longint;
  283. begin
  284. result:=1;
  285. end;
  286. procedure TRelObjData.writeReloc(Data: TRelocDataInt; len: aword; p: TObjSymbol; Reloctype: TObjRelocationType);
  287. var
  288. bytes: array [0..1] of Byte;
  289. symaddr: QWord;
  290. objreloc: TRelRelocation;
  291. begin
  292. if CurrObjSec=nil then
  293. internalerror(200403072);
  294. objreloc:=nil;
  295. if assigned(p) then
  296. begin
  297. { real address of the symbol }
  298. symaddr:=p.address;
  299. if p.bind=AB_EXTERNAL then
  300. begin
  301. objreloc:=TRelRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  302. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  303. objreloc.HiByte:=Byte(Data shr 8);
  304. CurrObjSec.ObjRelocations.Add(objreloc);
  305. end
  306. { relative relocations within the same section can be calculated directly,
  307. without the need to emit a relocation entry }
  308. else if (p.objsection=CurrObjSec) and
  309. (p.bind<>AB_COMMON) and
  310. (Reloctype=RELOC_RELATIVE) then
  311. begin
  312. data:=data+symaddr-len-CurrObjSec.Size;
  313. end
  314. else
  315. begin
  316. objreloc:=TRelRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  317. inc(data,symaddr);
  318. if Reloctype in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  319. objreloc.HiByte:=Byte(Data shr 8);
  320. CurrObjSec.ObjRelocations.Add(objreloc);
  321. end;
  322. end;
  323. case len of
  324. 2:
  325. begin
  326. bytes[0]:=Byte(Data);
  327. bytes[1]:=Byte(Data shr 8);
  328. writebytes(bytes,2);
  329. end;
  330. 1:
  331. begin
  332. bytes[0]:=Byte(Data);
  333. writebytes(bytes,1);
  334. end;
  335. else
  336. internalerror(2020050423);
  337. end;
  338. end;
  339. {*****************************************************************************
  340. TRelObjOutput
  341. *****************************************************************************}
  342. procedure TRelObjOutput.writeString(const S: ansistring);
  343. begin
  344. FWriter.write(S[1],Length(S));
  345. end;
  346. procedure TRelObjOutput.writeLine(const S: ansistring);
  347. begin
  348. writeString(S+#10)
  349. end;
  350. procedure TRelObjOutput.WriteAreaContentAndRelocations(sec: TObjSection);
  351. const
  352. MaxChunkSize={14}7;
  353. var
  354. ChunkStart,ChunkLen, i: LongWord;
  355. ChunkFixupStart,ChunkFixupEnd, j, st_ofs: Integer;
  356. st,sr: ansistring;
  357. buf: array [0..MaxChunkSize-1] of Byte;
  358. reloc: TRelRelocation;
  359. begin
  360. if (oso_data in sec.SecOptions) and (sec.Data=nil) then
  361. internalerror(200403073);
  362. if assigned(sec.data) then
  363. sec.data.seek(0);
  364. ChunkFixupStart:=0;
  365. ChunkFixupEnd:=-1;
  366. ChunkStart:=0;
  367. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  368. while ChunkLen>0 do
  369. begin
  370. { find last fixup in the chunk }
  371. while (ChunkFixupEnd<(sec.ObjRelocations.Count-1)) and
  372. (TRelRelocation(sec.ObjRelocations[ChunkFixupEnd+1]).DataOffset<(ChunkStart+ChunkLen)) do
  373. inc(ChunkFixupEnd);
  374. { check if last chunk is crossing the chunk boundary, and trim ChunkLen if necessary }
  375. if (ChunkFixupEnd>=ChunkFixupStart) and
  376. ((TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset+
  377. TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).size)>(ChunkStart+ChunkLen)) then
  378. begin
  379. ChunkLen:=TRelRelocation(sec.ObjRelocations[ChunkFixupEnd]).DataOffset-ChunkStart;
  380. Dec(ChunkFixupEnd);
  381. end;
  382. if ChunkLen>SizeOf(buf) then
  383. internalerror(2020050501);
  384. st:='T '+HexStr(Byte(ChunkStart),2)+' '+HexStr(Byte(ChunkStart shr 8),2);
  385. sr:='R 00 00 '+HexStr(Byte(sec.SecSymIdx),2)+' '+HexStr(Byte(sec.SecSymIdx shr 8),2);
  386. if assigned(sec.Data) then
  387. sec.Data.read(buf,ChunkLen)
  388. else
  389. FillChar(buf,ChunkLen,0);
  390. st_ofs:=1;
  391. { relocations present in the current chunk? }
  392. if ChunkFixupEnd>=ChunkFixupStart then
  393. begin
  394. j:=ChunkFixupStart;
  395. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  396. end
  397. else
  398. begin
  399. j:=-1;
  400. reloc:=nil;
  401. end;
  402. for i:=0 to ChunkLen-1 do
  403. begin
  404. st:=st+' '+HexStr(buf[i],2);
  405. Inc(st_ofs);
  406. if assigned(reloc) then
  407. begin
  408. { advance to the current relocation }
  409. while (reloc.DataOffset<(ChunkStart+i)) and (j<ChunkFixupEnd) do
  410. begin
  411. Inc(j);
  412. reloc:=TRelRelocation(sec.ObjRelocations[j]);
  413. end;
  414. { is there a relocation at the current position? }
  415. if reloc.DataOffset=(ChunkStart+i) then
  416. begin
  417. sr:=sr+' '+reloc.EncodeFlags+' '+HexStr(st_ofs,2)+' '+HexStr(Byte(reloc.SecOrSymIdx),2)+' '+HexStr(Byte(reloc.SecOrSymIdx shr 8),2);
  418. if reloc.typ in [RELOC_ABSOLUTE_HI8,RELOC_ABSOLUTE_LO8] then
  419. begin
  420. st:=st+' '+HexStr(reloc.HiByte,2);
  421. Inc(st_ofs);
  422. end;
  423. end;
  424. end;
  425. end;
  426. writeLine(st);
  427. writeLine(sr);
  428. { prepare next chunk }
  429. Inc(ChunkStart, ChunkLen);
  430. ChunkLen:=Min(MaxChunkSize, sec.size-ChunkStart);
  431. ChunkFixupStart:=ChunkFixupEnd+1;
  432. end;
  433. end;
  434. function TRelObjOutput.writeData(Data: TObjData): boolean;
  435. var
  436. global_symbols_count: Integer = 0;
  437. secidx, idx, i, j: Integer;
  438. objsym: TObjSymbol;
  439. objsec: TObjSection;
  440. begin
  441. global_symbols_count:=0;
  442. for i:=0 to Data.ObjSymbolList.Count-1 do
  443. begin
  444. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  445. if objsym.bind in [AB_EXTERNAL,AB_GLOBAL] then
  446. Inc(global_symbols_count);
  447. end;
  448. writeLine('XL2');
  449. writeLine('H '+tohex(data.ObjSectionList.Count)+' areas '+tohex(global_symbols_count)+' global symbols');
  450. idx:=0;
  451. for i:=0 to Data.ObjSymbolList.Count-1 do
  452. begin
  453. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  454. if objsym.bind=AB_EXTERNAL then
  455. begin
  456. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Ref0000');
  457. objsym.symidx:=idx;
  458. Inc(idx);
  459. end;
  460. end;
  461. secidx:=0;
  462. for i:=0 to Data.ObjSectionList.Count-1 do
  463. begin
  464. objsec:=TObjSection(Data.ObjSectionList[i]);
  465. writeLine('A '+objsec.Name+' size '+tohex(objsec.Size)+' flags 0 addr 0');
  466. objsec.SecSymIdx:=secidx;
  467. Inc(secidx);
  468. for j:=0 to Data.ObjSymbolList.Count-1 do
  469. begin
  470. objsym:=TObjSymbol(Data.ObjSymbolList[j]);
  471. if (objsym.bind=AB_GLOBAL) and (objsym.objsection=objsec) then
  472. begin
  473. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Def'+HexStr(objsym.offset,4));
  474. objsym.symidx:=idx;
  475. Inc(idx);
  476. end;
  477. end;
  478. end;
  479. for i:=0 to Data.ObjSectionList.Count-1 do
  480. begin
  481. objsec:=TObjSection(Data.ObjSectionList[i]);
  482. WriteAreaContentAndRelocations(objsec);
  483. end;
  484. result:=true;
  485. end;
  486. constructor TRelObjOutput.create(AWriter: TObjectWriter);
  487. begin
  488. inherited;
  489. cobjdata:=TRelObjData;
  490. end;
  491. {*****************************************************************************
  492. TRelAssembler
  493. *****************************************************************************}
  494. constructor TRelAssembler.create(info: pasminfo; smart: boolean);
  495. begin
  496. inherited;
  497. CObjOutput:=TRelObjOutput;
  498. CInternalAr:=tarobjectwriter;
  499. end;
  500. {*****************************************************************************
  501. TRelObjInput
  502. *****************************************************************************}
  503. function TRelObjInput.FillBuf: boolean;
  504. begin
  505. FBufPos:=0;
  506. FBufSize:=min(FReader.size-FReader.Pos,MaxBufSize);
  507. if FBufSize>0 then
  508. result:=FReader.read(FBuf,FBufSize)
  509. else
  510. result:=true;
  511. end;
  512. function TRelObjInput.AtEndOfBuf: boolean;
  513. begin
  514. result:=FBufPos=FBufSize;
  515. end;
  516. function TRelObjInput.AtEoF: boolean;
  517. begin
  518. result:=AtEndOfBuf and (FReader.Pos=FReader.size);
  519. end;
  520. function TRelObjInput.ReadChar(out c: char): boolean;
  521. begin
  522. c:=#0;
  523. if AtEndOfBuf then
  524. begin
  525. result:=FillBuf;
  526. if not result then
  527. exit;
  528. end;
  529. if not AtEndOfBuf then
  530. begin
  531. c:=FBuf[FBufPos];
  532. Inc(FBufPos);
  533. result:=true;
  534. end
  535. else
  536. result:=false;
  537. end;
  538. function TRelObjInput.PeekChar(out c: char): boolean;
  539. begin
  540. c:=#0;
  541. if AtEndOfBuf then
  542. begin
  543. result:=FillBuf;
  544. if not result then
  545. exit;
  546. end;
  547. if not AtEndOfBuf then
  548. begin
  549. c:=FBuf[FBufPos];
  550. result:=true;
  551. end
  552. else
  553. result:=false;
  554. end;
  555. function TRelObjInput.ReadLine(out s: string): boolean;
  556. var
  557. c: Char;
  558. begin
  559. s:='';
  560. if AtEoF then
  561. begin
  562. result:=false;
  563. exit;
  564. end;
  565. repeat
  566. if not AtEoF then
  567. begin
  568. if not ReadChar(c) then
  569. begin
  570. result:=false;
  571. exit;
  572. end;
  573. if not (c in [#13,#10]) then
  574. s:=s+c;
  575. end;
  576. until (c in [#13,#10]) or AtEoF;
  577. if (c=#13) and not AtEoF then
  578. begin
  579. if not PeekChar(c) then
  580. begin
  581. result:=false;
  582. exit;
  583. end;
  584. if c=#10 then
  585. begin
  586. if not ReadChar(c) then
  587. begin
  588. result:=false;
  589. exit;
  590. end;
  591. end;
  592. end;
  593. result:=true;
  594. end;
  595. constructor TRelObjInput.create;
  596. begin
  597. inherited create;
  598. cobjdata:=TRelObjData;
  599. FBufSize:=0;
  600. FBufPos:=0;
  601. end;
  602. function TRelObjInput.ReadObjData(AReader: TObjectreader; out Data: TObjData): boolean;
  603. function HandleTR(const T,R: string): boolean;
  604. begin
  605. { todo: implement }
  606. result:=true;
  607. end;
  608. const
  609. GenericRelErrMsg='Error reading REL file';
  610. var
  611. s, AreaName, SymbolName: string;
  612. RecType: Char;
  613. HeaderFound: Boolean=false;
  614. ExpectedAreas,ExpectedSymbols,AreaSize,AreaFlags,AreaAddr,
  615. SymbolOfs: LongInt;
  616. tmpint: SizeInt;
  617. CurrSec: TObjSection=nil;
  618. objsym: TObjSymbol;
  619. LastT: string='';
  620. begin
  621. FReader:=AReader;
  622. InputFileName:=AReader.FileName;
  623. Data:=CObjData.Create(InputFileName);
  624. result:=false;
  625. s:='';
  626. repeat
  627. if AtEoF or not ReadLine(s) then
  628. begin
  629. InputError(GenericRelErrMsg);
  630. exit;
  631. end;
  632. s:=Trim(s);
  633. until s<>'';
  634. if s<>'XL2' then
  635. begin
  636. InputError('Invalid or unsupported REL format identifier');
  637. exit;
  638. end;
  639. while not AtEoF do
  640. begin
  641. if not ReadLine(s) then
  642. begin
  643. InputError(GenericRelErrMsg);
  644. exit;
  645. end;
  646. s:=Trim(s);
  647. if s<>'' then
  648. begin
  649. RecType:=s[1];
  650. if (length(s)<3) or (s[2]<>' ') then
  651. begin
  652. InputError('Invalid or unsupported REL record');
  653. exit;
  654. end;
  655. delete(s,1,2);
  656. case RecType of
  657. 'H': { header }
  658. begin
  659. if HeaderFound then
  660. begin
  661. InputError('Duplicated header');
  662. exit;
  663. end;
  664. HeaderFound:=true;
  665. tmpint:=Pos(' ',s);
  666. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedAreas) then
  667. begin
  668. InputError('Invalid area count in header');
  669. exit;
  670. end;
  671. delete(s,1,tmpint);
  672. if copy(s,1,6)<>'areas ' then
  673. begin
  674. InputError('Invalid header');
  675. exit;
  676. end;
  677. delete(s,1,6);
  678. tmpint:=Pos(' ',s);
  679. if not TryStrToInt('$'+Copy(s,1,tmpint-1),ExpectedSymbols) then
  680. begin
  681. InputError('Invalid symbol count in header');
  682. exit;
  683. end;
  684. delete(s,1,tmpint);
  685. if s<>'global symbols' then
  686. begin
  687. InputError('Invalid header');
  688. exit;
  689. end;
  690. end;
  691. 'M': { module }
  692. begin
  693. { we ignore this for now }
  694. end;
  695. 'S': { symbol }
  696. begin
  697. if not HeaderFound then
  698. begin
  699. InputError('Symbol record encountered before header');
  700. exit;
  701. end;
  702. tmpint:=Pos(' ',s);
  703. if tmpint<=1 then
  704. begin
  705. InputError('Invalid symbol record');
  706. exit;
  707. end;
  708. SymbolName:=copy(s,1,tmpint-1);
  709. delete(s,1,tmpint);
  710. if Length(s)<4 then
  711. begin
  712. InputError('Invalid symbol record');
  713. exit;
  714. end;
  715. if not TryStrToInt('$'+Copy(s,4,Length(s)-4),SymbolOfs) then
  716. begin
  717. InputError('Invalid symbol offset');
  718. exit;
  719. end;
  720. case Copy(s,1,3) of
  721. 'Def':
  722. begin
  723. if CurrSec=nil then
  724. begin
  725. InputError('Public symbol defined outside any area');
  726. exit;
  727. end;
  728. if (SymbolOfs<0) or (SymbolOfs>=CurrSec.Size) then
  729. begin
  730. InputError('Public symbol offset outside the range of the current area');
  731. exit;
  732. end;
  733. objsym:=Data.CreateSymbol(SymbolName);
  734. objsym.bind:=AB_GLOBAL;
  735. objsym.typ:=AT_FUNCTION;
  736. objsym.objsection:=CurrSec;
  737. objsym.offset:=SymbolOfs;
  738. objsym.size:=0;
  739. end;
  740. 'Ref':
  741. begin
  742. if CurrSec<>nil then
  743. begin
  744. InputError('External symbols must be defined before the first area');
  745. exit;
  746. end;
  747. if SymbolOfs<>0 then
  748. begin
  749. InputError('External symbols must be declared with an offset of 0');
  750. exit;
  751. end;
  752. objsym:=Data.CreateSymbol(SymbolName);
  753. objsym.bind:=AB_EXTERNAL;
  754. objsym.typ:=AT_FUNCTION;
  755. objsym.objsection:=nil;
  756. objsym.offset:=0;
  757. objsym.size:=0;
  758. end;
  759. else
  760. begin
  761. InputError('Invalid or unsupported symbol record');
  762. exit;
  763. end;
  764. end;
  765. if Data.ObjSymbolList.Count>ExpectedSymbols then
  766. begin
  767. InputError('Number of symbols exceeds the number, declared in header');
  768. exit;
  769. end;
  770. end;
  771. 'A': { area }
  772. begin
  773. if not HeaderFound then
  774. begin
  775. InputError('Area record encountered before header');
  776. exit;
  777. end;
  778. tmpint:=Pos(' ',s);
  779. if tmpint<=1 then
  780. begin
  781. InputError('Invalid area record');
  782. exit;
  783. end;
  784. AreaName:=copy(s,1,tmpint-1);
  785. delete(s,1,tmpint);
  786. if copy(s,1,5)<>'size ' then
  787. begin
  788. InputError('Invalid area record');
  789. exit;
  790. end;
  791. delete(s,1,5);
  792. tmpint:=Pos(' ',s);
  793. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaSize) then
  794. begin
  795. InputError('Invalid area size');
  796. exit;
  797. end;
  798. delete(s,1,tmpint);
  799. if copy(s,1,6)<>'flags ' then
  800. begin
  801. InputError('Invalid area record');
  802. exit;
  803. end;
  804. delete(s,1,6);
  805. tmpint:=Pos(' ',s);
  806. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaFlags) then
  807. begin
  808. InputError('Invalid area flags');
  809. exit;
  810. end;
  811. delete(s,1,tmpint);
  812. if copy(s,1,5)<>'addr ' then
  813. begin
  814. InputError('Invalid area record');
  815. exit;
  816. end;
  817. delete(s,1,5);
  818. if not TryStrToInt('$'+Copy(s,1,tmpint-1),AreaAddr) then
  819. begin
  820. InputError('Invalid area address');
  821. exit;
  822. end;
  823. if AreaFlags<>0 then
  824. begin
  825. InputError('Unsupported area flags ('+tostr(AreaFlags)+')');
  826. exit;
  827. end;
  828. if AreaAddr<>0 then
  829. begin
  830. InputError('Area address<>0 not supported');
  831. exit;
  832. end;
  833. CurrSec:=Data.createsection(AreaName,1,[],false);
  834. CurrSec.alloc(AreaSize);
  835. if Data.ObjSectionList.Count>ExpectedAreas then
  836. begin
  837. InputError('Number of areas exceeds the number, declared in header');
  838. exit;
  839. end;
  840. end;
  841. 'T': { T line () }
  842. begin
  843. if LastT<>'' then
  844. begin
  845. InputError('T record not followed by R record');
  846. exit;
  847. end;
  848. LastT:=s;
  849. end;
  850. 'R': { R line (relocation information) }
  851. begin
  852. if LastT='' then
  853. begin
  854. InputError('R record without T record');
  855. exit;
  856. end;
  857. if not HandleTR(LastT,s) then
  858. exit;
  859. LastT:='';
  860. end;
  861. 'P': { P line (paging information) }
  862. begin
  863. InputError('P line records are not supported');
  864. exit;
  865. end;
  866. else
  867. begin
  868. InputError('Unsupported REL record type: #'+tostr(Ord(RecType)));
  869. exit;
  870. end;
  871. end;
  872. end;
  873. end;
  874. result:=true;
  875. end;
  876. class function TRelObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  877. var
  878. s: string;
  879. instance: TRelObjInput;
  880. begin
  881. result:=false;
  882. instance:=TRelObjInput.Create;
  883. instance.FReader:=AReader;
  884. with instance do
  885. while not AtEoF do
  886. begin
  887. if not ReadLine(s) then
  888. exit;
  889. s:=Trim(s);
  890. if s<>'' then
  891. begin
  892. result:=s='XL2';
  893. break;
  894. end;
  895. end;
  896. instance.Free;
  897. end;
  898. {*****************************************************************************
  899. TIntelHexExeOutput
  900. *****************************************************************************}
  901. function TIntelHexExeOutput.writeData: boolean;
  902. begin
  903. result:=false;
  904. end;
  905. procedure TIntelHexExeOutput.DoRelocationFixup(objsec: TObjSection);
  906. begin
  907. end;
  908. constructor TIntelHexExeOutput.create;
  909. begin
  910. inherited create;
  911. CObjData:=TRelObjData;
  912. MaxMemPos:=$FFFF;
  913. end;
  914. {*****************************************************************************
  915. Initialize
  916. *****************************************************************************}
  917. const
  918. as_z80_rel_info : tasminfo =
  919. (
  920. id : as_z80_rel;
  921. idtxt : 'REL';
  922. asmbin : '';
  923. asmcmd : '';
  924. supported_targets : [system_z80_embedded,system_z80_zxspectrum];
  925. flags : [af_outputbinary,af_smartlink_sections];
  926. labelprefix : '..@';
  927. labelmaxlen : 79;
  928. comment : '; ';
  929. dollarsign: '$';
  930. );
  931. initialization
  932. RegisterAssembler(as_z80_rel_info,TRelAssembler);
  933. end.