ogrel.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. { TRelObjData }
  33. TRelObjData = class(TObjData)
  34. public
  35. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  36. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  37. end;
  38. { TRelObjOutput }
  39. TRelObjOutput = class(tObjOutput)
  40. private
  41. procedure writeString(const S: ansistring);
  42. procedure writeLine(const S: ansistring);
  43. protected
  44. function writeData(Data:TObjData):boolean;override;
  45. public
  46. constructor create(AWriter:TObjectWriter);override;
  47. end;
  48. { TRelAssembler }
  49. TRelAssembler = class(tinternalassembler)
  50. constructor create(info: pasminfo; smart:boolean);override;
  51. end;
  52. implementation
  53. uses
  54. SysUtils,
  55. cutils,verbose,globals,
  56. fmodule,aasmtai,aasmdata,
  57. ogmap,
  58. version
  59. ;
  60. function tohex(q: qword): string;
  61. begin
  62. result:=HexStr(q,16);
  63. while (Length(result)>1) and (result[1]='0') do
  64. delete(result,1,1);
  65. end;
  66. {*****************************************************************************
  67. TRelObjData
  68. *****************************************************************************}
  69. function TRelObjData.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
  70. const
  71. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  72. '_CODE',
  73. '_DATA',
  74. '_DATA',
  75. '.rodata',
  76. '.bss',
  77. '.threadvar',
  78. '.pdata',
  79. '', { stubs }
  80. '__DATA,__nl_symbol_ptr',
  81. '__DATA,__la_symbol_ptr',
  82. '__DATA,__mod_init_func',
  83. '__DATA,__mod_term_func',
  84. '.stab',
  85. '.stabstr',
  86. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  87. '.eh_frame',
  88. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges',
  89. '.fpc',
  90. '.toc',
  91. '.init',
  92. '.fini',
  93. '.objc_class',
  94. '.objc_meta_class',
  95. '.objc_cat_cls_meth',
  96. '.objc_cat_inst_meth',
  97. '.objc_protocol',
  98. '.objc_string_object',
  99. '.objc_cls_meth',
  100. '.objc_inst_meth',
  101. '.objc_cls_refs',
  102. '.objc_message_refs',
  103. '.objc_symbols',
  104. '.objc_category',
  105. '.objc_class_vars',
  106. '.objc_instance_vars',
  107. '.objc_module_info',
  108. '.objc_class_names',
  109. '.objc_meth_var_types',
  110. '.objc_meth_var_names',
  111. '.objc_selector_strs',
  112. '.objc_protocol_ext',
  113. '.objc_class_ext',
  114. '.objc_property',
  115. '.objc_image_info',
  116. '.objc_cstring_object',
  117. '.objc_sel_fixup',
  118. '__DATA,__objc_data',
  119. '__DATA,__objc_const',
  120. '.objc_superrefs',
  121. '__DATA, __datacoal_nt,coalesced',
  122. '.objc_classlist',
  123. '.objc_nlclasslist',
  124. '.objc_catlist',
  125. '.obcj_nlcatlist',
  126. '.objc_protolist',
  127. '.stack',
  128. '.heap',
  129. '.gcc_except_table',
  130. '.ARM.attributes'
  131. );
  132. begin
  133. result:=secnames[atype];
  134. end;
  135. procedure TRelObjData.writeReloc(Data: TRelocDataInt; len: aword; p: TObjSymbol; Reloctype: TObjRelocationType);
  136. var
  137. bytes: array [0..1] of Byte;
  138. symaddr: QWord;
  139. objreloc: TObjRelocation;
  140. begin
  141. if CurrObjSec=nil then
  142. internalerror(200403072);
  143. objreloc:=nil;
  144. if assigned(p) then
  145. begin
  146. { real address of the symbol }
  147. symaddr:=p.address;
  148. if p.bind=AB_EXTERNAL then
  149. begin
  150. objreloc:=TObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  151. CurrObjSec.ObjRelocations.Add(objreloc);
  152. end
  153. { relative relocations within the same section can be calculated directly,
  154. without the need to emit a relocation entry }
  155. else if (p.objsection=CurrObjSec) and
  156. (p.bind<>AB_COMMON) and
  157. (Reloctype=RELOC_RELATIVE) then
  158. begin
  159. data:=data+symaddr-len-CurrObjSec.Size;
  160. end
  161. else
  162. begin
  163. objreloc:=TObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,Reloctype);
  164. CurrObjSec.ObjRelocations.Add(objreloc);
  165. end;
  166. end;
  167. case len of
  168. 2:
  169. begin
  170. bytes[0]:=Byte(Data);
  171. bytes[1]:=Byte(Data shr 8);
  172. writebytes(bytes,2);
  173. end;
  174. 1:
  175. begin
  176. bytes[0]:=Byte(Data);
  177. writebytes(bytes,1);
  178. end;
  179. else
  180. internalerror(2020050423);
  181. end;
  182. end;
  183. {*****************************************************************************
  184. TRelObjOutput
  185. *****************************************************************************}
  186. procedure TRelObjOutput.writeString(const S: ansistring);
  187. begin
  188. FWriter.write(S[1],Length(S));
  189. end;
  190. procedure TRelObjOutput.writeLine(const S: ansistring);
  191. begin
  192. writeString(S+#10)
  193. end;
  194. function TRelObjOutput.writeData(Data: TObjData): boolean;
  195. var
  196. global_symbols_count: Integer = 0;
  197. secidx, idx, i, j: Integer;
  198. objsym: TObjSymbol;
  199. objsec: TObjSection;
  200. begin
  201. global_symbols_count:=0;
  202. for i:=0 to Data.ObjSymbolList.Count-1 do
  203. begin
  204. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  205. if objsym.bind in [AB_EXTERNAL,AB_GLOBAL] then
  206. Inc(global_symbols_count);
  207. end;
  208. writeLine('XL2');
  209. writeLine('H '+tohex(data.ObjSectionList.Count)+' areas '+tohex(global_symbols_count)+' global symbols');
  210. idx:=0;
  211. for i:=0 to Data.ObjSymbolList.Count-1 do
  212. begin
  213. objsym:=TObjSymbol(Data.ObjSymbolList[i]);
  214. if objsym.bind=AB_EXTERNAL then
  215. begin
  216. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Ref0000');
  217. objsym.symidx:=idx;
  218. Inc(idx);
  219. end;
  220. end;
  221. secidx:=0;
  222. for i:=0 to Data.ObjSectionList.Count-1 do
  223. begin
  224. objsec:=TObjSection(Data.ObjSectionList[i]);
  225. writeLine('A '+objsec.Name+' size '+tohex(objsec.Size)+' flags 0 addr 0');
  226. objsec.SecSymIdx:=secidx;
  227. Inc(secidx);
  228. for j:=0 to Data.ObjSymbolList.Count-1 do
  229. begin
  230. objsym:=TObjSymbol(Data.ObjSymbolList[j]);
  231. if (objsym.bind=AB_GLOBAL) and (objsym.objsection=objsec) then
  232. begin
  233. writeLine('S '+ApplyAsmSymbolRestrictions(objsym.Name)+' Def'+HexStr(objsym.offset,4));
  234. objsym.symidx:=idx;
  235. Inc(idx);
  236. end;
  237. end;
  238. end;
  239. result:=true;
  240. end;
  241. constructor TRelObjOutput.create(AWriter: TObjectWriter);
  242. begin
  243. inherited;
  244. cobjdata:=TRelObjData;
  245. end;
  246. {*****************************************************************************
  247. TRelAssembler
  248. *****************************************************************************}
  249. constructor TRelAssembler.create(info: pasminfo; smart: boolean);
  250. begin
  251. inherited;
  252. CObjOutput:=TRelObjOutput;
  253. end;
  254. {*****************************************************************************
  255. Initialize
  256. *****************************************************************************}
  257. const
  258. as_z80_rel_info : tasminfo =
  259. (
  260. id : as_z80_rel;
  261. idtxt : 'REL';
  262. asmbin : '';
  263. asmcmd : '';
  264. supported_targets : [system_z80_embedded,system_z80_zxspectrum];
  265. flags : [af_outputbinary,af_smartlink_sections];
  266. labelprefix : '..@';
  267. labelmaxlen : 79;
  268. comment : '; ';
  269. dollarsign: '$';
  270. );
  271. initialization
  272. RegisterAssembler(as_z80_rel_info,TRelAssembler);
  273. end.