Moved ref frame calculations
[libvpx.git] / build / make / obj_int_extract.c
blobe01870f27a249c8a85b6890e6d89b9c4d3f17c97
1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
12 #include <stdio.h>
13 #include <stdlib.h>
15 #include "vpx_config.h"
17 #if defined(_MSC_VER)
18 #include <io.h>
19 #include <share.h>
20 #include "vpx/vpx_integer.h"
21 #else
22 #include <stdint.h>
23 #include <unistd.h>
24 #endif
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <stdarg.h>
32 typedef enum
34 OUTPUT_FMT_PLAIN,
35 OUTPUT_FMT_RVDS,
36 OUTPUT_FMT_GAS,
37 } output_fmt_t;
39 int log_msg(const char *fmt, ...)
41 int res;
42 va_list ap;
43 va_start(ap, fmt);
44 res = vfprintf(stderr, fmt, ap);
45 va_end(ap);
46 return res;
49 #if defined(__GNUC__) && __GNUC__
51 #if defined(__MACH__)
53 #include <mach-o/loader.h>
54 #include <mach-o/nlist.h>
56 int parse_macho(uint8_t *base_buf, size_t sz)
58 int i, j;
59 struct mach_header header;
60 uint8_t *buf = base_buf;
61 int base_data_section = 0;
63 memcpy(&header, buf, sizeof(struct mach_header));
64 buf += sizeof(struct mach_header);
66 if (header.magic != MH_MAGIC)
68 log_msg("Bad magic number for object file. 0x%x expected, 0x%x found.\n",
69 header.magic, MH_MAGIC);
70 goto bail;
73 if (header.cputype != CPU_TYPE_ARM)
75 log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_ARM.\n");
76 goto bail;
79 if (header.filetype != MH_OBJECT)
81 log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
82 goto bail;
85 for (i = 0; i < header.ncmds; i++)
87 struct load_command lc;
88 struct symtab_command sc;
89 struct segment_command seg_c;
91 memcpy(&lc, buf, sizeof(struct load_command));
93 if (lc.cmd == LC_SEGMENT)
95 uint8_t *seg_buf = buf;
96 struct section s;
98 memcpy(&seg_c, buf, sizeof(struct segment_command));
100 seg_buf += sizeof(struct segment_command);
102 for (j = 0; j < seg_c.nsects; j++)
104 memcpy(&s, seg_buf + (j * sizeof(struct section)), sizeof(struct section));
106 // Need to get this offset which is the start of the symbol table
107 // before matching the strings up with symbols.
108 base_data_section = s.offset;
111 else if (lc.cmd == LC_SYMTAB)
113 uint8_t *sym_buf = base_buf;
114 uint8_t *str_buf = base_buf;
116 if (base_data_section != 0)
118 memcpy(&sc, buf, sizeof(struct symtab_command));
120 if (sc.cmdsize != sizeof(struct symtab_command))
121 log_msg("Can't find symbol table!\n");
123 sym_buf += sc.symoff;
124 str_buf += sc.stroff;
126 for (j = 0; j < sc.nsyms; j++)
128 struct nlist nl;
129 int val;
131 memcpy(&nl, sym_buf + (j * sizeof(struct nlist)), sizeof(struct nlist));
133 val = *((int *)(base_buf + base_data_section + nl.n_value));
135 // Location of string is cacluated each time from the
136 // start of the string buffer. On darwin the symbols
137 // are prefixed by "_". On other platforms it is not
138 // so it needs to be removed. That is the reason for
139 // the +1.
140 printf("%-40s EQU %5d\n", str_buf + nl.n_un.n_strx + 1, val);
145 buf += lc.cmdsize;
148 return 0;
149 bail:
150 return 1;
154 int main(int argc, char **argv)
156 int fd;
157 char *f;
158 struct stat stat_buf;
159 uint8_t *file_buf;
160 int res;
162 if (argc < 2 || argc > 3)
164 fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
165 fprintf(stderr, " <obj file>\tMachO format object file to parse\n");
166 fprintf(stderr, "Output Formats:\n");
167 fprintf(stderr, " gas - compatible with GNU assembler\n");
168 fprintf(stderr, " rvds - compatible with armasm\n");
169 goto bail;
172 f = argv[2];
174 if (!((!strcmp(argv[1], "rvds")) || (!strcmp(argv[1], "gas"))))
175 f = argv[1];
177 fd = open(f, O_RDONLY);
179 if (fd < 0)
181 perror("Unable to open file");
182 goto bail;
185 if (fstat(fd, &stat_buf))
187 perror("stat");
188 goto bail;
191 file_buf = malloc(stat_buf.st_size);
193 if (!file_buf)
195 perror("malloc");
196 goto bail;
199 if (read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
201 perror("read");
202 goto bail;
205 if (close(fd))
207 perror("close");
208 goto bail;
211 res = parse_macho(file_buf, stat_buf.st_size);
212 free(file_buf);
214 if (!res)
215 return EXIT_SUCCESS;
217 bail:
218 return EXIT_FAILURE;
221 #else
222 #include "elf.h"
224 #define COPY_STRUCT(dst, buf, ofst, sz) do {\
225 if(ofst + sizeof((*(dst))) > sz) goto bail;\
226 memcpy(dst, buf+ofst, sizeof((*(dst))));\
227 } while(0)
229 #define ENDIAN_ASSIGN(val, memb) do {\
230 if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
231 (val) = (memb);\
232 } while(0)
234 #define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
235 ENDIAN_ASSIGN(memb, memb);\
236 } while(0)
238 typedef struct
240 uint8_t *buf; /* Buffer containing ELF data */
241 size_t sz; /* Buffer size */
242 int le_data; /* Data is little-endian */
243 Elf32_Ehdr hdr;
244 } elf_obj_t;
246 int parse_elf32_header(elf_obj_t *elf)
248 int res;
249 /* Verify ELF32 header */
250 COPY_STRUCT(&elf->hdr, elf->buf, 0, elf->sz);
251 res = elf->hdr.e_ident[EI_MAG0] == ELFMAG0;
252 res &= elf->hdr.e_ident[EI_MAG1] == ELFMAG1;
253 res &= elf->hdr.e_ident[EI_MAG2] == ELFMAG2;
254 res &= elf->hdr.e_ident[EI_MAG3] == ELFMAG3;
255 res &= elf->hdr.e_ident[EI_CLASS] == ELFCLASS32;
256 res &= elf->hdr.e_ident[EI_DATA] == ELFDATA2LSB
257 || elf->hdr.e_ident[EI_DATA] == ELFDATA2MSB;
259 if (!res) goto bail;
261 elf->le_data = elf->hdr.e_ident[EI_DATA] == ELFDATA2LSB;
263 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_type);
264 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_machine);
265 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_version);
266 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_entry);
267 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phoff);
268 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shoff);
269 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_flags);
270 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_ehsize);
271 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phentsize);
272 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phnum);
273 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shentsize);
274 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shnum);
275 ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shstrndx);
276 return 0;
277 bail:
278 return 1;
281 int parse_elf32_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr)
283 if (idx >= elf->hdr.e_shnum)
284 goto bail;
286 COPY_STRUCT(hdr, elf->buf, elf->hdr.e_shoff + idx * elf->hdr.e_shentsize,
287 elf->sz);
288 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_name);
289 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_type);
290 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_flags);
291 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_addr);
292 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_offset);
293 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_size);
294 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_link);
295 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_info);
296 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_addralign);
297 ENDIAN_ASSIGN_IN_PLACE(hdr->sh_entsize);
298 return 0;
299 bail:
300 return 1;
303 char *parse_elf32_string_table(elf_obj_t *elf, int s_idx, int idx)
305 Elf32_Shdr shdr;
307 if (parse_elf32_section(elf, s_idx, &shdr))
309 log_msg("Failed to parse ELF string table: section %d, index %d\n",
310 s_idx, idx);
311 return "";
314 return (char *)(elf->buf + shdr.sh_offset + idx);
317 int parse_elf32_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym)
319 COPY_STRUCT(sym, elf->buf, ofst, elf->sz);
320 ENDIAN_ASSIGN_IN_PLACE(sym->st_name);
321 ENDIAN_ASSIGN_IN_PLACE(sym->st_value);
322 ENDIAN_ASSIGN_IN_PLACE(sym->st_size);
323 ENDIAN_ASSIGN_IN_PLACE(sym->st_info);
324 ENDIAN_ASSIGN_IN_PLACE(sym->st_other);
325 ENDIAN_ASSIGN_IN_PLACE(sym->st_shndx);
326 return 0;
327 bail:
328 return 1;
331 int parse_elf32(uint8_t *buf, size_t sz, output_fmt_t mode)
333 elf_obj_t elf;
334 Elf32_Shdr shdr;
335 unsigned int ofst;
336 int i;
337 Elf32_Off strtab_off; /* save String Table offset for later use */
339 memset(&elf, 0, sizeof(elf));
340 elf.buf = buf;
341 elf.sz = sz;
343 /* Parse Header */
344 if (parse_elf32_header(&elf))
346 log_msg("Parse error: File does not appear to be valid ELF32\n");
347 return 1;
350 for (i = 0; i < elf.hdr.e_shnum; i++)
352 parse_elf32_section(&elf, i, &shdr);
354 if (shdr.sh_type == SHT_STRTAB)
356 char strtsb_name[128];
358 strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
360 if (!(strcmp(strtsb_name, ".shstrtab")))
362 log_msg("found section: %s\n", strtsb_name);
363 strtab_off = shdr.sh_offset;
364 break;
369 /* Parse all Symbol Tables */
370 for (i = 0; i < elf.hdr.e_shnum; i++)
373 parse_elf32_section(&elf, i, &shdr);
375 if (shdr.sh_type == SHT_SYMTAB)
377 for (ofst = shdr.sh_offset;
378 ofst < shdr.sh_offset + shdr.sh_size;
379 ofst += shdr.sh_entsize)
381 Elf32_Sym sym;
383 parse_elf32_symbol(&elf, ofst, &sym);
385 /* For all OBJECTS (data objects), extract the value from the
386 * proper data segment.
388 if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
389 log_msg("found data object %s\n",
390 parse_elf32_string_table(&elf,
391 shdr.sh_link,
392 sym.st_name));
394 if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
395 && sym.st_size == 4)
397 Elf32_Shdr dhdr;
398 int32_t val;
399 char section_name[128];
401 parse_elf32_section(&elf, sym.st_shndx, &dhdr);
403 /* For explanition - refer to _MSC_VER version of code */
404 strcpy(section_name, (char *)(elf.buf + strtab_off + dhdr.sh_name));
405 log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type);
407 if (!(strcmp(section_name, ".bss")))
409 val = 0;
411 else
413 memcpy(&val,
414 elf.buf + dhdr.sh_offset + sym.st_value,
415 sizeof(val));
418 if (!elf.le_data)
420 log_msg("Big Endian data not supported yet!\n");
421 goto bail;
424 switch (mode)
426 case OUTPUT_FMT_RVDS:
427 printf("%-40s EQU %5d\n",
428 parse_elf32_string_table(&elf,
429 shdr.sh_link,
430 sym.st_name),
431 val);
432 break;
433 case OUTPUT_FMT_GAS:
434 printf(".equ %-40s, %5d\n",
435 parse_elf32_string_table(&elf,
436 shdr.sh_link,
437 sym.st_name),
438 val);
439 break;
440 default:
441 printf("%s = %d\n",
442 parse_elf32_string_table(&elf,
443 shdr.sh_link,
444 sym.st_name),
445 val);
452 if (mode == OUTPUT_FMT_RVDS)
453 printf(" END\n");
455 return 0;
456 bail:
457 log_msg("Parse error: File does not appear to be valid ELF32\n");
458 return 1;
461 int main(int argc, char **argv)
463 int fd;
464 output_fmt_t mode;
465 char *f;
466 struct stat stat_buf;
467 uint8_t *file_buf;
468 int res;
470 if (argc < 2 || argc > 3)
472 fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
473 fprintf(stderr, " <obj file>\tELF format object file to parse\n");
474 fprintf(stderr, "Output Formats:\n");
475 fprintf(stderr, " gas - compatible with GNU assembler\n");
476 fprintf(stderr, " rvds - compatible with armasm\n");
477 goto bail;
480 f = argv[2];
482 if (!strcmp(argv[1], "rvds"))
483 mode = OUTPUT_FMT_RVDS;
484 else if (!strcmp(argv[1], "gas"))
485 mode = OUTPUT_FMT_GAS;
486 else
487 f = argv[1];
490 fd = open(f, O_RDONLY);
492 if (fd < 0)
494 perror("Unable to open file");
495 goto bail;
498 if (fstat(fd, &stat_buf))
500 perror("stat");
501 goto bail;
504 file_buf = malloc(stat_buf.st_size);
506 if (!file_buf)
508 perror("malloc");
509 goto bail;
512 if (read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
514 perror("read");
515 goto bail;
518 if (close(fd))
520 perror("close");
521 goto bail;
524 res = parse_elf32(file_buf, stat_buf.st_size, mode);
525 //res = parse_coff(file_buf, stat_buf.st_size);
526 free(file_buf);
528 if (!res)
529 return EXIT_SUCCESS;
531 bail:
532 return EXIT_FAILURE;
534 #endif
535 #endif
538 #if defined(_MSC_VER)
539 /* See "Microsoft Portable Executable and Common Object File Format Specification"
540 for reference.
542 #define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
543 #define get_le16(x) ((*(x)) | (*(x+1)) << 8)
545 int parse_coff(unsigned __int8 *buf, size_t sz)
547 unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
548 unsigned int sectionrawdata_ptr;
549 unsigned int i;
550 unsigned __int8 *ptr;
551 unsigned __int32 symoffset;
552 FILE *fp;
554 char **sectionlist; //this array holds all section names in their correct order.
555 //it is used to check if the symbol is in .bss or .data section.
557 nsections = get_le16(buf + 2);
558 symtab_ptr = get_le32(buf + 8);
559 symtab_sz = get_le32(buf + 12);
560 strtab_ptr = symtab_ptr + symtab_sz * 18;
562 if (nsections > 96)
563 goto bail;
565 sectionlist = malloc(nsections * sizeof * sectionlist);
567 //log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
570 The size of optional header is always zero for an obj file. So, the section header
571 follows the file header immediately.
574 ptr = buf + 20; //section header
576 for (i = 0; i < nsections; i++)
578 char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
579 strncpy(sectionname, ptr, 8);
580 //log_msg("COFF: Parsing section %s\n",sectionname);
582 sectionlist[i] = malloc(strlen(sectionname) + 1);
583 strcpy(sectionlist[i], sectionname);
585 if (!strcmp(sectionname, ".data")) sectionrawdata_ptr = get_le32(ptr + 20);
587 ptr += 40;
590 //log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
591 //log_msg("COFF: raw data pointer ofset for section .data is %u\n", sectionrawdata_ptr);
593 fp = fopen("vpx_asm_offsets.asm", "w");
595 if (fp == NULL)
597 perror("open file");
598 goto bail;
601 /* The compiler puts the data with non-zero offset in .data section, but puts the data with
602 zero offset in .bss section. So, if the data in in .bss section, set offset=0.
603 Note from Wiki: In an object module compiled from C, the bss section contains
604 the local variables (but not functions) that were declared with the static keyword,
605 except for those with non-zero initial values. (In C, static variables are initialized
606 to zero by default.) It also contains the non-local (both extern and static) variables
607 that are also initialized to zero (either explicitly or by default).
609 //move to symbol table
610 /* COFF symbol table:
611 offset field
612 0 Name(*)
613 8 Value
614 12 SectionNumber
615 14 Type
616 16 StorageClass
617 17 NumberOfAuxSymbols
619 ptr = buf + symtab_ptr;
621 for (i = 0; i < symtab_sz; i++)
623 __int16 section = get_le16(ptr + 12); //section number
625 if (section > 0 && ptr[16] == 2)
627 //if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
629 if (get_le32(ptr))
631 char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
632 strncpy(name, ptr, 8);
633 //log_msg("COFF: Parsing symbol %s\n",name);
634 fprintf(fp, "%-40s EQU ", name);
636 else
638 //log_msg("COFF: Parsing symbol %s\n",
639 // buf + strtab_ptr + get_le32(ptr+4));
640 fprintf(fp, "%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
643 if (!(strcmp(sectionlist[section-1], ".bss")))
645 symoffset = 0;
647 else
649 symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
652 //log_msg(" Section: %d\n",section);
653 //log_msg(" Class: %d\n",ptr[16]);
654 //log_msg(" Address: %u\n",get_le32(ptr+8));
655 //log_msg(" Offset: %u\n", symoffset);
657 fprintf(fp, "%5d\n", symoffset);
660 ptr += 18;
663 fprintf(fp, " END\n");
664 fclose(fp);
666 for (i = 0; i < nsections; i++)
668 free(sectionlist[i]);
671 free(sectionlist);
673 return 0;
674 bail:
676 for (i = 0; i < nsections; i++)
678 free(sectionlist[i]);
681 free(sectionlist);
683 return 1;
686 int main(int argc, char **argv)
688 int fd;
689 output_fmt_t mode;
690 const char *f;
691 struct _stat stat_buf;
692 unsigned __int8 *file_buf;
693 int res;
695 if (argc < 2 || argc > 3)
697 fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
698 fprintf(stderr, " <obj file>\tELF format object file to parse\n");
699 fprintf(stderr, "Output Formats:\n");
700 fprintf(stderr, " gas - compatible with GNU assembler\n");
701 fprintf(stderr, " rvds - compatible with armasm\n");
702 goto bail;
705 f = argv[2];
707 if (!strcmp(argv[1], "rvds"))
708 mode = OUTPUT_FMT_RVDS;
709 else if (!strcmp(argv[1], "gas"))
710 mode = OUTPUT_FMT_GAS;
711 else
712 f = argv[1];
714 if (_sopen_s(&fd, f, _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE))
716 perror("Unable to open file");
717 goto bail;
720 if (_fstat(fd, &stat_buf))
722 perror("stat");
723 goto bail;
726 file_buf = malloc(stat_buf.st_size);
728 if (!file_buf)
730 perror("malloc");
731 goto bail;
734 if (_read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
736 perror("read");
737 goto bail;
740 if (_close(fd))
742 perror("close");
743 goto bail;
746 res = parse_coff(file_buf, stat_buf.st_size);
748 free(file_buf);
750 if (!res)
751 return EXIT_SUCCESS;
753 bail:
754 return EXIT_FAILURE;
756 #endif