123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2008 by Giulio Bernardi
- Resource writer for Mach-O files
- See the file COPYING.FPC, included in this 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.
- **********************************************************************}
- type
- _TMachOSymbolTable_ = class(TMachOSymbolTable)
- protected
- function AddSymbol(aName : string; sect : byte; addr : longword;
- glob : boolean) : integer; override;
- protected
- public
- procedure WriteToStream(aStream : TStream); override;
- end;
- _TMachOSubWriter_ = class(TAbstractMachOSubWriter)
- private
- procedure SwapSection(var aSection: _TSection_);
- protected
- procedure PrescanResourceTree; override;
- procedure WriteResHeader(aStream : TStream; aResources : TResources); override;
- procedure WriteNodeInfos(aStream : TStream); override;
- procedure WriteNodeInfo(aStream : TStream; aNode : TResourceTreeNode); override;
- procedure AllocateSpaceForLoadCommands(aStream : TStream); override;
- procedure FixLoadCommands(aStream : TStream; aResources : TResources); override;
- procedure FixResHeader(aStream : TStream); override;
- public
- constructor Create(aParent : TMachOResourceWriter; const aMachineType
- : TMachOMachineType; const aOppositeEndianess : boolean); override;
- end;
- { _TMachOSymbolTable_ }
- function _TMachOSymbolTable_.AddSymbol(aName: string; sect: byte; addr: longword;
- glob: boolean): integer;
- var p : _PNlist_;
- begin
- p:=GetMem(sizeof(_TNlist_));
- p^.strx:=fStringTable.Add(aName);
- p^._type:=N_SECT;
- if glob then p^._type:=p^._type or N_EXT;
- p^.desc:=0;
- p^.sect:=sect;
- p^.value:=addr;
- Result:=fList.Count;
- fList.Add(p);
- end;
- procedure _TMachOSymbolTable_.WriteToStream(aStream: TStream);
- var nlist : _TNlist_;
- i : integer;
- begin
- for i:=0 to fList.Count-1 do
- begin
- nlist:=_PNlist_(fList[i])^;
- if fOppositeEndianess then
- begin
- nlist.strx:=SwapEndian(nlist.strx);
- nlist.desc:=SwapEndian(nlist.desc);
- nlist.value:=SwapEndian(nlist.value);
- end;
- aStream.WriteBuffer(nlist,sizeof(nlist));
- end;
- end;
- { _TMachOSubWriter_ }
- procedure _TMachOSubWriter_.SwapSection(var aSection: _TSection_);
- begin
- aSection.addr:=SwapEndian(aSection.addr);
- aSection.size:=SwapEndian(aSection.size);
- aSection.offset:=SwapEndian(aSection.offset);
- aSection.align:=SwapEndian(aSection.align);
- aSection.reloff:=SwapEndian(aSection.reloff);
- aSection.nreloc:=SwapEndian(aSection.nreloc);
- aSection.flags:=SwapEndian(aSection.flags);
- aSection.reserved1:=SwapEndian(aSection.reserved1);
- aSection.reserved2:=SwapEndian(aSection.reserved2);
- end;
- procedure _TMachOSubWriter_.PrescanResourceTree;
- begin
- fResStrTable.Clear;
- fRoot.SubDirRVA:=sizeof(_TResHdr_)+sizeof(_TResInfoNode_);
- fResStrTable.StartOfs:=PrescanNode(fRoot,sizeof(_TResInfoNode_));
- if fResStrTable.Used then
- fDataCurOfs:=NextAligned(fDataAlignment,fResStrTable.StartOfs+fResStrTable.Size)
- else
- fDataCurOfs:=fResStrTable.StartOfs;
- end;
- procedure _TMachOSubWriter_.WriteResHeader(aStream: TStream;
- aResources: TResources);
- var hdr : _TResHdr_;
- begin
- hdr.rootptr:=sizeof(hdr);
- hdr.count:=aResources.Count;
- hdr.usedhandles:=0;
- hdr.handles:=0;
- fRelocations.Add(0,1);
- fRelocations.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),2);
- if fOppositeEndianess then
- begin
- hdr.rootptr:=SwapEndian(hdr.rootptr);
- hdr.count:=SwapEndian(hdr.count);
- //handles must be fixed later
- // hdr.usedhandles:=SwapEndian(hdr.usedhandles);
- // hdr.handles:=SwapEndian(hdr.handles);
- end;
- aStream.WriteBuffer(hdr,sizeof(hdr));
- end;
- procedure _TMachOSubWriter_.WriteNodeInfos(aStream: TStream);
- begin
- fCurOfs:=sizeof(_TResHdr_);
- WriteNodeInfo(aStream,fRoot);
- WriteSubNodes(aStream,fRoot);
- end;
- procedure _TMachOSubWriter_.WriteNodeInfo(aStream: TStream;
- aNode: TResourceTreeNode);
- var infonode : _TResInfoNode_;
- begin
- if aNode.Desc.DescType=dtID then
- infonode.nameid:=aNode.Desc.ID
- else
- begin
- infonode.nameid:=fResStrTable.StartOfs+aNode.NameRVA;
- fRelocations.Add(fCurOfs,1);
- end;
- infonode.ncount:=aNode.NamedCount;
- if aNode.IsLeaf then
- begin
- infonode.idcountsize:=aNode.Data.RawData.Size;
- infonode.subptr:=fDataCurOfs;
- fDataCurOfs:=NextAligned(fDataAlignment,fDataCurOfs+infonode.idcountsize);
- end
- else
- begin
- infonode.idcountsize:=aNode.IDCount;
- infonode.subptr:=aNode.SubDirRVA;
- end;
- fRelocations.Add(
- fCurOfs+sizeof(infonode.nameid)+sizeof(infonode.ncount)+
- sizeof(infonode.idcountsize),1);
- if fOppositeEndianess then
- begin
- infonode.nameid:=SwapEndian(infonode.nameid);
- infonode.ncount:=SwapEndian(infonode.ncount);
- infonode.idcountsize:=SwapEndian(infonode.idcountsize);
- infonode.subptr:=SwapEndian(infonode.subptr);
- end;
- aStream.WriteBuffer(infonode,sizeof(infonode));
- inc(fCurOfs,sizeof(infonode));
- end;
- procedure _TMachOSubWriter_.AllocateSpaceForLoadCommands(aStream: TStream);
- var buf : pbyte;
- begin
- fHeader.sizeofcmds:=
- //segment+res section+bss section
- sizeof(_TSegmentCommand_)+sizeof(_TSection_)*2+
- //symbol table and dynamic symbol table commands
- sizeof(TSymtabCommand)+sizeof(TDySymtabCommand)+
- //common header of the three commands
- sizeof(TLoadCommand)*3;
- buf:=GetMem(fHeader.sizeofcmds);
- FillByte(buf^,fHeader.sizeofcmds,0);
- try
- aStream.WriteBuffer(buf^,fHeader.sizeofcmds);
- finally
- FreeMem(buf);
- end;
- end;
- procedure _TMachOSubWriter_.FixLoadCommands(aStream: TStream; aResources : TResources);
- var ldcommand : TLoadCommand;
- segcommand : _TSegmentCommand_;
- symcommand : TSymtabCommand;
- dysymcommand : TDySymtabCommand;
- ressection,bsssection : _TSection_;
- begin
- ldcommand.cmd:=fSegType;
- ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(segcommand)+sizeof(ressection)*2;
- FillByte(segcommand.name[0],16,0);
- segcommand.vmaddr:=0;
- segcommand.vmsize:=fDataCurOfs+sizeof(_ptrtype_)*aResources.Count;
- segcommand.fileoff:=fSectionStart;
- segcommand.filesize:=fDataCurOfs;
- segcommand.maxprot:=VM_PROT_READ or VM_PROT_WRITE;
- segcommand.initprot:=VM_PROT_READ or VM_PROT_WRITE;
- segcommand.nsects:=2;
- segcommand.flags:=0;
- ressection.sectname:=RsrcSectName;
- ressection.segname:=DataSegName;
- ressection.addr:=0;
- ressection.size:=segcommand.filesize;
- ressection.offset:=segcommand.fileoff;
- ressection.align:=fSectAlignment;
- ressection.reloff:=fRelocations.StartOfs;
- ressection.nreloc:=fRelocations.Count;
- ressection.flags:=S_ATTR_LOC_RELOC;
- ressection.reserved1:=0;
- ressection.reserved2:=0;
- bsssection.sectname:=HandlesSectName;
- bsssection.segname:=DataSegName;
- bsssection.addr:=fDataCurOfs;
- bsssection.size:=sizeof(_ptrtype_)*aResources.Count;
- bsssection.offset:=0;
- bsssection.align:=fSectAlignment;
- bsssection.reloff:=0;
- bsssection.nreloc:=0;
- bsssection.flags:=S_ZEROFILL;
- bsssection.reserved1:=0;
- bsssection.reserved2:=0;
- if fOppositeEndianess then
- begin
- ldcommand.cmd:=SwapEndian(ldcommand.cmd);
- ldcommand.cmdsize:=SwapEndian(ldcommand.cmdsize);
- segcommand.vmaddr:=SwapEndian(segcommand.vmaddr);
- segcommand.vmsize:=SwapEndian(segcommand.vmsize);
- segcommand.fileoff:=SwapEndian(segcommand.fileoff);
- segcommand.filesize:=SwapEndian(segcommand.filesize);
- segcommand.maxprot:=SwapEndian(segcommand.maxprot);
- segcommand.initprot:=SwapEndian(segcommand.initprot);
- segcommand.nsects:=SwapEndian(segcommand.nsects);
- segcommand.flags:=SwapEndian(segcommand.flags);
- SwapSection(ressection);
- SwapSection(bsssection);
- end;
- aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
- aStream.WriteBuffer(segcommand,sizeof(segcommand));
- aStream.WriteBuffer(ressection,sizeof(ressection));
- aStream.WriteBuffer(bsssection,sizeof(bsssection));
- ldcommand.cmd:=LC_SYMTAB;
- ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(symcommand);
- symcommand.symoff:=fSymbolTable.StartOfs;
- symcommand.nsyms:=fSymbolTable.Count;
- symcommand.stroff:=fMachOStringTable.StartOfs;
- symcommand.strsize:=NextAligned(fDataAlignment,fMachOStringTable.Size);
- if fOppositeEndianess then
- begin
- ldcommand.cmd:=SwapEndian(ldcommand.cmd);
- ldcommand.cmdsize:=SwapEndian(ldcommand.cmdsize);
- symcommand.symoff:=SwapEndian(symcommand.symoff);
- symcommand.nsyms:=SwapEndian(symcommand.nsyms);
- symcommand.stroff:=SwapEndian(symcommand.stroff);
- symcommand.strsize:=SwapEndian(symcommand.strsize);
- end;
- aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
- aStream.WriteBuffer(symcommand,sizeof(symcommand));
- ldcommand.cmd:=LC_DYSYMTAB;
- ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(dysymcommand);
- dysymcommand.ilocalsym:=0;
- dysymcommand.nlocalsym:=fSymbolTable.LocalCount;
- dysymcommand.iextdefsym:=dysymcommand.ilocalsym+dysymcommand.nlocalsym;
- dysymcommand.nextdefsym:=fSymbolTable.GlobalCount;
- dysymcommand.iundefsym:=dysymcommand.iextdefsym+dysymcommand.nextdefsym;
- dysymcommand.nundefsym:=0;
- dysymcommand.tocoff:=0;
- dysymcommand.ntoc:=0;
- dysymcommand.modtaboff:=0;
- dysymcommand.nmodtab:=0;
- dysymcommand.extrefsymoff:=0;
- dysymcommand.nextrefsyms:=0;
- dysymcommand.indirectsymoff:=0;
- dysymcommand.nindirectsyms:=0;
- dysymcommand.extreloff:=0;
- dysymcommand.nextrel:=0;
- dysymcommand.locreloff:=0;
- dysymcommand.nlocrel:=0;
- if fOppositeEndianess then
- begin
- ldcommand.cmd:=SwapEndian(ldcommand.cmd);
- ldcommand.cmdsize:=SwapEndian(ldcommand.cmdsize);
- dysymcommand.ilocalsym:=SwapEndian(dysymcommand.ilocalsym);
- dysymcommand.nlocalsym:=SwapEndian(dysymcommand.nlocalsym);
- dysymcommand.iextdefsym:=SwapEndian(dysymcommand.iextdefsym);
- dysymcommand.nextdefsym:=SwapEndian(dysymcommand.nextdefsym);
- dysymcommand.iundefsym:=SwapEndian(dysymcommand.iundefsym);
- dysymcommand.nundefsym:=SwapEndian(dysymcommand.nundefsym);
- dysymcommand.tocoff:=SwapEndian(dysymcommand.tocoff);
- dysymcommand.ntoc:=SwapEndian(dysymcommand.ntoc);
- dysymcommand.modtaboff:=SwapEndian(dysymcommand.modtaboff);
- dysymcommand.nmodtab:=SwapEndian(dysymcommand.nmodtab);
- dysymcommand.extrefsymoff:=SwapEndian(dysymcommand.extrefsymoff);
- dysymcommand.nextrefsyms:=SwapEndian(dysymcommand.nextrefsyms);
- dysymcommand.indirectsymoff:=SwapEndian(dysymcommand.indirectsymoff);
- dysymcommand.nindirectsyms:=SwapEndian(dysymcommand.nindirectsyms);
- dysymcommand.extreloff:=SwapEndian(dysymcommand.extreloff);
- dysymcommand.nextrel:=SwapEndian(dysymcommand.nextrel);
- dysymcommand.locreloff:=SwapEndian(dysymcommand.locreloff);
- dysymcommand.nlocrel:=SwapEndian(dysymcommand.nlocrel);
- end;
- aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
- aStream.WriteBuffer(dysymcommand,sizeof(dysymcommand));
- end;
- procedure _TMachOSubWriter_.FixResHeader(aStream : TStream);
- var hdr : _TResHdr_;
- begin
- hdr.handles:=fDataCurOfs;
- if fOppositeEndianess then
- hdr.handles:=SwapEndian(hdr.handles);
- aStream.Seek(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),
- soFromCurrent);
- aStream.WriteBuffer(hdr.handles,sizeof(hdr.handles));
- end;
- constructor _TMachOSubWriter_.Create(aParent : TMachOResourceWriter;
- const aMachineType : TMachOMachineType; const aOppositeEndianess : boolean);
- begin
- inherited Create(aParent, aMachineType,aOppositeEndianess);
- fSymbolTable:=_TMachOSymbolTable_.Create(fMachOStringTable);
- fSymbolTable.OppositeEndianess:=fOppositeEndianess;
- {$IF _TMachOSubWriter_=TMachO32SubWriter}
- fDataAlignment:=4;
- fSectAlignment:=2; //2^2
- fSegType:=LC_SEGMENT;
- {$ELSE}
- fDataAlignment:=8;
- fSectAlignment:=3; //2^3
- fSegType:=LC_SEGMENT_64;
- {$ENDIF}
- end;
|