123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- { *********************************************************************** }
- { }
- { fpcres2elf - Free Pascal Resource to ELF object compiler }
- { Part of the Free Pascal and CrossFPC distributions }
- { }
- { Copyright (C) 2005 Simon Kissel }
- { }
- { See the file COPYING.FPC, included in the FPC distribution, }
- { for details about the copyright. }
- { }
- { 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. }
- { }
- { *********************************************************************** }
- {
- This unit will compile an ELF object file out of a supplied .res resource
- file. Optionally, Delphi/Kylix dfm/xfm form files are also accepted as
- input. These will automatically be converted into resources internally.
- fpcres2elf builds with Delphi, Kylix and FPC.
- Currently this only works on 32Bit targets, but support for 64Bit targets
- is in the works. Support for big endian systems is completely missing,
- though.
- Format used for the various resource sections:
- fpc.resptrs: This section is contained in resptrs.o and always linked to the executable by
- FPC. It containes an exported label fpcrespointers, which is used at runtime
- to find the resptrs section in memory. The resptrs contains pointers to all the
- sections and their sizes. These are updated in a post-precessing step by the
- compiler and by the external resource embedder when applied to an ELF file.
- This section always is 128 Bytes long and initially filled with zeros.
- The first integer (32/64 Bit) value in this section contains the version
- number of the resource system. Currently this value is 1.
- The second integer (32/64 Bit) value in this section contains the number of
- resources.
- After this follows a version-defined number of TFPCResourceSectionInfo entries.
- fpc.ressym: Contains the resource names. This simply is a stream of zero-terminated strings.
- Only textual names are supported, numeric IDs get autoconverted to #ID's.
- The reshash table has got a byte index into ressym to quickly get that data if needed
- fpc.reshash: n TFPCResourceInfo records. (number of entries is defined in fpc.resptrs)
- fpc.resdata: Contains the plain resource data stream. A byte index into the data stream
- is given for each resource entry in TResourceInfo
- fpc.resspare: An empty section which is resized to make room if the size of any of the previous
- sections gets changed. NOT USED IN VERSION 1 (SIZE WILL BE 0)
- fpc.resstr: This section is completely seperated from the rest and contains a block of
- resourcestrings in internal FPC format.
- resptr TFPCResourceSectionInfo list for FPC resources version 1:
- Index Pointer to
- 0 ressym
- 1 reshash
- 2 resdata
- 3 resspare
- 4 resstr
- 5 reserved for future extension (stabs)
- 6 reserved for future extension
- }
- {$ifdef fpc}
- {$mode objfpc}
- {$endif}
- {$h+}
- unit elfres;
- interface
- uses
- elfbfd,
- SysUtils,
- Classes;
- const fpcres2elf_version=1;
- // Do not change the following consts, they are dummy tables to generate an .o that makes ld happy
- const shstrtab = #0+'.symtab'+#0+'.strtab'+#0+'.shstrtab'+#0+'.text'+#0+'.data'+#0+
- '.bss'+#0+'fpc.ressym'+#0+'fpc.resstr'+#0+'fpc.reshash'+#0+
- 'fpc.resdata'+#0+'fpc.resspare'+#0+#0;
- symtab = #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$01#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$02#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$03#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$04#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$05#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$06#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$07#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$08#$00;
- strtab = #$00#$00; // this actually is just one byte long
- zeros = #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
- fake = 'fakefakefakefakefakefakefakefake';
- // header of a windows 32 bit .res file (16 bytes)
- reshdr = #$00#$00#$00#$00#$20#$00#$00#$00#$FF#$FF#$00#$00#$FF#$FF#$00#$00+
- #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
- FilerSignature: array[1..4] of Char = 'TPF0';
- SDefaultExtension = '.or';
-
- Type
- { TElfResCreator }
- TElfResCreator = Class(TObject)
- private
- FDestFileName: String;
- FExtension: string;
- FSourceFileName: String;
- FOverwrite: Boolean;
- FVerbose: Boolean;
- FVersion: Integer;
- Protected
- FSectionStream: TMemoryStream;
- FDataStream: TMemoryStream;
- FSymStream: TMemoryStream;
- FHashStream: TMemoryStream;
- sectionheader_ofs: integer;
- shstrtab_ofs: integer;
- CurrentResource:integer;
- resheader: string;
- Signature: byte;
- Procedure AllocateData; virtual;
- Procedure FreeData; virtual;
- Procedure DoAlign(const a: integer);
- Public
- Constructor Create;
- Procedure Convert(Const Source,Destination : String);
- Procedure ConvertStreams(Source,Dest : TStream);
- Procedure DoConvertStreams(Source,Dest : TStream); virtual;Abstract;
- Property Verbose : Boolean Read FVerbose Write FVerbose;
- Property SourceFileName : String Read FSourceFileName;
- Property DestFileName : String Read FDestFileName;
- Property Overwrite : Boolean Read FOverwrite Write FOverWrite;
- Property Version : Integer Read FVersion Write FVersion;
- Property Extension : string Read FExtension Write FExtension;
- end;
-
- { TElf32ResCreator }
- TElf32ResCreator = Class(TElfResCreator)
- Private
- ResourceEntries: array of TELF32ResourceInfo;
- Protected
- Procedure AllocateData; override;
- Procedure FreeData; override;
- public
- procedure LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- procedure LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- procedure LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- Procedure DoConvertStreams(Source,Dest : TStream); override;
- end;
-
- { TElf64Creator }
- TElf64ResCreator = Class(TElfResCreator)
- Procedure DoConvertStreams(Source,Dest : TStream); override;
- end;
- EElfResError = Class(Exception);
- implementation
- resourcestring
- SErrUnrecognizedFormat = 'Unrecognized file format for input file "%s"';
- Procedure DoError (Msg : String);
- begin
- Raise EElfResError.Create(Msg);
- end;
- Procedure DoErrorFmt (Msg : String; Args : Array of const);
- begin
- Raise EElfResError.CreateFmt(Msg,Args);
- end;
- function HashELF(const S : string) : longint;
- {Note: this hash function is described in "Practical Algorithms For
- Programmers" by Andrew Binstock and John Rex, Addison Wesley,
- with modifications in Dr Dobbs Journal, April 1996}
- var
- G : longint;
- i : integer;
- begin
- Result := 0;
- for i := 1 to length(S) do begin
- Result := (Result shl 4) + ord(S[i]);
- G := Result and $F0000000;
- if (G <> 0) then
- Result := Result xor (G shr 24);
- Result := Result and (not G);
- end;
- end;
- { TElfResCreator }
- procedure TElfResCreator.AllocateData;
- begin
- FSectionStream:=TMemoryStream.Create;
- FDataStream:=TMemoryStream.Create;
- FSymStream:=TMemoryStream.Create;
- FHashStream:=TMemoryStream.Create;
- end;
- procedure TElfResCreator.FreeData;
- begin
- FreeAndNil(FSectionStream);
- FreeAndNil(FDataStream);
- FreeAndNil(FSymStream);
- FreeAndNil(FHashStream);
- end;
- constructor TElfResCreator.Create;
- begin
- FVersion:=fpcres2elf_version;
- FOverwrite:=True;
- FVerbose:=False;
- FExtension:=SDefaultExtension;
- end;
- // fill the memorystream so it is aligned, max supported align is 16
- procedure TElfResCreator.DoAlign(const a: integer);
- var i: integer;
- begin
- i:=(4 - (FSectionStream.position MOD a)) MOD a;
- if (i>0) then FSectionStream.Write(zeros[1],i);
- end;
- procedure TElfResCreator.Convert(const Source, Destination: String);
- Var
- Src,Dest : TFileStream;
- begin
- FSourceFileName:=Source;
- FDestFileName:=Destination;
- if FDestFileName='' then
- FDestFileName:=ChangeFileExt(Source,FExtension);
- Src:=TFileStream.Create(FSourceFileName,fmOpenRead or fmShareDenyWrite);
- try
- Dest:=TFileStream.Create(FDestFileName,fmCreate or fmShareDenyWrite);
- Try
- ConvertStreams(Src,Dest);
- Finally
- Dest.Free;
- end;
- Finally
- Src.Free;
- end;
- end;
- procedure TElfResCreator.ConvertStreams(Source, Dest: TStream);
- begin
- AllocateData;
- Try
- DoConvertStreams(Source,Dest);
- Finally
- FreeData;
- end;
- end;
- { ---------------------------------------------------------------------
- TElf32ResCreator
- ---------------------------------------------------------------------}
- procedure TElf32ResCreator.AllocateData;
- begin
- inherited AllocateData;
- // reserve space for 1024 resource entries for now
- SetLength(ResourceEntries,1024);
- CurrentResource:=0;
- end;
- procedure TElf32ResCreator.FreeData;
- begin
- inherited FreeData;
- SetLength(ResourceEntries,0);
- end;
- procedure TElf32ResCreator.LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- var l:longint;
- w:word;
- ws:WideString;
- wc:WideChar;
- name:string;
- i,nl: integer;
- headersize:integer;
- headerstart:integer;
- begin
- headerstart:=rs.Position;
- resinfo.ptr:=DataStream.Position;
- rs.Read(resinfo.size,4);
- rs.Read(headersize,4);
- rs.Read(l,4); // Type
- if (l AND $0000FFFF)=$0000FFFF then
- begin // Type is stored as ID
- resinfo.restype:=(l AND $FFFF0000) shr 16; // kill the marker, we always use IDs
- end
- else
- begin
- // we don't support text IDs for now, skip until we have reached the end
- // of the widestring, and set rcdata (10) in this case.
- repeat
- rs.Read(w,2);
- until w=0;
- resinfo.restype:=10;
- end;
- rs.Read(l,4); // Name
- if (l AND $0000FFFF)=$0000FFFF then
- begin // Name is stored as ID.
- l:=(l AND $FFFF0000) shr 16; // kill the marker
- // We don't want to support integer names, we'll instead convert them to a #id string
- // which is more common.
- name:='#'+inttostr(l);
- end
- else
- begin
- // Ok, it's a widestring ID
- ws:=widechar(l AND $0000FFFF);
- ws:=ws+widechar((l AND $FFFF0000) shr 16);
- // get the rest of it
- repeat
- rs.Read(wc,2);
- if wc<>#0 then ws:=ws+wc;
- until wc=#0;
- // convert to ANSI
- name:=ws;
- end;
- // create a hash of the name
- resinfo.reshash:=HashELF(name);
- // save the name plus a trailing #0 to the SymStream, also save
- // the position of this name in the SymStream
- resinfo.name:=SymStream.Position;
- name:=name+#0;
- nl:=length(name);
- SymStream.Write(name[1],length(name));
- // We don't care about the rest of the header
- rs.Seek(headersize-(rs.position-headerstart),soFromCurrent);
- // Now copy over the resource data into our internal memory stream
- DataStream.CopyFrom(rs,resinfo.size);
- // Align the resource stream on a dword boundary
- i:=(4 - (rs.Position MOD 4)) MOD 4;
- if (i>0) then rs.Seek(i,soFromCurrent);
- // Align the data stream on a dword boundary
- i:=(4 - (DataStream.Position MOD 4)) MOD 4;
- if (i>0) then DataStream.Write(zeros[1],i);
- end;
- procedure TElf32ResCreator.LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- var name: string;
- i: integer;
- begin
- resinfo.ptr:=0;
- resinfo.restype:=10; // RCDATA
- // Skip the header
- rs.Position:=3;
- // Read the name
- setlength(name,64); // Component names can be 64 chars at max
- rs.Read(name[1],64);
- // Find end of name
- i:=pos(#0,name);
- name:=copy(name,1,i-1);
- // Seek to after the name and skip other crap
- rs.Position:=i+9;
- resinfo.size:=rs.Size-rs.Position;
- // ...this is followed by the data.
- // create a hash of the name
- resinfo.reshash:=HashELF(name);
- // save the name plus a trailing #0 to the SymStream, also save
- // the position of this name in the SymStream
- resinfo.name:=SymStream.Position;
- name:=name+#0;
- SymStream.Write(name[1],length(name));
- // Now copy over the resource data into our internal memory stream
- DataStream.CopyFrom(rs,resinfo.size);
- // Align the data stream on a dword boundary
- i:=(4 - (DataStream.Position MOD 4)) MOD 4;
- if (i>0) then DataStream.Write(zeros,i);
- end;
- procedure TElf32ResCreator.LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
- var ms:TMemoryStream;
- begin
- ms:=nil;
- try
- ms:=TMemoryStream.Create;
- ObjectTextToResource(rs,ms);
- LoadBinaryDFMEntry(ms, DataStream, SymStream, resinfo);
- finally
- ms.free;
- end;
- end;
- procedure TElf32ResCreator.DoConvertStreams(Source, Dest: TStream);
- Var
- I : Integer;
- ElfHeader: TElf32Header;
- SectionHeader: TElf32sechdr;
- ressym: TELF32ResourceSectionInfo;
- resstr: TELF32ResourceSectionInfo;
- reshash: TELF32ResourceSectionInfo;
- resdata: TELF32ResourceSectionInfo;
- resspare: TELF32ResourceSectionInfo;
-
- begin
- // Read and check the header of the input file. First check if it's a 32bit resource
- // file...
- SetLength(resheader,32);
- Source.Read(resheader[1],32);
- if (resheader<>reshdr) then
- begin
- // ...not a 32Bit resource file. Now let's see if it's a text or binary dfm/xfm/lfm file.
- Source.Position:=0;
- Source.Read(Signature,1);
- if (Signature=$FF) then
- begin
- Source.Position:=0;
- LoadBinaryDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
- end
- else if char(Signature) in ['o','O','i','I',' ',#13,#11,#9] then
- begin
- Source.Position:=0;
- LoadTextDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
- end
- else
- DoErrorFmt(SErrUnrecognizedFormat,[SourceFileName]);
- inc(CurrentResource,1);
- end
- else // ...yes, it's a resource file.
- while Source.Position<Source.Size do
- begin
- // Load Resource info, and copy the resource data into the DataStream
- LoadRESEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
- inc(CurrentResource,1);
- // if we hit the current limit of allocated ResourceEntries in the
- // array, allocate some more space
- if (CurrentResource>=length(ResourceEntries)) then
- setlength(ResourceEntries,length(ResourceEntries)+1024);
- end;
- // downsize the ResourceEntries to the really needed size
- SetLength(ResourceEntries,CurrentResource);
- // Write the symbol table - ressym
- ressym.ptr:=FSectionStream.Position+sizeof(TElf32Header);
- FSymStream.Position:=0;
- FSectionStream.CopyFrom(FSymStream,FSymStream.Size);
- // resstr
- resstr.ptr:=FSectionStream.Position+sizeof(TElf32Header);
- resstr.size:=0;
- // TODO: Load string data here
- doalign(4);
- // Now write the ResourceInfos.
- reshash.ptr:=FSectionStream.Position+sizeof(TElf32Header);
- for i:=0 to high(ResourceEntries) do
- begin
- FSectionStream.Write(ResourceEntries[i],sizeof(TELF32ResourceInfo));
- end;
- doalign(4);
- // Next write the resource data stream
- resdata.ptr:=FSectionStream.Position+sizeof(TElf32Header);
- FDataStream.Position:=0;
- FSectionStream.CopyFrom(FDataStream,FDataStream.Size);
- doalign(4);
- // resspare
- resspare.ptr:=FSectionStream.Position+sizeof(TElf32Header);
- // don't write anything, this is an empty section
- // shstrtab - this is not aligned
- shstrtab_ofs:=FSectionStream.Position+sizeof(TElf32Header);
- FSectionStream.Write(shstrtab[1],length(shstrtab));
- // Write 12 section headers. The headers itself don't need to be aligned,
- // as their size can be divided by 4. As shstrtab is uneven and not aligned,
- // we however need to align the start of the section header table
- doalign(4);
- sectionheader_ofs:=FSectionStream.Position+sizeof(TElf32Header);;
- // empty one
- fillchar(SectionHeader,sizeof(SectionHeader),0);
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .text
- SectionHeader.sh_name:=$1B;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=6; // AX
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
- SectionHeader.sh_size:=0; // yep, pretty empty it is
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .data
- SectionHeader.sh_name:=$21;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=3; // WA
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
- SectionHeader.sh_size:=0; // yep, pretty empty it is
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .bss
- SectionHeader.sh_name:=$27;
- SectionHeader.sh_type:=8; // NOBITS
- SectionHeader.sh_flags:=3; // WA
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
- SectionHeader.sh_size:=0; // yep, pretty empty it is
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // fpc.ressym
- SectionHeader.sh_name:=$2C;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=2; // A
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=ressym.ptr; // directly after header
- SectionHeader.sh_size:=FSymStream.Size;
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=1; // DON'T align this, as this section will be merged by ld
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // fpc.resstr
- SectionHeader.sh_name:=$37;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=2; // A
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=resstr.ptr;
- SectionHeader.sh_size:=0; // currently empty
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // fpc.reshash
- SectionHeader.sh_name:=$42;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=2; // A
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=reshash.ptr;
- SectionHeader.sh_size:=length(ResourceEntries)*sizeof(TELF32ResourceInfo);
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // fpc.resdata
- SectionHeader.sh_name:=$4e;
- SectionHeader.sh_type:=1; // PROGBITS
- SectionHeader.sh_flags:=2; // A
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=resdata.ptr;
- SectionHeader.sh_size:=FDataStream.Size;
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // fpc.resspare
- // Not used in V1
- SectionHeader.sh_name:=$5a;
- SectionHeader.sh_type:=8; // NOBITS
- SectionHeader.sh_flags:=2; // A
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=resspare.ptr; // fake, as it's empty, should be equal to shstrtab's offset
- SectionHeader.sh_size:=0; //DataStream.Size; // Leave as much room as we currently have in resdata section
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .shstrtab
- SectionHeader.sh_name:=$11;
- SectionHeader.sh_type:=3; // STRTAB
- SectionHeader.sh_flags:=0;
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=shstrtab_ofs; // $3E
- SectionHeader.sh_size:=$67;
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=1; // alignment
- SectionHeader.sh_entsize:=0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .symtab
- SectionHeader.sh_name:=$01;
- SectionHeader.sh_type:=2; // SYMTAB
- SectionHeader.sh_flags:=0;
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=FSectionStream.Position+sizeof(TElf32Header)+sizeOf(SectionHeader)+sizeOf(SectionHeader); // will come directly after this and the next section. $0288;
- SectionHeader.sh_size:=$90;
- SectionHeader.sh_link:=$0B;
- SectionHeader.sh_info:=$09;
- SectionHeader.sh_addralign:=4; // alignment
- SectionHeader.sh_entsize:=$10;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // .strtab
- SectionHeader.sh_name:=$09;
- SectionHeader.sh_type:=3; // STRTAB
- SectionHeader.sh_flags:=0;
- SectionHeader.sh_addr:=0;
- SectionHeader.sh_offset:=FSectionStream.Position+sizeof(TElf32Header)+sizeOf(SectionHeader)+$90; // will come after this sectionheader and the $90 bytes symtab - $0318; end of file
- SectionHeader.sh_size:=1;
- SectionHeader.sh_link:=0;
- SectionHeader.sh_info:=0;
- SectionHeader.sh_addralign:=1; // alignment
- SectionHeader.sh_entsize:=$0;
- FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
- // now write the symbol table
- FSectionStream.Write(symtab[1],length(symtab));
- // We don't need to align it, as it's $90 in size
- // now write the string table, it's just a single byte
- FSectionStream.Write(strtab[1],1);
- // Ok, we are done, now let's really write something to disk...
- // First write the ELF header
- fillchar(ElfHeader,sizeof(ElfHeader),0);
- ElfHeader.magic0123:=$464c457f; { = #127'ELF' }
- ElfHeader.file_class:=1;
- ElfHeader.data_encoding:=1;
- ElfHeader.file_version:=1;
- ElfHeader.e_type:=1;
- ElfHeader.e_machine:=3;
- ElfHeader.e_version:=1;
- ElfHeader.e_shoff:=sectionheader_ofs;
- ElfHeader.e_shstrndx:=9;
- ElfHeader.e_shnum:=12;
- ElfHeader.e_ehsize:=sizeof(TElf32header);
- ElfHeader.e_shentsize:=sizeof(TElf32sechdr);
- Dest.Write(ElfHeader,sizeof(TElf32header));
- // And now let's dump our whole memorystream into it.
- FSectionStream.Position:=0;
- Dest.CopyFrom(FSectionStream,FsectionStream.Size);
- end;
- { TElf64Creator }
- procedure TElf64ResCreator.DoConvertStreams(Source, Dest: TStream);
- begin
- DoError('64 bits resources not yet supported')
- end;
- end.
|