|
| 1 | +unit cofflib; |
| 2 | + |
| 3 | +{$mode objfpc}{$H+} |
| 4 | + |
| 5 | +interface |
| 6 | +uses |
| 7 | + Classes, SysUtils,DateUtils; |
| 8 | + |
| 9 | +Function CreateCOFF(inFile,OutFile,PublicName,publicsizename : String; UseFileSizeSymbol : Boolean) : word; |
| 10 | + |
| 11 | +implementation |
| 12 | + |
| 13 | +type |
| 14 | + TCOFFHeader = packed record |
| 15 | + Machine: Word; |
| 16 | + NumberOfSections: Word; |
| 17 | + TimeDateStamp: LongWord; |
| 18 | + PointerToSymbolTable: LongWord; |
| 19 | + NumberOfSymbols: LongWord; |
| 20 | + SizeOfOptionalHeader: Word; |
| 21 | + Characteristics: Word; |
| 22 | + end; |
| 23 | + |
| 24 | + TCOFFSectionHeader = packed record |
| 25 | + Name: array[0..7] of Char; |
| 26 | + VirtualSize: LongWord; |
| 27 | + VirtualAddress: LongWord; |
| 28 | + SizeOfRawData: LongWord; |
| 29 | + PointerToRawData: LongWord; |
| 30 | + PointerToRelocations: LongWord; |
| 31 | + PointerToLinenumbers: LongWord; |
| 32 | + NumberOfRelocations: Word; |
| 33 | + NumberOfLinenumbers: Word; |
| 34 | + Characteristics: LongWord; |
| 35 | + end; |
| 36 | + |
| 37 | + TCOFFSymbolTable = packed record |
| 38 | + PointerToName : LongWord; //0 by default |
| 39 | + Offset : LongWord; //first entry starts at 4 offset; there is longword size of string table |
| 40 | + Value : LongWord; //for name_size put value in this and SectionNumber = $FFFF |
| 41 | + SectionNumber : Word; // should be 1 for .data |
| 42 | + SType : Word; // should be 0 for name |
| 43 | + StorageClass : Byte; // 2 |
| 44 | + AuxSymbols : Byte; // 0 |
| 45 | + end; |
| 46 | + |
| 47 | + TCOFFStringTable = packed record |
| 48 | + Length : LongWord; // includes this field (4 bytes) as part of string table length = all strings added up + 4 bytes |
| 49 | + Names : array[0..255] of char; // just storing 2 strings - going to limit names to 20 chars each |
| 50 | + end; |
| 51 | + |
| 52 | + TCOFFSymbolTableArray = array[1..2] of TCOFFSymbolTable; |
| 53 | + var |
| 54 | + coff_header: TCOFFHeader; |
| 55 | + section_headers: TCOFFSectionHeader; |
| 56 | + section_data: TMemoryStream; |
| 57 | + section_data_size: LongWord; |
| 58 | + out_file: TFileStream; |
| 59 | + string_symbol_table : TCOFFSymbolTableArray; |
| 60 | + string_table : TCOFFStringTable; |
| 61 | + |
| 62 | +procedure SetHeader(var H : TCOFFHeader;fsize : LongWord;UseFileSizeSymbol : boolean); |
| 63 | +begin |
| 64 | + // Set the COFF header fields |
| 65 | + H.Machine := $14C; |
| 66 | + H.NumberOfSections := 1; |
| 67 | + H.TimeDateStamp := DateTimeToUnix(Now); |
| 68 | + H.PointerToSymbolTable := SizeOf(TCOFFHeader) + SizeOf(TCOFFSectionHeader)+((4+fsize+15) div 16)*16; // rounded to LongWords |
| 69 | + if UseFileSizeSymbol then H.NumberOfSymbols := 2 else H.NumberOfSymbols := 1; //name and name_size |
| 70 | + H.SizeOfOptionalHeader := 0; |
| 71 | + H.Characteristics := $105; |
| 72 | +end; |
| 73 | + |
| 74 | +procedure setsectionheader(var SH : TCOFFSectionHeader; fsize : LongWord); |
| 75 | +begin |
| 76 | + // Set the section header fields |
| 77 | + SH.Name := '.data'#0#0#0; //pad with nulls |
| 78 | + SH.VirtualSize := 0; |
| 79 | + SH.VirtualAddress := 0; |
| 80 | + SH.SizeOfRawData := ((4+fsize+15) div 16)*16 ; // ((4 + size +15 ) div 16) *16 |
| 81 | + SH.PointerToRawData := SizeOf(TCOFFHeader) + SizeOf(TCOFFSectionHeader); //just after the headers |
| 82 | + SH.PointerToRelocations := 0; |
| 83 | + SH.PointerToLinenumbers := 0; |
| 84 | + SH.NumberOfRelocations := 0; |
| 85 | + SH.NumberOfLinenumbers := 0; |
| 86 | + SH.Characteristics := $40; |
| 87 | +end; |
| 88 | + |
| 89 | +procedure SetStringValues(var STA : TCOFFSymbolTableArray;stable : word;offset,value : longword;sectionnumber,stype :word; StorageClass,AuxSymbols : byte); |
| 90 | +begin |
| 91 | + STA[stable].PointerToName:=0; |
| 92 | + STA[stable].Offset:=offset; |
| 93 | + STA[stable].value:=value; |
| 94 | + STA[stable].sectionnumber:=sectionnumber; |
| 95 | + STA[stable].stype:=stype; |
| 96 | + STA[stable].storageclass:=storageclass; |
| 97 | + STA[stable].auxsymbols:=auxsymbols; |
| 98 | +end; |
| 99 | + |
| 100 | +procedure SetStringData(var STA : TCOFFSymbolTableArray; |
| 101 | + var STRT : TCOFFStringTable; |
| 102 | + sname,name_size : shortstring; fsize : longword; UseFileSizeSymbol : boolean); |
| 103 | +begin |
| 104 | + FillChar(STRT.names,sizeof(STRT.names),0); //clear the string tables with nulls |
| 105 | + |
| 106 | + SetStringValues(STA,1,4,4,1,0,2,0); |
| 107 | + SetStringValues(STA,2,4+length(sname)+1,fsize,$FFFF,0,2,0); |
| 108 | + if UseFileSizeSymbol then |
| 109 | + STRT.Length:=4+length(sname)+1+length(name_size)+1 |
| 110 | + else |
| 111 | + STRT.Length:=4+length(sname)+1; |
| 112 | + |
| 113 | + Move(sname[1],STRT.names[0],length(sname)); |
| 114 | + if UseFileSizeSymbol then Move(name_size[1],STRT.names[length(sname)+1],length(name_size)); |
| 115 | +end; |
| 116 | + |
| 117 | +procedure WriteHeader(var F : File;var H : TCOFFHeader); |
| 118 | +begin |
| 119 | + Blockwrite(F,H, SizeOf(H)); |
| 120 | +end; |
| 121 | + |
| 122 | +procedure WriteSectionHeader(var F : File;var SH : TCOFFSectionHeader); |
| 123 | +begin |
| 124 | + Blockwrite(F,SH, SizeOf(SH)); |
| 125 | +end; |
| 126 | + |
| 127 | +procedure WriteSectionData(var F : File;var Data; DataSize,rawsize : LongWord); //rawsize is the longword alligned size |
| 128 | +var |
| 129 | + startpad : longword =0; |
| 130 | + zeropadlength : longword; |
| 131 | + padbytes : array[1..32] of byte; |
| 132 | +begin |
| 133 | + Blockwrite(F,startpad,sizeof(startpad)); |
| 134 | + Blockwrite(F,Data, DataSize); |
| 135 | + zeropadlength:=rawsize-DataSize-sizeof(startpad); |
| 136 | + FillChar(padbytes,sizeof(padbytes),0); |
| 137 | + Blockwrite(F,padbytes,zeropadlength); |
| 138 | +end; |
| 139 | + |
| 140 | +procedure WriteSymbolTable(var F:File;var STA : TCOFFSymbolTableArray;UseFileSizeSymbol : Boolean); |
| 141 | +begin |
| 142 | + if UseFileSizeSymbol then |
| 143 | + Blockwrite(F,STA,sizeof(STA)) |
| 144 | + else |
| 145 | + Blockwrite(F,STA[1],sizeof(STA[1])); |
| 146 | +end; |
| 147 | + |
| 148 | +procedure WriteStringTable(var F:File;var STRT : TCOFFStringTable); |
| 149 | +begin |
| 150 | + Blockwrite(F,STRT,STRT.length); |
| 151 | +end; |
| 152 | + |
| 153 | +Function CreateCOFF(inFile,OutFile,PublicName,publicsizename : String; UseFileSizeSymbol : Boolean) : word; |
| 154 | +var |
| 155 | + inF,OutF : File; |
| 156 | + error : word; |
| 157 | + InFileSize : Longword; |
| 158 | + H : TCOFFHeader; |
| 159 | + SH : TCOFFSectionHeader; |
| 160 | + STA : TCOFFSymbolTableArray; |
| 161 | + STRT : TCOFFStringTable; |
| 162 | + Data : Pointer; |
| 163 | +begin |
| 164 | +{$I-} |
| 165 | + Assign(inF,inFile); |
| 166 | + Reset(inF,1); |
| 167 | + InFileSize:=FileSize(inF); |
| 168 | + GetMem(Data,InFileSize); |
| 169 | + if Data<>NIL then |
| 170 | + begin |
| 171 | + Blockread(inF,Data^,InFileSize); |
| 172 | + |
| 173 | + SetHeader(H,InFileSize,UseFileSizeSymbol); |
| 174 | + SetSectionHeader(SH,InFileSize); |
| 175 | + SetStringData(STA,STRT,PublicName,PublicSizeName,InFileSize,UseFileSizeSymbol); |
| 176 | + |
| 177 | + Assign(outF,OutFile); |
| 178 | + Rewrite(outF,1); |
| 179 | + |
| 180 | + WriteHeader(outF,H); |
| 181 | + WriteSectionHeader(outF,SH); |
| 182 | + WriteSectionData(outF,Data^,InFileSize,SH.SizeOfRawData); |
| 183 | + WriteSymbolTable(outF,STA,UseFileSizeSymbol); |
| 184 | + WriteStringTable(outF,STRT); |
| 185 | + |
| 186 | + close(outF); |
| 187 | + FreeMem(Data,InFileSize); |
| 188 | + end; |
| 189 | + close(inF); |
| 190 | +{$I+} |
| 191 | + result:=IORESULT; |
| 192 | +end; |
| 193 | + |
| 194 | + |
| 195 | +begin |
| 196 | + |
| 197 | +end. |
| 198 | + |
0 commit comments