ag386bin.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements an binary assembler output class
  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 ag386bin;
  19. {$i defines.inc}
  20. {$define MULTIPASS}
  21. interface
  22. uses
  23. cobjects,
  24. globals,
  25. cpubase,aasm,
  26. fmodule,finput,
  27. ogbase,assemble;
  28. type
  29. togtype=(og_none,og_dbg,og_coff,og_pecoff,og_elf);
  30. pi386binasmlist=^ti386binasmlist;
  31. ti386binasmlist=object
  32. SmartAsm : boolean;
  33. constructor init(t:togtype;smart:boolean);
  34. destructor done;
  35. procedure WriteBin;
  36. private
  37. { the aasmoutput lists that need to be processed }
  38. lists : byte;
  39. list : array[1..maxoutputlists] of TAAsmoutput;
  40. { current processing }
  41. currlistidx : byte;
  42. currlist : TAAsmoutput;
  43. currpass : byte;
  44. {$ifdef GDB}
  45. n_line : byte; { different types of source lines }
  46. linecount,
  47. includecount : longint;
  48. funcname : pasmsymbol;
  49. stabslastfileinfo : tfileposinfo;
  50. procedure convertstabs(p:pchar);
  51. procedure emitlineinfostabs(nidx,line : longint);
  52. procedure emitstabs(s:string);
  53. procedure WriteFileLineInfo(var fileinfo : tfileposinfo);
  54. procedure StartFileLineInfo;
  55. procedure EndFileLineInfo;
  56. {$endif}
  57. function MaybeNextList(var hp:Tai):boolean;
  58. function TreePass0(hp:Tai):Tai;
  59. function TreePass1(hp:Tai):Tai;
  60. function TreePass2(hp:Tai):Tai;
  61. procedure writetree;
  62. procedure writetreesmart;
  63. end;
  64. implementation
  65. uses
  66. {$ifdef delphi}
  67. sysutils,
  68. {$else}
  69. strings,
  70. {$endif}
  71. cutils,globtype,systems,verbose,
  72. cpuasm,
  73. {$ifdef GDB}
  74. gdb,
  75. {$endif}
  76. { binary writers }
  77. ogcoff,ogelf
  78. ;
  79. {$ifdef GDB}
  80. procedure ti386binasmlist.convertstabs(p:pchar);
  81. var
  82. ofs,
  83. nidx,nother,ii,i,line,j : longint;
  84. code : integer;
  85. hp : pchar;
  86. reloc : boolean;
  87. sec : tsection;
  88. ps : pasmsymbol;
  89. s : string;
  90. begin
  91. ofs:=0;
  92. reloc:=true;
  93. ps:=nil;
  94. sec:=sec_none;
  95. if p[0]='"' then
  96. begin
  97. i:=1;
  98. { we can have \" inside the string !! PM }
  99. while not ((p[i]='"') and (p[i-1]<>'\')) do
  100. inc(i);
  101. p[i]:=#0;
  102. ii:=i;
  103. hp:=@p[1];
  104. s:=StrPas(@P[i+2]);
  105. end
  106. else
  107. begin
  108. hp:=nil;
  109. s:=StrPas(P);
  110. i:=-2; {needed below (PM) }
  111. end;
  112. { When in pass 1 then only alloc and leave }
  113. if currpass=1 then
  114. begin
  115. objectalloc.staballoc(hp);
  116. if assigned(hp) then
  117. p[i]:='"';
  118. exit;
  119. end;
  120. { Parse the rest of the stabs }
  121. if s='' then
  122. internalerror(33000);
  123. j:=pos(',',s);
  124. if j=0 then
  125. internalerror(33001);
  126. Val(Copy(s,1,j-1),nidx,code);
  127. if code<>0 then
  128. internalerror(33002);
  129. i:=i+2+j;
  130. Delete(s,1,j);
  131. j:=pos(',',s);
  132. if (j=0) then
  133. internalerror(33003);
  134. Val(Copy(s,1,j-1),nother,code);
  135. if code<>0 then
  136. internalerror(33004);
  137. i:=i+j;
  138. Delete(s,1,j);
  139. j:=pos(',',s);
  140. if j=0 then
  141. begin
  142. j:=256;
  143. ofs:=-1;
  144. end;
  145. Val(Copy(s,1,j-1),line,code);
  146. if code<>0 then
  147. internalerror(33005);
  148. if ofs=0 then
  149. begin
  150. Delete(s,1,j);
  151. i:=i+j;
  152. Val(s,ofs,code);
  153. if code=0 then
  154. reloc:=false
  155. else
  156. begin
  157. ofs:=0;
  158. s:=strpas(@p[i]);
  159. { handle asmsymbol or
  160. asmsymbol - asmsymbol }
  161. j:=pos(' ',s);
  162. if j=0 then
  163. j:=pos('-',s);
  164. { single asmsymbol }
  165. if j=0 then
  166. j:=256;
  167. { the symbol can be external
  168. so we must use newasmsymbol and
  169. not getasmsymbol !! PM }
  170. ps:=newasmsymbol(copy(s,1,j-1));
  171. if not assigned(ps) then
  172. internalerror(33006)
  173. else
  174. begin
  175. sec:=ps^.section;
  176. ofs:=ps^.address;
  177. reloc:=true;
  178. UsedAsmSymbolListInsert(ps);
  179. end;
  180. if j<256 then
  181. begin
  182. i:=i+j;
  183. s:=strpas(@p[i]);
  184. if (s<>'') and (s[1]=' ') then
  185. begin
  186. j:=0;
  187. while (s[j+1]=' ') do
  188. inc(j);
  189. i:=i+j;
  190. s:=strpas(@p[i]);
  191. end;
  192. ps:=getasmsymbol(s);
  193. if not assigned(ps) then
  194. internalerror(33007)
  195. else
  196. begin
  197. if ps^.section<>sec then
  198. internalerror(33008);
  199. ofs:=ofs-ps^.address;
  200. reloc:=false;
  201. UsedAsmSymbolListInsert(ps);
  202. end;
  203. end;
  204. end;
  205. end;
  206. { external bss need speical handling (PM) }
  207. if assigned(ps) and (ps^.section=sec_none) then
  208. begin
  209. if currpass=2 then
  210. begin
  211. objectdata.writesymbol(ps);
  212. objectoutput.exportsymbol(ps);
  213. end;
  214. objectdata.WriteSymStabs(sec,ofs,hp,ps,nidx,nother,line,reloc)
  215. end
  216. else
  217. objectdata.WriteStabs(sec,ofs,hp,nidx,nother,line,reloc);
  218. if assigned(hp) then
  219. p[ii]:='"';
  220. end;
  221. procedure ti386binasmlist.emitlineinfostabs(nidx,line : longint);
  222. var
  223. sec : tsection;
  224. begin
  225. if currpass=1 then
  226. begin
  227. objectalloc.staballoc(nil);
  228. exit;
  229. end;
  230. if (nidx=n_textline) and assigned(funcname) and
  231. (target_os.use_function_relative_addresses) then
  232. objectdata.WriteStabs(sec_code,objectdata.sectionsize(sec_code)-funcname^.address,
  233. nil,nidx,0,line,false)
  234. else
  235. begin
  236. if nidx=n_textline then
  237. sec:=sec_code
  238. else if nidx=n_dataline then
  239. sec:=sec_data
  240. else
  241. sec:=sec_bss;
  242. objectdata.WriteStabs(sec,objectdata.sectionsize(sec),
  243. nil,nidx,0,line,true);
  244. end;
  245. end;
  246. procedure ti386binasmlist.emitstabs(s:string);
  247. begin
  248. s:=s+#0;
  249. ConvertStabs(@s[1]);
  250. end;
  251. procedure ti386binasmlist.WriteFileLineInfo(var fileinfo : tfileposinfo);
  252. var
  253. curr_n : byte;
  254. hp : pasmsymbol;
  255. infile : tinputfile;
  256. begin
  257. if not ((cs_debuginfo in aktmoduleswitches) or
  258. (cs_gdb_lineinfo in aktglobalswitches)) then
  259. exit;
  260. { file changed ? (must be before line info) }
  261. if (fileinfo.fileindex<>0) and
  262. (stabslastfileinfo.fileindex<>fileinfo.fileindex) then
  263. begin
  264. infile:=current_module.sourcefiles.get_file(fileinfo.fileindex);
  265. if includecount=0 then
  266. curr_n:=n_sourcefile
  267. else
  268. curr_n:=n_includefile;
  269. { get symbol for this includefile }
  270. hp:=newasmsymboltype('Ltext'+ToStr(IncludeCount),AB_LOCAL,AT_FUNCTION);
  271. if currpass=1 then
  272. begin
  273. hp^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  274. UsedAsmSymbolListInsert(hp);
  275. end
  276. else
  277. objectdata.writesymbol(hp);
  278. { emit stabs }
  279. if (infile.path^<>'') then
  280. EmitStabs('"'+lower(BsToSlash(FixPath(infile.path^,false)))+'",'+tostr(curr_n)+
  281. ',0,0,Ltext'+ToStr(IncludeCount));
  282. EmitStabs('"'+lower(FixFileName(infile.name^))+'",'+tostr(curr_n)+
  283. ',0,0,Ltext'+ToStr(IncludeCount));
  284. inc(includecount);
  285. end;
  286. { line changed ? }
  287. if (stabslastfileinfo.line<>fileinfo.line) and (fileinfo.line<>0) then
  288. emitlineinfostabs(n_line,fileinfo.line);
  289. stabslastfileinfo:=fileinfo;
  290. end;
  291. procedure ti386binasmlist.StartFileLineInfo;
  292. var
  293. fileinfo : tfileposinfo;
  294. begin
  295. FillChar(stabslastfileinfo,sizeof(stabslastfileinfo),0);
  296. n_line:=n_textline;
  297. funcname:=nil;
  298. linecount:=1;
  299. includecount:=0;
  300. fileinfo.fileindex:=1;
  301. fileinfo.line:=1;
  302. WriteFileLineInfo(fileinfo);
  303. end;
  304. procedure ti386binasmlist.EndFileLineInfo;
  305. var
  306. hp : pasmsymbol;
  307. store_sec : tsection;
  308. begin
  309. if not ((cs_debuginfo in aktmoduleswitches) or
  310. (cs_gdb_lineinfo in aktglobalswitches)) then
  311. exit;
  312. store_sec:=objectalloc.currsec;
  313. objectalloc.setsection(sec_code);
  314. hp:=newasmsymboltype('Letext',AB_LOCAL,AT_FUNCTION);
  315. if currpass=1 then
  316. begin
  317. hp^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  318. UsedAsmSymbolListInsert(hp);
  319. end
  320. else
  321. objectdata.writesymbol(hp);
  322. EmitStabs('"",'+tostr(n_sourcefile)+',0,0,Letext');
  323. objectalloc.setsection(store_sec);
  324. end;
  325. {$endif GDB}
  326. function ti386binasmlist.MaybeNextList(var hp:Tai):boolean;
  327. begin
  328. { maybe end of list }
  329. while not assigned(hp) do
  330. begin
  331. if currlistidx<lists then
  332. begin
  333. inc(currlistidx);
  334. currlist:=list[currlistidx];
  335. hp:=Tai(currList.first);
  336. end
  337. else
  338. begin
  339. MaybeNextList:=false;
  340. exit;
  341. end;
  342. end;
  343. MaybeNextList:=true;
  344. end;
  345. function ti386binasmlist.TreePass0(hp:Tai):Tai;
  346. var
  347. l : longint;
  348. begin
  349. while assigned(hp) do
  350. begin
  351. case hp.typ of
  352. ait_align :
  353. begin
  354. { always use the maximum fillsize in this pass to avoid possible
  355. short jumps to become out of range }
  356. Tai_align(hp).fillsize:=Tai_align(hp).aligntype;
  357. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  358. end;
  359. ait_datablock :
  360. begin
  361. if not SmartAsm then
  362. begin
  363. if not Tai_datablock(hp).is_global then
  364. begin
  365. l:=Tai_datablock(hp).size;
  366. if l>2 then
  367. objectalloc.sectionalign(4)
  368. else if l>1 then
  369. objectalloc.sectionalign(2);
  370. objectalloc.sectionalloc(Tai_datablock(hp).size);
  371. end;
  372. end
  373. else
  374. begin
  375. l:=Tai_datablock(hp).size;
  376. if l>2 then
  377. objectalloc.sectionalign(4)
  378. else if l>1 then
  379. objectalloc.sectionalign(2);
  380. objectalloc.sectionalloc(Tai_datablock(hp).size);
  381. end;
  382. end;
  383. ait_const_32bit :
  384. objectalloc.sectionalloc(4);
  385. ait_const_16bit :
  386. objectalloc.sectionalloc(2);
  387. ait_const_8bit :
  388. objectalloc.sectionalloc(1);
  389. ait_real_80bit :
  390. objectalloc.sectionalloc(10);
  391. ait_real_64bit :
  392. objectalloc.sectionalloc(8);
  393. ait_real_32bit :
  394. objectalloc.sectionalloc(4);
  395. ait_comp_64bit :
  396. objectalloc.sectionalloc(8);
  397. ait_const_rva,
  398. ait_const_symbol :
  399. objectalloc.sectionalloc(4);
  400. ait_section:
  401. objectalloc.setsection(Tai_section(hp).sec);
  402. ait_symbol :
  403. Tai_symbol(hp).sym^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  404. ait_label :
  405. Tai_label(hp).l^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  406. ait_string :
  407. objectalloc.sectionalloc(Tai_string(hp).len);
  408. ait_instruction :
  409. begin
  410. { reset instructions which could change in pass 2 }
  411. Taicpu(hp).resetpass2;
  412. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  413. end;
  414. ait_cut :
  415. if SmartAsm then
  416. break;
  417. end;
  418. hp:=Tai(hp.next);
  419. end;
  420. TreePass0:=hp;
  421. end;
  422. function ti386binasmlist.TreePass1(hp:Tai):Tai;
  423. var
  424. i,l : longint;
  425. begin
  426. while assigned(hp) do
  427. begin
  428. {$ifdef GDB}
  429. { write stabs }
  430. if ((cs_debuginfo in aktmoduleswitches) or
  431. (cs_gdb_lineinfo in aktglobalswitches)) then
  432. begin
  433. if (objectalloc.currsec<>sec_none) and
  434. not(hp.typ in [
  435. ait_label,
  436. ait_regalloc,ait_tempalloc,
  437. ait_stabn,ait_stabs,ait_section,
  438. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  439. WriteFileLineInfo(hp.fileinfo);
  440. end;
  441. {$endif GDB}
  442. case hp.typ of
  443. ait_align :
  444. begin
  445. { here we must determine the fillsize which is used in pass2 }
  446. Tai_align(hp).fillsize:=align(objectalloc.sectionsize,Tai_align(hp).aligntype)-
  447. objectalloc.sectionsize;
  448. objectalloc.sectionalloc(Tai_align(hp).fillsize);
  449. end;
  450. ait_datablock :
  451. begin
  452. if objectalloc.currsec<>sec_bss then
  453. Message(asmw_e_alloc_data_only_in_bss);
  454. if not SmartAsm then
  455. begin
  456. if Tai_datablock(hp).is_global then
  457. begin
  458. Tai_datablock(hp).sym^.setaddress(sec_none,Tai_datablock(hp).size,Tai_datablock(hp).size);
  459. { force to be common/external, must be after setaddress as that would
  460. set it to AS_GLOBAL }
  461. Tai_datablock(hp).sym^.bind:=AB_COMMON;
  462. end
  463. else
  464. begin
  465. l:=Tai_datablock(hp).size;
  466. if l>2 then
  467. objectalloc.sectionalign(4)
  468. else if l>1 then
  469. objectalloc.sectionalign(2);
  470. Tai_datablock(hp).sym^.setaddress(objectalloc.currsec,objectalloc.sectionsize,
  471. Tai_datablock(hp).size);
  472. objectalloc.sectionalloc(Tai_datablock(hp).size);
  473. end;
  474. end
  475. else
  476. begin
  477. l:=Tai_datablock(hp).size;
  478. if l>2 then
  479. objectalloc.sectionalign(4)
  480. else if l>1 then
  481. objectalloc.sectionalign(2);
  482. Tai_datablock(hp).sym^.setaddress(objectalloc.currsec,objectalloc.sectionsize,Tai_datablock(hp).size);
  483. objectalloc.sectionalloc(Tai_datablock(hp).size);
  484. end;
  485. UsedAsmSymbolListInsert(Tai_datablock(hp).sym);
  486. end;
  487. ait_const_32bit :
  488. objectalloc.sectionalloc(4);
  489. ait_const_16bit :
  490. objectalloc.sectionalloc(2);
  491. ait_const_8bit :
  492. objectalloc.sectionalloc(1);
  493. ait_real_80bit :
  494. objectalloc.sectionalloc(10);
  495. ait_real_64bit :
  496. objectalloc.sectionalloc(8);
  497. ait_real_32bit :
  498. objectalloc.sectionalloc(4);
  499. ait_comp_64bit :
  500. objectalloc.sectionalloc(8);
  501. ait_const_rva,
  502. ait_const_symbol :
  503. begin
  504. objectalloc.sectionalloc(4);
  505. UsedAsmSymbolListInsert(Tai_const_symbol(hp).sym);
  506. end;
  507. ait_section:
  508. begin
  509. objectalloc.setsection(Tai_section(hp).sec);
  510. {$ifdef GDB}
  511. case Tai_section(hp).sec of
  512. sec_code : n_line:=n_textline;
  513. sec_data : n_line:=n_dataline;
  514. sec_bss : n_line:=n_bssline;
  515. else
  516. n_line:=n_dataline;
  517. end;
  518. stabslastfileinfo.line:=-1;
  519. {$endif GDB}
  520. end;
  521. {$ifdef GDB}
  522. ait_stabn :
  523. convertstabs(Tai_stabn(hp).str);
  524. ait_stabs :
  525. convertstabs(Tai_stabs(hp).str);
  526. ait_stab_function_name :
  527. begin
  528. if assigned(Tai_stab_function_name(hp).str) then
  529. begin
  530. funcname:=getasmsymbol(strpas(Tai_stab_function_name(hp).str));
  531. UsedAsmSymbolListInsert(funcname);
  532. end
  533. else
  534. funcname:=nil;
  535. end;
  536. ait_force_line :
  537. stabslastfileinfo.line:=0;
  538. {$endif}
  539. ait_symbol :
  540. begin
  541. Tai_symbol(hp).sym^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  542. UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  543. end;
  544. ait_symbol_end :
  545. begin
  546. if target_info.target=target_i386_linux then
  547. begin
  548. Tai_symbol(hp).sym^.size:=objectalloc.sectionsize-Tai_symbol(hp).sym^.address;
  549. UsedAsmSymbolListInsert(Tai_symbol(hp).sym);
  550. end;
  551. end;
  552. ait_label :
  553. begin
  554. Tai_label(hp).l^.setaddress(objectalloc.currsec,objectalloc.sectionsize,0);
  555. UsedAsmSymbolListInsert(Tai_label(hp).l);
  556. end;
  557. ait_string :
  558. objectalloc.sectionalloc(Tai_string(hp).len);
  559. ait_instruction :
  560. begin
  561. objectalloc.sectionalloc(Taicpu(hp).Pass1(objectalloc.sectionsize));
  562. { fixup the references }
  563. for i:=1 to Taicpu(hp).ops do
  564. begin
  565. with Taicpu(hp).oper[i-1] do
  566. begin
  567. case typ of
  568. top_ref :
  569. begin
  570. if assigned(ref^.symbol) then
  571. UsedAsmSymbolListInsert(ref^.symbol);
  572. end;
  573. top_symbol :
  574. begin
  575. UsedAsmSymbolListInsert(sym);
  576. end;
  577. end;
  578. end;
  579. end;
  580. end;
  581. ait_direct :
  582. Message(asmw_f_direct_not_supported);
  583. ait_cut :
  584. if SmartAsm then
  585. break;
  586. end;
  587. hp:=Tai(hp.next);
  588. end;
  589. TreePass1:=hp;
  590. end;
  591. function ti386binasmlist.TreePass2(hp:Tai):Tai;
  592. var
  593. l : longint;
  594. {$ifdef I386}
  595. co : comp;
  596. {$endif I386}
  597. begin
  598. { main loop }
  599. while assigned(hp) do
  600. begin
  601. {$ifdef GDB}
  602. { write stabs }
  603. if ((cs_debuginfo in aktmoduleswitches) or
  604. (cs_gdb_lineinfo in aktglobalswitches)) then
  605. begin
  606. if (objectdata.currsec<>sec_none) and
  607. not(hp.typ in [
  608. ait_label,
  609. ait_regalloc,ait_tempalloc,
  610. ait_stabn,ait_stabs,ait_section,
  611. ait_cut,ait_marker,ait_align,ait_stab_function_name]) then
  612. WriteFileLineInfo(hp.fileinfo);
  613. end;
  614. {$endif GDB}
  615. case hp.typ of
  616. ait_align :
  617. objectdata.writebytes(Tai_align(hp).getfillbuf^,Tai_align(hp).fillsize);
  618. ait_section :
  619. begin
  620. objectdata.defaultsection(Tai_section(hp).sec);
  621. {$ifdef GDB}
  622. case Tai_section(hp).sec of
  623. sec_code : n_line:=n_textline;
  624. sec_data : n_line:=n_dataline;
  625. sec_bss : n_line:=n_bssline;
  626. else
  627. n_line:=n_dataline;
  628. end;
  629. stabslastfileinfo.line:=-1;
  630. {$endif GDB}
  631. end;
  632. ait_symbol :
  633. begin
  634. objectdata.writesymbol(Tai_symbol(hp).sym);
  635. objectoutput.exportsymbol(Tai_symbol(hp).sym);
  636. end;
  637. ait_datablock :
  638. begin
  639. objectdata.writesymbol(Tai_datablock(hp).sym);
  640. objectoutput.exportsymbol(Tai_datablock(hp).sym);
  641. if SmartAsm or (not Tai_datablock(hp).is_global) then
  642. begin
  643. l:=Tai_datablock(hp).size;
  644. if l>2 then
  645. objectdata.allocalign(4)
  646. else if l>1 then
  647. objectdata.allocalign(2);
  648. objectdata.alloc(Tai_datablock(hp).size);
  649. end;
  650. end;
  651. ait_const_32bit :
  652. objectdata.writebytes(Tai_const(hp).value,4);
  653. ait_const_16bit :
  654. objectdata.writebytes(Tai_const(hp).value,2);
  655. ait_const_8bit :
  656. objectdata.writebytes(Tai_const(hp).value,1);
  657. ait_real_80bit :
  658. objectdata.writebytes(Tai_real_80bit(hp).value,10);
  659. ait_real_64bit :
  660. objectdata.writebytes(Tai_real_64bit(hp).value,8);
  661. ait_real_32bit :
  662. objectdata.writebytes(Tai_real_32bit(hp).value,4);
  663. ait_comp_64bit :
  664. begin
  665. {$ifdef FPC}
  666. co:=comp(Tai_comp_64bit(hp).value);
  667. {$else}
  668. co:=Tai_comp_64bit(hp).value;
  669. {$endif}
  670. objectdata.writebytes(co,8);
  671. end;
  672. ait_string :
  673. objectdata.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  674. ait_const_rva :
  675. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  676. Tai_const_symbol(hp).sym,relative_rva);
  677. ait_const_symbol :
  678. objectdata.writereloc(Tai_const_symbol(hp).offset,4,
  679. Tai_const_symbol(hp).sym,relative_false);
  680. ait_label :
  681. begin
  682. objectdata.writesymbol(Tai_label(hp).l);
  683. { exporting shouldn't be necessary as labels are local,
  684. but it's better to be on the safe side (PFV) }
  685. objectoutput.exportsymbol(Tai_label(hp).l);
  686. end;
  687. ait_instruction :
  688. Taicpu(hp).Pass2;
  689. {$ifdef GDB}
  690. ait_stabn :
  691. convertstabs(Tai_stabn(hp).str);
  692. ait_stabs :
  693. convertstabs(Tai_stabs(hp).str);
  694. ait_stab_function_name :
  695. if assigned(Tai_stab_function_name(hp).str) then
  696. funcname:=getasmsymbol(strpas(Tai_stab_function_name(hp).str))
  697. else
  698. funcname:=nil;
  699. ait_force_line :
  700. stabslastfileinfo.line:=0;
  701. {$endif}
  702. ait_cut :
  703. if SmartAsm then
  704. break;
  705. end;
  706. hp:=Tai(hp.next);
  707. end;
  708. TreePass2:=hp;
  709. end;
  710. procedure ti386binasmlist.writetree;
  711. var
  712. hp : Tai;
  713. label
  714. doexit;
  715. begin
  716. objectalloc.resetsections;
  717. objectalloc.setsection(sec_code);
  718. objectdata:=objectoutput.initwriting(cut_normal);
  719. objectdata.defaultsection(sec_code);
  720. { reset the asmsymbol list }
  721. CreateUsedAsmsymbolList;
  722. {$ifdef MULTIPASS}
  723. { Pass 0 }
  724. currpass:=0;
  725. objectalloc.setsection(sec_code);
  726. { start with list 1 }
  727. currlistidx:=1;
  728. currlist:=list[currlistidx];
  729. hp:=Tai(currList.first);
  730. while assigned(hp) do
  731. begin
  732. hp:=TreePass0(hp);
  733. MaybeNextList(hp);
  734. end;
  735. { leave if errors have occured }
  736. if errorcount>0 then
  737. goto doexit;
  738. {$endif}
  739. { Pass 1 }
  740. currpass:=1;
  741. objectalloc.resetsections;
  742. objectalloc.setsection(sec_code);
  743. {$ifdef GDB}
  744. StartFileLineInfo;
  745. {$endif GDB}
  746. { start with list 1 }
  747. currlistidx:=1;
  748. currlist:=list[currlistidx];
  749. hp:=Tai(currList.first);
  750. while assigned(hp) do
  751. begin
  752. hp:=TreePass1(hp);
  753. MaybeNextList(hp);
  754. end;
  755. {$ifdef GDB}
  756. EndFileLineInfo;
  757. {$endif GDB}
  758. { check for undefined labels and reset }
  759. UsedAsmSymbolListCheckUndefined;
  760. { set section sizes }
  761. objectdata.setsectionsizes(objectalloc.secsize);
  762. { leave if errors have occured }
  763. if errorcount>0 then
  764. goto doexit;
  765. { Pass 2 }
  766. currpass:=2;
  767. {$ifdef GDB}
  768. StartFileLineInfo;
  769. {$endif GDB}
  770. { start with list 1 }
  771. currlistidx:=1;
  772. currlist:=list[currlistidx];
  773. hp:=Tai(currList.first);
  774. while assigned(hp) do
  775. begin
  776. hp:=TreePass2(hp);
  777. MaybeNextList(hp);
  778. end;
  779. {$ifdef GDB}
  780. EndFileLineInfo;
  781. {$endif GDB}
  782. { leave if errors have occured }
  783. if errorcount>0 then
  784. goto doexit;
  785. { write last objectfile }
  786. objectoutput.donewriting;
  787. objectdata:=nil;
  788. doexit:
  789. { reset the used symbols back, must be after the .o has been
  790. written }
  791. UsedAsmsymbolListReset;
  792. DestroyUsedAsmsymbolList;
  793. end;
  794. procedure ti386binasmlist.writetreesmart;
  795. var
  796. hp : Tai;
  797. startsec : tsection;
  798. place: tcutplace;
  799. begin
  800. objectalloc.resetsections;
  801. objectalloc.setsection(sec_code);
  802. objectdata:=objectoutput.initwriting(cut_normal);
  803. objectdata.defaultsection(sec_code);
  804. startsec:=sec_code;
  805. { start with list 1 }
  806. currlistidx:=1;
  807. currlist:=list[currlistidx];
  808. hp:=Tai(currList.first);
  809. while assigned(hp) do
  810. begin
  811. { reset the asmsymbol list }
  812. CreateUsedAsmSymbolList;
  813. {$ifdef MULTIPASS}
  814. { Pass 0 }
  815. currpass:=0;
  816. objectalloc.resetsections;
  817. objectalloc.setsection(startsec);
  818. TreePass0(hp);
  819. { leave if errors have occured }
  820. if errorcount>0 then
  821. exit;
  822. {$endif MULTIPASS}
  823. { Pass 1 }
  824. currpass:=1;
  825. objectalloc.resetsections;
  826. objectalloc.setsection(startsec);
  827. {$ifdef GDB}
  828. StartFileLineInfo;
  829. {$endif GDB}
  830. TreePass1(hp);
  831. {$ifdef GDB}
  832. EndFileLineInfo;
  833. {$endif GDB}
  834. { check for undefined labels }
  835. UsedAsmSymbolListCheckUndefined;
  836. { set section sizes }
  837. objectdata.setsectionsizes(objectalloc.secsize);
  838. { leave if errors have occured }
  839. if errorcount>0 then
  840. exit;
  841. { Pass 2 }
  842. currpass:=2;
  843. objectdata.defaultsection(startsec);
  844. {$ifdef GDB}
  845. StartFileLineInfo;
  846. {$endif GDB}
  847. hp:=TreePass2(hp);
  848. {$ifdef GDB}
  849. EndFileLineInfo;
  850. {$endif GDB}
  851. { leave if errors have occured }
  852. if errorcount>0 then
  853. exit;
  854. { if not end then write the current objectfile }
  855. objectoutput.donewriting;
  856. objectdata:=nil;
  857. { reset the used symbols back, must be after the .o has been
  858. written }
  859. UsedAsmsymbolListReset;
  860. DestroyUsedAsmsymbolList;
  861. { end of lists? }
  862. if not MaybeNextList(hp) then
  863. break;
  864. { save section for next loop }
  865. { this leads to a problem if startsec is sec_none !! PM }
  866. startsec:=objectalloc.currsec;
  867. { we will start a new objectfile so reset everything }
  868. { The place can still change in the next while loop, so don't init }
  869. { the writer yet (JM) }
  870. if (hp.typ=ait_cut) then
  871. place := Tai_cut(hp).place
  872. else
  873. place := cut_normal;
  874. { avoid empty files }
  875. while assigned(hp.next) and
  876. (Tai(hp.next).typ in [ait_marker,ait_comment,ait_section,ait_cut]) do
  877. begin
  878. if Tai(hp.next).typ=ait_section then
  879. startsec:=Tai_section(hp.next).sec
  880. else if (Tai(hp.next).typ=ait_cut) then
  881. place := Tai_cut(hp).place;
  882. hp:=Tai(hp.next);
  883. end;
  884. objectdata:=objectoutput.initwriting(place);
  885. hp:=Tai(hp.next);
  886. { there is a problem if startsec is sec_none !! PM }
  887. if startsec=sec_none then
  888. startsec:=sec_code;
  889. if not MaybeNextList(hp) then
  890. break;
  891. end;
  892. end;
  893. procedure ti386binasmlist.writebin;
  894. procedure addlist(p:TAAsmoutput);
  895. begin
  896. inc(lists);
  897. list[lists]:=p;
  898. end;
  899. begin
  900. if cs_debuginfo in aktmoduleswitches then
  901. addlist(debuglist);
  902. addlist(codesegment);
  903. addlist(datasegment);
  904. addlist(consts);
  905. addlist(rttilist);
  906. if assigned(resourcestringlist) then
  907. addlist(resourcestringlist);
  908. addlist(bsssegment);
  909. if assigned(importssection) then
  910. addlist(importssection);
  911. if assigned(exportssection) and not UseDeffileForExport then
  912. addlist(exportssection);
  913. if assigned(resourcesection) then
  914. addlist(resourcesection);
  915. if SmartAsm then
  916. writetreesmart
  917. else
  918. writetree;
  919. end;
  920. constructor ti386binasmlist.init(t:togtype;smart:boolean);
  921. begin
  922. case t of
  923. og_none :
  924. Message(asmw_f_no_binary_writer_selected);
  925. og_coff :
  926. objectoutput:=tcoffoutput.createdjgpp(smart);
  927. og_pecoff :
  928. objectoutput:=tcoffoutput.createwin32(smart);
  929. og_elf :
  930. objectoutput:=telf32output.create(smart);
  931. else
  932. internalerror(43243432);
  933. end;
  934. objectalloc:=tobjectalloc.create;
  935. SmartAsm:=smart;
  936. currpass:=0;
  937. end;
  938. destructor ti386binasmlist.done;
  939. {$ifdef MEMDEBUG}
  940. var
  941. d : tmemdebug;
  942. {$endif}
  943. begin
  944. {$ifdef MEMDEBUG}
  945. d.init('agbin');
  946. {$endif}
  947. objectoutput.free;
  948. objectalloc.free;
  949. {$ifdef MEMDEBUG}
  950. d.done;
  951. {$endif}
  952. end;
  953. end.
  954. {
  955. $Log$
  956. Revision 1.4 2000-12-25 00:07:31 peter
  957. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  958. tlinkedlist objects)
  959. Revision 1.3 2000/12/23 19:59:35 peter
  960. * object to class for ow/og objects
  961. * split objectdata from objectoutput
  962. Revision 1.2 2000/12/12 19:50:21 peter
  963. * clear usedasmsymbol at exit of writetree
  964. Revision 1.1 2000/11/30 22:18:48 florian
  965. * moved to i386
  966. Revision 1.9 2000/11/12 22:20:37 peter
  967. * create generic toutputsection for binary writers
  968. Revision 1.8 2000/09/24 15:06:10 peter
  969. * use defines.inc
  970. Revision 1.7 2000/08/27 16:11:49 peter
  971. * moved some util functions from globals,cobjects to cutils
  972. * splitted files into finput,fmodule
  973. Revision 1.6 2000/08/12 15:34:22 peter
  974. + usedasmsymbollist to check and reset only the used symbols (merged)
  975. Revision 1.5 2000/08/08 19:28:57 peter
  976. * memdebug/memory patches (merged)
  977. * only once illegal directive (merged)
  978. Revision 1.4 2000/08/04 22:00:50 peter
  979. * merges from fixes
  980. Revision 1.3 2000/07/13 12:08:24 michael
  981. + patched to 1.1.0 with former 1.09patch from peter
  982. Revision 1.2 2000/07/13 11:32:29 michael
  983. + removed logs
  984. }