ogrel.pas 46 KB

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