8from ctypes
import create_string_buffer
12FILE_HEADER_RELFLG = 0x1
15FILE_HEADER_LSYMS = 0x8
16FILE_HEADER_AR32WR = 0x100
19SECTION_HEADER_TEXT = 0x20
20SECTION_HEADER_DATA = 0x40
21SECTION_HEADER_BSS = 0x80
33FILE_HEADER_FORMAT =
'HHIIIHH'
34FILE_HEADER_SIZE = calcsize(FILE_HEADER_FORMAT)
43FILE_HEADER_NUM_SECTIONS = 1
44FILE_HEADER_TIMESTAMP = 0
45FILE_HEADER_SIZE_OF_OPTIONAL = 0
46FILE_HEADER_FLAGS = FILE_HEADER_LNNO
61SECTION_HEADER_FORMAT =
'8sIIIIIIHHI'
62SECTION_HEADER_SIZE = calcsize(SECTION_HEADER_FORMAT)
63SECTION_NAME_RODATA = b
'.rodata'
64SECTION_NAME_TEXT = b
'.text'
67SECTION_RAW_DATA_PTR = (
68 FILE_HEADER_SIZE + FILE_HEADER_NUM_SECTIONS * SECTION_HEADER_SIZE)
69SECTION_RELOCATION_PTR = 0x0
70SECTION_LINE_NUMS_PTR = 0x0
71SECTION_NUM_RELOCATION = 0
72SECTION_NUM_LINE_NUMS = 0
89SYMBOL_TABLE_ENTRY_SHORT_LEN = 8
90SYMBOL_TABLE_ENTRY_FORMAT_SHORT =
'8sIhHBB'
91SYMBOL_TABLE_ENTRY_FORMAT_LONG =
'IIIhHBB'
92SYMBOL_TABLE_ENTRY_SIZE = calcsize(SYMBOL_TABLE_ENTRY_FORMAT_SHORT)
93SYMBOL_TABLE_ENTRY_ZEROS = 0x0
94SYMBOL_TABLE_ENTRY_SECTION = 1
95SYMBOL_TABLE_ENTRY_TYPE = 0
96SYMBOL_TABLE_ENTRY_CLASS = 2
97SYMBOL_TABLE_ENTRY_NUM_AUX = 0
99STRING_TABLE_OFFSET = 0x4
101SIZE_LENGTH = calcsize(SIZE_FORMAT)
103SIZE_SYMBOL_FORMAT_X64 =
'Q'
104SIZE_SYMBOL_LENGTH_X64 = calcsize(SIZE_SYMBOL_FORMAT_X64)
108 parser = argparse.ArgumentParser(
109 description=
'Generate a COFF file for binary data.')
110 parser.add_argument(
'--input', dest=
'input', help=
'Path of the input file.')
112 '--output', dest=
'output', help=
'Name of the output file.')
116 help=
'Name of the symbol for the binary data')
118 '--size_symbol_name',
120 help=
'Name of the symbol for the size of the binary data')
121 parser.add_argument(
'--arch', dest=
'arch')
123 '--executable', dest=
'executable', action=
'store_true', default=
False)
125 args = parser.parse_args()
126 use_64_bit = args.arch
in [
'x64',
'arm64',
'riscv64']
128 with open(args.input,
'rb')
as f:
129 section_data = f.read()
135 section_size =
len(section_data)
136 includes_size_name = (args.size_name !=
None)
139 symbol_prefix = b
'_' if args.arch ==
'x86' else b
''
140 num_symbols = 2
if includes_size_name
else 1
141 symbol_name = symbol_prefix + args.symbol_name.encode()
142 size_symbol_name =
None
143 if (includes_size_name):
144 size_symbol = args.size_name
if args.size_name
else args.symbol_name +
"Size"
145 size_symbol_name = symbol_prefix + size_symbol.encode()
147 size_symbol_format = SIZE_SYMBOL_FORMAT_X64
if use_64_bit
else SIZE_FORMAT
148 size_symbol_size = SIZE_SYMBOL_LENGTH_X64
if use_64_bit
else SIZE_LENGTH
151 symbol_table_ptr = (FILE_HEADER_SIZE + SECTION_HEADER_SIZE + section_size +
157 long_symbol_name =
False
158 long_size_symbol_name =
False
159 if (
len(symbol_name) > SYMBOL_TABLE_ENTRY_SHORT_LEN):
160 string_table_len +=
len(symbol_name) + 1
161 long_symbol_name =
True
163 if (includes_size_name
and
164 (
len(size_symbol_name) > SYMBOL_TABLE_ENTRY_SHORT_LEN)):
165 string_table_len +=
len(size_symbol_name) + 1
166 long_size_symbol_name =
True
170 buff = create_string_buffer(
171 FILE_HEADER_SIZE + SECTION_HEADER_SIZE + section_size +
172 num_symbols * SYMBOL_TABLE_ENTRY_SIZE + SIZE_LENGTH + size_symbol_size +
175 FILE_HEADER_MAGIC = FILE_HEADER_MAGICS[args.arch]
179 pack_into(FILE_HEADER_FORMAT, buff, offset, FILE_HEADER_MAGIC,
180 FILE_HEADER_NUM_SECTIONS, FILE_HEADER_TIMESTAMP, symbol_table_ptr,
181 num_symbols, FILE_HEADER_SIZE_OF_OPTIONAL, FILE_HEADER_FLAGS)
182 offset += FILE_HEADER_SIZE
184 section_name = SECTION_NAME_RODATA
185 section_type = SECTION_HEADER_DATA
187 section_name = SECTION_NAME_TEXT
188 section_type = SECTION_HEADER_TEXT
191 pack_into(SECTION_HEADER_FORMAT, buff, offset, section_name, SECTION_PADDR,
192 SECTION_VADDR, section_size + size_symbol_size,
193 SECTION_RAW_DATA_PTR, SECTION_RELOCATION_PTR,
194 SECTION_LINE_NUMS_PTR, SECTION_NUM_RELOCATION,
195 SECTION_NUM_LINE_NUMS, section_type)
196 offset += SECTION_HEADER_SIZE
199 buff[offset:offset + section_size] = section_data
200 offset += section_size
203 pack_into(size_symbol_format, buff, offset, section_size)
204 offset += size_symbol_size
210 string_table_offset = STRING_TABLE_OFFSET
212 pack_into(SYMBOL_TABLE_ENTRY_FORMAT_LONG, buff, offset,
213 SYMBOL_TABLE_ENTRY_ZEROS, string_table_offset, 0x0,
214 SYMBOL_TABLE_ENTRY_SECTION, SYMBOL_TABLE_ENTRY_TYPE,
215 SYMBOL_TABLE_ENTRY_CLASS, SYMBOL_TABLE_ENTRY_NUM_AUX)
216 string_table_offset +=
len(symbol_name) + 1
218 pack_into(SYMBOL_TABLE_ENTRY_FORMAT_SHORT, buff, offset, symbol_name,
219 0x0, SYMBOL_TABLE_ENTRY_SECTION, SYMBOL_TABLE_ENTRY_TYPE,
220 SYMBOL_TABLE_ENTRY_CLASS, SYMBOL_TABLE_ENTRY_NUM_AUX)
221 offset += SYMBOL_TABLE_ENTRY_SIZE
223 if includes_size_name:
225 if long_size_symbol_name:
226 pack_into(SYMBOL_TABLE_ENTRY_FORMAT_LONG, buff, offset,
227 SYMBOL_TABLE_ENTRY_ZEROS, string_table_offset,
228 section_size, SYMBOL_TABLE_ENTRY_SECTION,
229 SYMBOL_TABLE_ENTRY_TYPE, SYMBOL_TABLE_ENTRY_CLASS,
230 SYMBOL_TABLE_ENTRY_NUM_AUX)
232 pack_into(SYMBOL_TABLE_ENTRY_FORMAT_SHORT, buff, offset,
233 symbol_name, section_size, SYMBOL_TABLE_ENTRY_SECTION,
234 SYMBOL_TABLE_ENTRY_TYPE, SYMBOL_TABLE_ENTRY_CLASS,
235 SYMBOL_TABLE_ENTRY_NUM_AUX)
236 offset += SYMBOL_TABLE_ENTRY_SIZE
238 pack_into(SIZE_FORMAT, buff, offset, string_table_len + SIZE_LENGTH)
239 offset += SIZE_LENGTH
243 symbol_len =
len(symbol_name)
244 buff[offset:offset + symbol_len] = symbol_name
249 if includes_size_name
and long_size_symbol_name:
250 symbol_len =
len(size_symbol_name)
251 buff[offset:offset + symbol_len] = size_symbol_name
256 with open(args.output,
'wb')
as f:
260if __name__ ==
'__main__':