123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- {
- $Id$
- Copyright (c) 1998-2000 by Peter Vreman
- Contains the base stuff for binary object file writers
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit ogbase;
- {$i defines.inc}
- interface
- uses
- {$ifdef Delphi}
- sysutils,
- dmisc,
- {$else Delphi}
- strings,
- dos,
- {$endif Delphi}
- { common }
- cclasses,cobjects,
- { targets }
- systems,
- { outputwriters }
- owbase,owar,
- { assembler }
- cpubase,aasm;
- type
- tsecsize = array[tsection] of longint;
- relative_type = (relative_false,relative_true,relative_rva);
- poutputreloc = ^toutputreloc;
- toutputreloc = packed record
- next : poutputreloc;
- address : longint;
- symbol : pasmsymbol;
- section : tsection; { only used if symbol=nil }
- typ : relative_type;
- end;
- poutputsymbol = ^toutputsymbol;
- toutputsymbol = packed record
- namestr : string[8]; { namestr or nameidx will be used }
- nameidx : longint;
- section : tsection;
- value : longint;
- bind : TAsmsymbind;
- typ : TAsmsymtype;
- size : longint;
- end;
- tobjectsection = class
- name : string[32];
- secsymidx : longint; { index for the section in symtab }
- addralign : longint;
- { size of the data and in the file }
- data : TDynamicArray;
- datasize : longint;
- datapos : longint;
- { size and position in memory, set by setsectionsize }
- memsize,
- mempos : longint;
- { relocation }
- nrelocs : longint;
- relochead : POutputReloc;
- reloctail : ^POutputReloc;
- constructor create(const Aname:string;Aalign:longint;alloconly:boolean);
- destructor destroy;override;
- function write(var d;l:longint):longint;
- function writestr(const s:string):longint;
- procedure writealign(l:longint);
- function aligneddatasize:longint;
- procedure alignsection;
- procedure alloc(l:longint);
- procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
- procedure addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
- end;
- tobjectdata = class
- { section }
- currsec : tsection;
- sects : array[TSection] of tobjectsection;
- constructor create;
- destructor destroy;override;
- procedure createsection(sec:tsection);virtual;
- procedure defaultsection(sec:tsection);
- function sectionsize(s:tsection):longint;
- procedure setsectionsizes(var s:tsecsize);virtual;
- procedure alloc(len:longint);
- procedure allocalign(len:longint);
- procedure writebytes(var data;len:longint);
- procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;abstract;
- procedure writesymbol(p:pasmsymbol);virtual;abstract;
- procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;abstract;
- procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;nidx,nother,line:longint;reloc:boolean);virtual;abstract;
- end;
- tobjectalloc = class
- currsec : tsection;
- secsize : tsecsize;
- constructor create;
- destructor destroy;override;
- procedure setsection(sec:tsection);
- function sectionsize:longint;
- procedure sectionalloc(l:longint);
- procedure sectionalign(l:longint);
- procedure staballoc(p:pchar);
- procedure resetsections;
- end;
- tobjectoutput = class
- protected
- path : pathstr;
- ObjFile : string;
- { smartlinking }
- objsmart : boolean;
- place : tcutplace;
- SmartFilesCount,
- SmartHeaderCount : longint;
- { writer }
- writer : tobjectwriter;
- { section }
- data : tobjectdata;
- { Writing }
- procedure NextSmartName;
- protected
- procedure writetodisk;virtual;
- public
- constructor create(smart:boolean);
- destructor destroy;override;
- function initwriting(Aplace:tcutplace):tobjectdata;virtual;
- procedure donewriting;virtual;
- procedure exportsymbol(p:pasmsymbol);
- end;
- var
- { current object data, used in ag386bin/cpuasm }
- objectdata : tobjectdata;
- { current object allocator }
- objectalloc : tobjectalloc;
- { current object writer used }
- objectoutput : tobjectoutput;
- implementation
- uses
- comphook,
- cutils,globtype,globals,verbose,fmodule;
- {****************************************************************************
- tobjectalloc
- ****************************************************************************}
- constructor tobjectalloc.create;
- begin
- end;
- destructor tobjectalloc.destroy;
- begin
- end;
- procedure tobjectalloc.setsection(sec:tsection);
- begin
- currsec:=sec;
- end;
- procedure tobjectalloc.resetsections;
- begin
- FillChar(secsize,sizeof(secsize),0);
- end;
- procedure tobjectalloc.sectionalloc(l:longint);
- begin
- inc(secsize[currsec],l);
- end;
- procedure tobjectalloc.sectionalign(l:longint);
- begin
- if (secsize[currsec] mod l)<>0 then
- inc(secsize[currsec],l-(secsize[currsec] mod l));
- end;
- procedure tobjectalloc.staballoc(p:pchar);
- begin
- inc(secsize[sec_stab]);
- if assigned(p) and (p[0]<>#0) then
- inc(secsize[sec_stabstr],strlen(p)+1);
- end;
- function tobjectalloc.sectionsize:longint;
- begin
- sectionsize:=secsize[currsec];
- end;
- {****************************************************************************
- TSectionOutput
- ****************************************************************************}
- constructor tobjectsection.create(const Aname:string;Aalign:longint;alloconly:boolean);
- begin
- name:=Aname;
- secsymidx:=0;
- addralign:=Aalign;
- { data }
- datasize:=0;
- datapos:=0;
- if alloconly then
- data:=nil
- else
- Data:=TDynamicArray.Create(8192);
- { position }
- mempos:=0;
- memsize:=0;
- { relocation }
- NRelocs:=0;
- relocHead:=nil;
- relocTail:=@relocHead;
- end;
- destructor tobjectsection.destroy;
- begin
- if assigned(Data) then
- Data.Free;
- end;
- function tobjectsection.write(var d;l:longint):longint;
- begin
- write:=datasize;
- if not assigned(Data) then
- Internalerror(3334441);
- Data.write(d,l);
- inc(datasize,l);
- end;
- function tobjectsection.writestr(const s:string):longint;
- begin
- writestr:=datasize;
- if not assigned(Data) then
- Internalerror(3334441);
- Data.write(s[1],length(s));
- inc(datasize,length(s));
- end;
- procedure tobjectsection.writealign(l:longint);
- var
- i : longint;
- empty : array[0..63] of char;
- begin
- { no alignment needed for 0 or 1 }
- if l<=1 then
- exit;
- i:=datasize mod l;
- if i>0 then
- begin
- if assigned(data) then
- begin
- fillchar(empty,sizeof(empty),0);
- Data.write(empty,l-i);
- end;
- inc(datasize,l-i);
- end;
- end;
- function tobjectsection.aligneddatasize:longint;
- begin
- aligneddatasize:=align(datasize,addralign);
- end;
- procedure tobjectsection.alignsection;
- begin
- writealign(addralign);
- end;
- procedure tobjectsection.alloc(l:longint);
- begin
- if assigned(Data) then
- Internalerror(3334442);
- inc(datasize,l);
- end;
- procedure tobjectsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
- var
- r : POutputReloc;
- begin
- new(r);
- reloctail^:=r;
- reloctail:=@r^.next;
- r^.next:=nil;
- r^.address:=ofs;
- r^.symbol:=p;
- r^.section:=sec_none;
- r^.typ:=relative;
- inc(nrelocs);
- end;
- procedure tobjectsection.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
- var
- r : POutputReloc;
- begin
- new(r);
- reloctail^:=r;
- reloctail:=@r^.next;
- r^.next:=nil;
- r^.address:=ofs;
- r^.symbol:=nil;
- r^.section:=sec;
- r^.typ:=relative;
- inc(nrelocs);
- end;
- {****************************************************************************
- tobjectdata
- ****************************************************************************}
- constructor tobjectdata.create;
- begin
- { reset }
- FillChar(Sects,sizeof(Sects),0);
- end;
- destructor tobjectdata.destroy;
- var
- sec : tsection;
- begin
- { free memory }
- for sec:=low(tsection) to high(tsection) do
- if assigned(sects[sec]) then
- sects[sec].free;
- end;
- procedure tobjectdata.createsection(sec:tsection);
- begin
- sects[sec]:=tobjectsection.create(target_asm.secnames[sec],1,(sec=sec_bss));
- end;
- function tobjectdata.sectionsize(s:tsection):longint;
- begin
- if assigned(sects[s]) then
- sectionsize:=sects[s].datasize
- else
- sectionsize:=0;
- end;
- procedure tobjectdata.setsectionsizes(var s:tsecsize);
- begin
- end;
- procedure tobjectdata.defaultsection(sec:tsection);
- begin
- currsec:=sec;
- end;
- procedure tobjectdata.writebytes(var data;len:longint);
- begin
- if not assigned(sects[currsec]) then
- createsection(currsec);
- sects[currsec].write(data,len);
- end;
- procedure tobjectdata.alloc(len:longint);
- begin
- if not assigned(sects[currsec]) then
- createsection(currsec);
- sects[currsec].alloc(len);
- end;
- procedure tobjectdata.allocalign(len:longint);
- var
- modulo : longint;
- begin
- if not assigned(sects[currsec]) then
- createsection(currsec);
- modulo:=sects[currsec].datasize mod len;
- if modulo > 0 then
- sects[currsec].alloc(len-modulo);
- end;
- {****************************************************************************
- tobjectoutput
- ****************************************************************************}
- constructor tobjectoutput.create(smart:boolean);
- begin
- SmartFilesCount:=0;
- SmartHeaderCount:=0;
- objsmart:=smart;
- objfile:=current_module.objfilename^;
- { Which path will be used ? }
- if objsmart and
- (cs_asm_leave in aktglobalswitches) then
- begin
- path:=current_module.path^+FixFileName(current_module.modulename^)+target_info.smartext;
- {$I-}
- mkdir(path);
- {$I+}
- if ioresult<>0 then;
- path:=FixPath(path,false);
- end
- else
- path:=current_module.path^;
- { init writer }
- if objsmart and
- not(cs_asm_leave in aktglobalswitches) then
- writer:=tarobjectwriter.create(current_module.staticlibfilename^)
- else
- writer:=tobjectwriter.create;
- end;
- destructor tobjectoutput.destroy;
- begin
- writer.free;
- end;
- procedure tobjectoutput.NextSmartName;
- var
- s : string;
- begin
- inc(SmartFilesCount);
- if SmartFilesCount>999999 then
- Message(asmw_f_too_many_asm_files);
- if (cs_asm_leave in aktglobalswitches) then
- s:=current_module.asmprefix^
- else
- s:=current_module.modulename^;
- case place of
- cut_begin :
- begin
- inc(SmartHeaderCount);
- s:=s+tostr(SmartHeaderCount)+'h';
- end;
- cut_normal :
- s:=s+tostr(SmartHeaderCount)+'s';
- cut_end :
- s:=s+tostr(SmartHeaderCount)+'t';
- end;
- ObjFile:=FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
- end;
- procedure tobjectoutput.writetodisk;
- begin
- end;
- function tobjectoutput.initwriting(Aplace:tcutplace):tobjectdata;
- begin
- place:=Aplace;
- { the data should be set by the real output like coffoutput }
- data:=nil;
- initwriting:=nil;
- { open the writer }
- if objsmart then
- NextSmartName;
- writer.createfile(objfile);
- end;
- procedure tobjectoutput.donewriting;
- begin
- { Only write the .o if there are no errors }
- if errorcount=0 then
- writetodisk;
- { close the writer }
- writer.closefile;
- { free data }
- data.free;
- data:=nil;
- end;
- procedure tobjectoutput.exportsymbol(p:pasmsymbol);
- begin
- { export globals and common symbols, this is needed
- for .a files }
- if p^.bind in [AB_GLOBAL,AB_COMMON] then
- writer.writesym(p^.name);
- end;
- end.
- {
- $Log$
- Revision 1.5 2000-12-25 00:07:26 peter
- + new tlinkedlist class (merge of old tstringqueue,tcontainer and
- tlinkedlist objects)
- Revision 1.4 2000/12/24 12:25:31 peter
- + cstreams unit
- * dynamicarray object to class
- Revision 1.3 2000/12/23 19:59:35 peter
- * object to class for ow/og objects
- * split objectdata from objectoutput
- Revision 1.2 2000/11/13 21:56:07 peter
- * removed some virtual from methods
- * sectionsize method implemented (fixes lineinfo stabs)
- Revision 1.1 2000/11/12 22:20:37 peter
- * create generic tobjectsection for binary writers
- }
|