1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5
6 /* Define the file handles. */
7
8 FILE *source_file;
9 FILE *array_file;
10
11
12 #define ELF_ID_STRING_SIZE 16
13 #define ELF_ARM_MACHINE_TYPE 40
14 #define ELF_EXECUTABLE 2
15
16
17 typedef struct ELF_HEADER_STRUCT
18 {
19 unsigned char elf_header_id_string[ELF_ID_STRING_SIZE];
20 unsigned short elf_header_file_type;
21 unsigned short elf_header_machinge_type;
22 unsigned long elf_header_version;
23 unsigned long elf_header_entry_address;
24 unsigned long elf_header_program_header_offset;
25 unsigned long elf_header_section_header_offset;
26 unsigned long elf_header_processor_flags;
27 unsigned short elf_header_size;
28 unsigned short elf_header_program_header_size;
29 unsigned short elf_header_program_header_entries;
30 unsigned short elf_header_section_header_size;
31 unsigned short elf_header_section_header_entries;
32 unsigned short elf_header_section_string_index;
33 } ELF_HEADER;
34
35
36 typedef struct ELF_PROGRAM_HEADER_STRUCT
37 {
38 unsigned long elf_program_header_type;
39 unsigned long elf_program_header_offset;
40 unsigned long elf_program_header_virtual_address;
41 unsigned long elf_program_header_physical_address;
42 unsigned long elf_program_header_file_size;
43 unsigned long elf_program_header_memory_size;
44 unsigned long elf_program_header_flags;
45 unsigned long elf_program_header_alignment;
46 } ELF_PROGRAM_HEADER;
47
48
49 typedef struct ELF_SECTION_HEADER_STRUCT
50 {
51 unsigned long elf_section_header_name;
52 unsigned long elf_section_header_type;
53 unsigned long elf_section_header_flags;
54 unsigned long elf_section_header_address;
55 unsigned long elf_section_header_offset;
56 unsigned long elf_section_header_size;
57 unsigned long elf_section_header_link;
58 unsigned long elf_section_header_info;
59 unsigned long elf_section_header_alignment;
60 unsigned long elf_section_header_entry_size;
61 } ELF_SECTION_HEADER;
62
63
64 typedef struct ELF_SYMBOL_TABLE_ENTRY_STRUCT
65 {
66 unsigned long elf_symbol_table_entry_name;
67 unsigned long elf_symbol_table_entry_address;
68 unsigned long elf_symbol_table_entry_size;
69 unsigned char elf_symbol_table_entry_info;
70 unsigned char elf_symbol_table_entry_other;
71 unsigned short elf_symbol_table_entry_shndx;
72
73 } ELF_SYMBOL_TABLE_ENTRY;
74
75
76 typedef struct CODE_SECTION_ENTRY_STRUCT
77 {
78 unsigned long code_section_index;
79 unsigned long code_section_address;
80 unsigned long code_section_size;
81 } CODE_SECTION_ENTRY;
82
83
84 /* Define global variables. */
85
86 ELF_HEADER header;
87 ELF_PROGRAM_HEADER *program_header;
88 ELF_SECTION_HEADER *section_header;
89 unsigned char *section_string_table;
90 unsigned char *main_string_table;
91 unsigned long total_symbols;
92 ELF_SYMBOL_TABLE_ENTRY *symbol_table;
93 unsigned long total_functions;
94 ELF_SYMBOL_TABLE_ENTRY *function_table;
95 CODE_SECTION_ENTRY *code_section_array;
96
97
98 /* Define helper functions. */
99
elf_object_read(unsigned long offset,void * object_address,int object_size)100 int elf_object_read(unsigned long offset, void *object_address, int object_size)
101 {
102
103 int i;
104 int alpha;
105 unsigned char *buffer;
106
107 /* Setup the buffer pointer. */
108 buffer = (unsigned char *) object_address;
109
110 /* Seek to the proper position in the file. */
111 fseek(source_file, offset, SEEK_SET);
112
113 /* Read the ELF object. */
114 for (i = 0; i < object_size; i++)
115 {
116 alpha = fgetc(source_file);
117
118 if (alpha == EOF)
119 return(1);
120
121 buffer[i] = (unsigned char) alpha;
122 }
123
124 /* Return success. */
125 return(0);
126 }
127
128
main(int argc,char * argv[])129 int main(int argc, char* argv[])
130 {
131
132 unsigned long i, j, k;
133 unsigned long current_total;
134 unsigned long address;
135 unsigned long size;
136 unsigned long column;
137 unsigned char *code_buffer;
138 unsigned long code_section_index;
139 CODE_SECTION_ENTRY code_section_temp;
140
141
142 /* Determine if the proper number of files are provided. */
143 if (argc != 3)
144 {
145
146 /* Print an error message out and wait for user key hit. */
147 printf("module_to_c_array.exe - Copyright (c) Microsoft Corporation v5.8\n");
148 printf("**** Error: invalid input parameter for module_to_c_array.exe **** \n");
149 printf(" Command Line Should be:\n\n");
150 printf(" > module_to_c_array source_elf_file c_array_file <cr> \n\n");
151 return(1);
152 }
153
154 /* Attempt to open the source file for reading. */
155 source_file = fopen(argv[1], "rb");
156
157 /* Determine if the source file was opened properly. */
158 if (source_file == NULL)
159 {
160
161 /* Print an error message out and wait for user key hit. */
162 printf("**** Error: open failed on source elf file **** \n");
163 printf(" File: %s ", argv[1]);
164 return(2);
165 }
166
167 /* Attempt to open the dump file for writing. */
168 array_file = fopen(argv[2], "w");
169
170 /* Determine if the dump file was opened properly. */
171 if (array_file == NULL)
172 {
173
174 /* Print an error message out and wait for user key hit. */
175 printf("**** Error: open failed on C array file **** \n");
176 printf(" File: %s ", argv[2]);
177 return(3);
178 }
179
180 /* Read the ELF header. */
181 elf_object_read(0, &header, sizeof(header));
182
183 fprintf(array_file, "/**************************** Module-to-C-array Utility *****************************************/\n");
184 fprintf(array_file, "/* */\n");
185 fprintf(array_file, "/* Copyright (c) Microsoft Corporation Version 5.8, build date: 03-01-2018 */\n");
186 fprintf(array_file, "/* */\n");
187 fprintf(array_file, "/************************************************************************************************/\n\n");
188 fprintf(array_file, "/* \n");
189 fprintf(array_file, " Input ELF file: %30s\n", argv[1]);
190 fprintf(array_file, " Output C Array file: %30s\n", argv[2]);
191 fprintf(array_file, "*/\n\n");
192
193 /* Allocate memory for the program header(s). */
194 program_header = malloc(sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries);
195
196 /* Read the program header(s). */
197 elf_object_read(header.elf_header_program_header_offset, program_header, (sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries));
198
199 /* Allocate memory for the section header(s). */
200 section_header = malloc(sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries);
201
202 /* Read the section header(s). */
203 elf_object_read(header.elf_header_section_header_offset, section_header, (sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries));
204
205
206 /* Alocate memory for the section string table. */
207 section_string_table = malloc(section_header[header.elf_header_section_string_index].elf_section_header_size);
208
209 /* Read the section string table. */
210 elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, section_header[header.elf_header_section_string_index].elf_section_header_size);
211
212 /* Allocate memory for the code section array. */
213 code_section_array = malloc(sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries);
214 code_section_index = 0;
215
216 /* Print out the section header(s). */
217 for (i = 0; i < header.elf_header_section_header_entries; i++)
218 {
219
220 /* Determine if this section is a code section and there is a size. */
221 if ((section_header[i].elf_section_header_type == 1) && (section_header[i].elf_section_header_size))
222 {
223
224 /* Check for an-instruction area. */
225 if ((section_header[i].elf_section_header_flags & 0x4) || (section_header[i].elf_section_header_flags & 0x2))
226 {
227 /* Determine if this new section overlaps with an existing section. */
228 for (j = 0; j < code_section_index; j++)
229 {
230 /* Is there an overlap? */
231 if ((section_header[i].elf_section_header_address >= code_section_array[j].code_section_address) &&
232 ((section_header[i].elf_section_header_address+section_header[i].elf_section_header_size + section_header[i].elf_section_header_offset) < (code_section_array[j].code_section_address+code_section_array[j].code_section_size)))
233 {
234 /* New section is within a current section, just disregard it. */
235 break;
236 }
237 }
238
239 /* Determine if we have an overlap. */
240 if (j == code_section_index)
241 {
242
243 /* Yes, we have a code section... save it! */
244 code_section_array[code_section_index].code_section_index = i;
245 code_section_array[code_section_index].code_section_address = section_header[i].elf_section_header_address;
246 code_section_array[code_section_index].code_section_size = section_header[i].elf_section_header_size;
247
248 /* Move to next code section. */
249 code_section_index++;
250 }
251 }
252 }
253 }
254
255 /* Check for no code sections. */
256 if (code_section_index == 0)
257 {
258
259 /* Print an error message out. */
260 printf("**** Error: No code sections found! **** \n");
261
262 fprintf(array_file, "unsigned char module_code[] = {0x00};\n\n");
263
264 /* Close files. */
265 fclose(source_file);
266 fclose(array_file);
267
268 return(4);
269 }
270
271 /* One or more code sections have been found... let's put them in the correct order by address. */
272 i = 0;
273 while (i+1 < code_section_index)
274 {
275
276 /* Make the "ith" entry the lowest address. */
277 j = i + 1;
278 do
279 {
280 /* Is there a new lowest address? */
281 if (code_section_array[j].code_section_address < code_section_array[i].code_section_address)
282 {
283 /* Yes, swap them! */
284 code_section_temp = code_section_array[i];
285 code_section_array[i] = code_section_array[j];
286 code_section_array[j] = code_section_temp;
287 }
288
289 /* Move the inner index. */
290 j++;
291 } while (j < code_section_index);
292
293 /* Move top index. */
294 i++;
295 }
296
297 /* Now print out the sections in a C array. */
298 fprintf(array_file, "unsigned char module_code[] = {\n\n");
299 fprintf(array_file, "/* Address Contents */\n\n");
300
301 address = code_section_array[0].code_section_address;
302 column = 0;
303
304 for (i = 0; i < code_section_index; i++)
305 {
306
307 /* Determine if there is any fill characters between sections. */
308 while (address < code_section_array[i].code_section_address)
309 {
310
311 /* Print out a character with a leading comma, except on the first character. */
312 if (column == 0)
313 fprintf(array_file, "/* 0x%08X */ 0x00", address);
314 else
315 fprintf(array_file, ", 0x00");
316
317 /* Move column forward. */
318 column++;
319
320 /* Are we at the end of the column? */
321 if (column >= 16)
322 {
323 fprintf(array_file, ",\n");
324 column = 0;
325 }
326
327 /* Move address forward. */
328 address++;
329 }
330
331 /* Now allocate memory for the code section. */
332 code_buffer = malloc(code_section_array[i].code_section_size);
333
334 /* Read in the code area. */
335 j = code_section_array[i].code_section_index;
336 elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size);
337
338 /* Write out the contents of this program area. */
339 size = code_section_array[i].code_section_size;
340
341 j = 0;
342 k = 0;
343 while (size)
344 {
345
346 /* Print out a character with a leading comma, except on the first character. */
347 if (column == 0)
348 fprintf(array_file, "/* 0x%08X */ 0x%02X", address, (unsigned int) code_buffer[j]);
349 else
350 fprintf(array_file, ", 0x%02X", (unsigned int) code_buffer[j]);
351
352 /* Move column forward. */
353 column++;
354
355 /* Are we at the end of the column? */
356 if (column >= 16)
357 {
358
359 /* Is this the last byte of the image? */
360 if ((size != 1) || (i+1 != code_section_index))
361 {
362 if (k == 0)
363 {
364 k = code_section_array[i].code_section_index;
365 fprintf(array_file, ", /* SECTION: %s */\n", §ion_string_table[section_header[k].elf_section_header_name]);
366 }
367 else
368 fprintf(array_file, ",\n");
369 }
370 column = 0;
371 }
372
373 /* Move address forward. */
374 address++;
375
376 /* Decrement size. */
377 size--;
378
379 /* Move index into buffer. */
380 j++;
381 }
382 }
383
384 /* Finally, finish the C array containing the module code. */
385 fprintf(array_file, "};\n\n");
386
387 /* Close files. */
388 fclose(source_file);
389 fclose(array_file);
390
391 return 0;
392 }
393