ogbase.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. Contains the base stuff for binary object file writers
  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 ogbase;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. {$ifdef Delphi}
  23. sysutils,
  24. dmisc,
  25. {$else Delphi}
  26. strings,
  27. dos,
  28. {$endif Delphi}
  29. { common }
  30. cobjects,
  31. { targets }
  32. systems,
  33. { outputwriters }
  34. owbase,owar,
  35. { assembler }
  36. cpubase,aasm;
  37. type
  38. tsecsize = array[tsection] of longint;
  39. relative_type = (relative_false,relative_true,relative_rva);
  40. poutputreloc = ^toutputreloc;
  41. toutputreloc = packed record
  42. next : poutputreloc;
  43. address : longint;
  44. symbol : pasmsymbol;
  45. section : tsection; { only used if symbol=nil }
  46. typ : relative_type;
  47. end;
  48. poutputsymbol = ^toutputsymbol;
  49. toutputsymbol = packed record
  50. namestr : string[8]; { namestr or nameidx is used }
  51. nameidx : longint;
  52. section : tsection;
  53. value : longint;
  54. bind : TAsmsymbind;
  55. typ : TAsmsymtype;
  56. size : longint;
  57. end;
  58. poutputsection = ^toutputsection;
  59. toutputsection = object
  60. name : string[32];
  61. secsymidx : longint; { index for the section in symtab }
  62. addralign : longint;
  63. { size of the data and in the file }
  64. data : PDynamicArray;
  65. datasize : longint;
  66. datapos : longint;
  67. { size and position in memory, set by setsectionsize }
  68. memsize,
  69. mempos : longint;
  70. { relocation }
  71. nrelocs : longint;
  72. relochead : POutputReloc;
  73. reloctail : ^POutputReloc;
  74. constructor init(const Aname:string;Aalign:longint;alloconly:boolean);
  75. destructor done;
  76. function write(var d;l:longint):longint;
  77. function writestr(const s:string):longint;
  78. procedure writealign(l:longint);
  79. function aligneddatasize:longint;
  80. procedure alignsection;
  81. procedure alloc(l:longint);
  82. procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  83. procedure addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  84. end;
  85. pobjectalloc = ^tobjectalloc;
  86. tobjectalloc = object
  87. currsec : tsection;
  88. secsize : tsecsize;
  89. constructor init;
  90. destructor done;
  91. procedure setsection(sec:tsection);
  92. function sectionsize:longint;
  93. procedure sectionalloc(l:longint);
  94. procedure sectionalign(l:longint);
  95. procedure staballoc(p:pchar);
  96. procedure resetsections;
  97. end;
  98. pobjectoutput = ^tobjectoutput;
  99. tobjectoutput = object
  100. writer : pobjectwriter;
  101. path : pathstr;
  102. ObjFile : string;
  103. { smartlinking }
  104. objsmart : boolean;
  105. place : tcutplace;
  106. SmartFilesCount,
  107. SmartHeaderCount : longint;
  108. { section }
  109. currsec : tsection;
  110. sects : array[TSection] of POutputSection;
  111. constructor init(smart:boolean);
  112. destructor done;virtual;
  113. { Writing }
  114. procedure NextSmartName;
  115. procedure initwriting(Aplace:tcutplace);virtual;
  116. procedure donewriting;virtual;
  117. procedure createsection(sec:tsection);virtual;
  118. procedure defaultsection(sec:tsection);
  119. function sectionsize(s:tsection):longint;
  120. procedure setsectionsizes(var s:tsecsize);virtual;
  121. procedure alloc(len:longint);
  122. procedure allocalign(len:longint);
  123. procedure writebytes(var data;len:longint);
  124. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  125. procedure writesymbol(p:pasmsymbol);virtual;
  126. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  127. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  128. nidx,nother,line:longint;reloc:boolean);virtual;
  129. end;
  130. var
  131. objectalloc : pobjectalloc;
  132. objectoutput : pobjectoutput;
  133. implementation
  134. uses
  135. comphook,
  136. cutils,globtype,globals,verbose,fmodule;
  137. {****************************************************************************
  138. tobjectalloc
  139. ****************************************************************************}
  140. constructor tobjectalloc.init;
  141. begin
  142. end;
  143. destructor tobjectalloc.done;
  144. begin
  145. end;
  146. procedure tobjectalloc.setsection(sec:tsection);
  147. begin
  148. currsec:=sec;
  149. end;
  150. procedure tobjectalloc.resetsections;
  151. begin
  152. FillChar(secsize,sizeof(secsize),0);
  153. end;
  154. procedure tobjectalloc.sectionalloc(l:longint);
  155. begin
  156. inc(secsize[currsec],l);
  157. end;
  158. procedure tobjectalloc.sectionalign(l:longint);
  159. begin
  160. if (secsize[currsec] mod l)<>0 then
  161. inc(secsize[currsec],l-(secsize[currsec] mod l));
  162. end;
  163. procedure tobjectalloc.staballoc(p:pchar);
  164. begin
  165. inc(secsize[sec_stab]);
  166. if assigned(p) and (p[0]<>#0) then
  167. inc(secsize[sec_stabstr],strlen(p)+1);
  168. end;
  169. function tobjectalloc.sectionsize:longint;
  170. begin
  171. sectionsize:=secsize[currsec];
  172. end;
  173. {****************************************************************************
  174. TSectionOutput
  175. ****************************************************************************}
  176. constructor toutputsection.init(const Aname:string;Aalign:longint;alloconly:boolean);
  177. begin
  178. name:=Aname;
  179. secsymidx:=0;
  180. addralign:=Aalign;
  181. { data }
  182. datasize:=0;
  183. datapos:=0;
  184. if alloconly then
  185. data:=nil
  186. else
  187. new(Data,Init(8192));
  188. { position }
  189. mempos:=0;
  190. memsize:=0;
  191. { relocation }
  192. NRelocs:=0;
  193. relocHead:=nil;
  194. relocTail:=@relocHead;
  195. end;
  196. destructor toutputsection.done;
  197. begin
  198. if assigned(Data) then
  199. dispose(Data,done);
  200. end;
  201. function toutputsection.write(var d;l:longint):longint;
  202. begin
  203. write:=datasize;
  204. if not assigned(Data) then
  205. Internalerror(3334441);
  206. Data^.write(d,l);
  207. inc(datasize,l);
  208. end;
  209. function toutputsection.writestr(const s:string):longint;
  210. begin
  211. writestr:=datasize;
  212. if not assigned(Data) then
  213. Internalerror(3334441);
  214. Data^.write(s[1],length(s));
  215. inc(datasize,length(s));
  216. end;
  217. procedure toutputsection.writealign(l:longint);
  218. var
  219. i : longint;
  220. empty : array[0..63] of char;
  221. begin
  222. { no alignment needed for 0 or 1 }
  223. if l<=1 then
  224. exit;
  225. i:=datasize mod l;
  226. if i>0 then
  227. begin
  228. if assigned(data) then
  229. begin
  230. fillchar(empty,sizeof(empty),0);
  231. data^.write(empty,l-i);
  232. end;
  233. inc(datasize,l-i);
  234. end;
  235. end;
  236. function toutputsection.aligneddatasize:longint;
  237. begin
  238. aligneddatasize:=align(datasize,addralign);
  239. end;
  240. procedure toutputsection.alignsection;
  241. begin
  242. writealign(addralign);
  243. end;
  244. procedure toutputsection.alloc(l:longint);
  245. begin
  246. if assigned(Data) then
  247. Internalerror(3334442);
  248. inc(datasize,l);
  249. end;
  250. procedure toutputsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  251. var
  252. r : POutputReloc;
  253. begin
  254. new(r);
  255. reloctail^:=r;
  256. reloctail:=@r^.next;
  257. r^.next:=nil;
  258. r^.address:=ofs;
  259. r^.symbol:=p;
  260. r^.section:=sec_none;
  261. r^.typ:=relative;
  262. inc(nrelocs);
  263. end;
  264. procedure toutputsection.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  265. var
  266. r : POutputReloc;
  267. begin
  268. new(r);
  269. reloctail^:=r;
  270. reloctail:=@r^.next;
  271. r^.next:=nil;
  272. r^.address:=ofs;
  273. r^.symbol:=nil;
  274. r^.section:=sec;
  275. r^.typ:=relative;
  276. inc(nrelocs);
  277. end;
  278. {****************************************************************************
  279. tobjectoutput
  280. ****************************************************************************}
  281. constructor tobjectoutput.init(smart:boolean);
  282. begin
  283. SmartFilesCount:=0;
  284. SmartHeaderCount:=0;
  285. objsmart:=smart;
  286. objfile:=current_module^.objfilename^;
  287. { Which path will be used ? }
  288. if objsmart and
  289. (cs_asm_leave in aktglobalswitches) then
  290. begin
  291. path:=current_module^.path^+FixFileName(current_module^.modulename^)+target_info.smartext;
  292. {$I-}
  293. mkdir(path);
  294. {$I+}
  295. if ioresult<>0 then;
  296. path:=FixPath(path,false);
  297. end
  298. else
  299. path:=current_module^.path^;
  300. { init writer }
  301. if objsmart and
  302. not(cs_asm_leave in aktglobalswitches) then writer:=New(parobjectwriter,Init(current_module^.staticlibfilename^))
  303. else
  304. writer:=New(pobjectwriter,Init);
  305. end;
  306. destructor tobjectoutput.done;
  307. begin
  308. Dispose(writer,done);
  309. end;
  310. procedure tobjectoutput.NextSmartName;
  311. var
  312. s : string;
  313. begin
  314. inc(SmartFilesCount);
  315. if SmartFilesCount>999999 then
  316. Message(asmw_f_too_many_asm_files);
  317. if (cs_asm_leave in aktglobalswitches) then
  318. s:=current_module^.asmprefix^
  319. else
  320. s:=current_module^.modulename^;
  321. case place of
  322. cut_begin :
  323. begin
  324. inc(SmartHeaderCount);
  325. s:=s+tostr(SmartHeaderCount)+'h';
  326. end;
  327. cut_normal :
  328. s:=s+tostr(SmartHeaderCount)+'s';
  329. cut_end :
  330. s:=s+tostr(SmartHeaderCount)+'t';
  331. end;
  332. ObjFile:=FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  333. end;
  334. procedure tobjectoutput.initwriting(Aplace:tcutplace);
  335. begin
  336. place:=Aplace;
  337. { open the writer }
  338. if objsmart then
  339. NextSmartName;
  340. writer^.create(objfile);
  341. { reset }
  342. FillChar(Sects,sizeof(Sects),0);
  343. end;
  344. procedure tobjectoutput.donewriting;
  345. var
  346. sec : tsection;
  347. begin
  348. { free memory }
  349. for sec:=low(tsection) to high(tsection) do
  350. if assigned(sects[sec]) then
  351. dispose(sects[sec],done);
  352. { close the writer }
  353. writer^.close;
  354. end;
  355. procedure tobjectoutput.createsection(sec:tsection);
  356. begin
  357. sects[sec]:=new(poutputsection,init(target_asm.secnames[sec],1,(sec=sec_bss)));
  358. end;
  359. function tobjectoutput.sectionsize(s:tsection):longint;
  360. begin
  361. if assigned(sects[s]) then
  362. sectionsize:=sects[s]^.datasize
  363. else
  364. sectionsize:=0;
  365. end;
  366. procedure tobjectoutput.setsectionsizes(var s:tsecsize);
  367. begin
  368. end;
  369. procedure tobjectoutput.defaultsection(sec:tsection);
  370. begin
  371. currsec:=sec;
  372. end;
  373. procedure tobjectoutput.writebytes(var data;len:longint);
  374. begin
  375. if not assigned(sects[currsec]) then
  376. createsection(currsec);
  377. sects[currsec]^.write(data,len);
  378. end;
  379. procedure tobjectoutput.alloc(len:longint);
  380. begin
  381. if not assigned(sects[currsec]) then
  382. createsection(currsec);
  383. sects[currsec]^.alloc(len);
  384. end;
  385. procedure tobjectoutput.allocalign(len:longint);
  386. var
  387. modulo : longint;
  388. begin
  389. if not assigned(sects[currsec]) then
  390. createsection(currsec);
  391. modulo:=sects[currsec]^.datasize mod len;
  392. if modulo > 0 then
  393. sects[currsec]^.alloc(len-modulo);
  394. end;
  395. procedure tobjectoutput.writesymbol(p:pasmsymbol);
  396. begin
  397. Do_halt(211);
  398. end;
  399. procedure tobjectoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  400. begin
  401. Do_halt(211);
  402. end;
  403. procedure tobjectoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);
  404. begin
  405. Do_halt(211);
  406. end;
  407. procedure tobjectoutput.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  408. nidx,nother,line:longint;reloc:boolean);
  409. begin
  410. Do_halt(211);
  411. end;
  412. end.
  413. {
  414. $Log$
  415. Revision 1.2 2000-11-13 21:56:07 peter
  416. * removed some virtual from methods
  417. * sectionsize method implemented (fixes lineinfo stabs)
  418. Revision 1.1 2000/11/12 22:20:37 peter
  419. * create generic toutputsection for binary writers
  420. }