media/libvpx/build/make/obj_int_extract.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/build/make/obj_int_extract.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,827 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +
    1.15 +#include <stdarg.h>
    1.16 +#include <stdio.h>
    1.17 +#include <stdlib.h>
    1.18 +#include <string.h>
    1.19 +
    1.20 +#include "vpx_config.h"
    1.21 +#include "vpx/vpx_integer.h"
    1.22 +
    1.23 +typedef enum {
    1.24 +  OUTPUT_FMT_PLAIN,
    1.25 +  OUTPUT_FMT_RVDS,
    1.26 +  OUTPUT_FMT_GAS,
    1.27 +} output_fmt_t;
    1.28 +
    1.29 +int log_msg(const char *fmt, ...) {
    1.30 +  int res;
    1.31 +  va_list ap;
    1.32 +  va_start(ap, fmt);
    1.33 +  res = vfprintf(stderr, fmt, ap);
    1.34 +  va_end(ap);
    1.35 +  return res;
    1.36 +}
    1.37 +
    1.38 +#if defined(__GNUC__) && __GNUC__
    1.39 +#if defined(__MACH__)
    1.40 +
    1.41 +#include <mach-o/loader.h>
    1.42 +#include <mach-o/nlist.h>
    1.43 +
    1.44 +int print_macho_equ(output_fmt_t mode, uint8_t* name, int val) {
    1.45 +  switch (mode) {
    1.46 +    case OUTPUT_FMT_RVDS:
    1.47 +      printf("%-40s EQU %5d\n", name, val);
    1.48 +      return 0;
    1.49 +    case  OUTPUT_FMT_GAS:
    1.50 +      printf(".set %-40s, %5d\n", name, val);
    1.51 +      return 0;
    1.52 +    default:
    1.53 +      log_msg("Unsupported mode: %d", mode);
    1.54 +      return 1;
    1.55 +  }
    1.56 +}
    1.57 +
    1.58 +int parse_macho(uint8_t *base_buf, size_t sz, output_fmt_t mode) {
    1.59 +  int i, j;
    1.60 +  struct mach_header header;
    1.61 +  uint8_t *buf = base_buf;
    1.62 +  int base_data_section = 0;
    1.63 +  int bits = 0;
    1.64 +
    1.65 +  /* We can read in mach_header for 32 and 64 bit architectures
    1.66 +   * because it's identical to mach_header_64 except for the last
    1.67 +   * element (uint32_t reserved), which we don't use. Then, when
    1.68 +   * we know which architecture we're looking at, increment buf
    1.69 +   * appropriately.
    1.70 +   */
    1.71 +  memcpy(&header, buf, sizeof(struct mach_header));
    1.72 +
    1.73 +  if (header.magic == MH_MAGIC) {
    1.74 +    if (header.cputype == CPU_TYPE_ARM
    1.75 +        || header.cputype == CPU_TYPE_X86) {
    1.76 +      bits = 32;
    1.77 +      buf += sizeof(struct mach_header);
    1.78 +    } else {
    1.79 +      log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
    1.80 +      goto bail;
    1.81 +    }
    1.82 +  } else if (header.magic == MH_MAGIC_64) {
    1.83 +    if (header.cputype == CPU_TYPE_X86_64) {
    1.84 +      bits = 64;
    1.85 +      buf += sizeof(struct mach_header_64);
    1.86 +    } else {
    1.87 +      log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
    1.88 +      goto bail;
    1.89 +    }
    1.90 +  } else {
    1.91 +    log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
    1.92 +            MH_MAGIC, MH_MAGIC_64, header.magic);
    1.93 +    goto bail;
    1.94 +  }
    1.95 +
    1.96 +  if (header.filetype != MH_OBJECT) {
    1.97 +    log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
    1.98 +    goto bail;
    1.99 +  }
   1.100 +
   1.101 +  for (i = 0; i < header.ncmds; i++) {
   1.102 +    struct load_command lc;
   1.103 +
   1.104 +    memcpy(&lc, buf, sizeof(struct load_command));
   1.105 +
   1.106 +    if (lc.cmd == LC_SEGMENT) {
   1.107 +      uint8_t *seg_buf = buf;
   1.108 +      struct section s;
   1.109 +      struct segment_command seg_c;
   1.110 +
   1.111 +      memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
   1.112 +      seg_buf += sizeof(struct segment_command);
   1.113 +
   1.114 +      /* Although each section is given it's own offset, nlist.n_value
   1.115 +       * references the offset of the first section. This isn't
   1.116 +       * apparent without debug information because the offset of the
   1.117 +       * data section is the same as the first section. However, with
   1.118 +       * debug sections mixed in, the offset of the debug section
   1.119 +       * increases but n_value still references the first section.
   1.120 +       */
   1.121 +      if (seg_c.nsects < 1) {
   1.122 +        log_msg("Not enough sections\n");
   1.123 +        goto bail;
   1.124 +      }
   1.125 +
   1.126 +      memcpy(&s, seg_buf, sizeof(struct section));
   1.127 +      base_data_section = s.offset;
   1.128 +    } else if (lc.cmd == LC_SEGMENT_64) {
   1.129 +      uint8_t *seg_buf = buf;
   1.130 +      struct section_64 s;
   1.131 +      struct segment_command_64 seg_c;
   1.132 +
   1.133 +      memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
   1.134 +      seg_buf += sizeof(struct segment_command_64);
   1.135 +
   1.136 +      /* Explanation in LG_SEGMENT */
   1.137 +      if (seg_c.nsects < 1) {
   1.138 +        log_msg("Not enough sections\n");
   1.139 +        goto bail;
   1.140 +      }
   1.141 +
   1.142 +      memcpy(&s, seg_buf, sizeof(struct section_64));
   1.143 +      base_data_section = s.offset;
   1.144 +    } else if (lc.cmd == LC_SYMTAB) {
   1.145 +      if (base_data_section != 0) {
   1.146 +        struct symtab_command sc;
   1.147 +        uint8_t *sym_buf = base_buf;
   1.148 +        uint8_t *str_buf = base_buf;
   1.149 +
   1.150 +        memcpy(&sc, buf, sizeof(struct symtab_command));
   1.151 +
   1.152 +        if (sc.cmdsize != sizeof(struct symtab_command)) {
   1.153 +          log_msg("Can't find symbol table!\n");
   1.154 +          goto bail;
   1.155 +        }
   1.156 +
   1.157 +        sym_buf += sc.symoff;
   1.158 +        str_buf += sc.stroff;
   1.159 +
   1.160 +        for (j = 0; j < sc.nsyms; j++) {
   1.161 +          /* Location of string is cacluated each time from the
   1.162 +           * start of the string buffer.  On darwin the symbols
   1.163 +           * are prefixed by "_", so we bump the pointer by 1.
   1.164 +           * The target value is defined as an int in *_asm_*_offsets.c,
   1.165 +           * which is 4 bytes on all targets we currently use.
   1.166 +           */
   1.167 +          if (bits == 32) {
   1.168 +            struct nlist nl;
   1.169 +            int val;
   1.170 +
   1.171 +            memcpy(&nl, sym_buf, sizeof(struct nlist));
   1.172 +            sym_buf += sizeof(struct nlist);
   1.173 +
   1.174 +            memcpy(&val, base_buf + base_data_section + nl.n_value,
   1.175 +                   sizeof(val));
   1.176 +            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
   1.177 +          } else { /* if (bits == 64) */
   1.178 +            struct nlist_64 nl;
   1.179 +            int val;
   1.180 +
   1.181 +            memcpy(&nl, sym_buf, sizeof(struct nlist_64));
   1.182 +            sym_buf += sizeof(struct nlist_64);
   1.183 +
   1.184 +            memcpy(&val, base_buf + base_data_section + nl.n_value,
   1.185 +                   sizeof(val));
   1.186 +            print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val);
   1.187 +          }
   1.188 +        }
   1.189 +      }
   1.190 +    }
   1.191 +
   1.192 +    buf += lc.cmdsize;
   1.193 +  }
   1.194 +
   1.195 +  return 0;
   1.196 +bail:
   1.197 +  return 1;
   1.198 +
   1.199 +}
   1.200 +
   1.201 +#elif defined(__ELF__)
   1.202 +#include "elf.h"
   1.203 +
   1.204 +#define COPY_STRUCT(dst, buf, ofst, sz) do {\
   1.205 +    if(ofst + sizeof((*(dst))) > sz) goto bail;\
   1.206 +    memcpy(dst, buf+ofst, sizeof((*(dst))));\
   1.207 +  } while(0)
   1.208 +
   1.209 +#define ENDIAN_ASSIGN(val, memb) do {\
   1.210 +    if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
   1.211 +    (val) = (memb);\
   1.212 +  } while(0)
   1.213 +
   1.214 +#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
   1.215 +    ENDIAN_ASSIGN(memb, memb);\
   1.216 +  } while(0)
   1.217 +
   1.218 +typedef struct {
   1.219 +  uint8_t      *buf; /* Buffer containing ELF data */
   1.220 +  size_t        sz;  /* Buffer size */
   1.221 +  int           le_data; /* Data is little-endian */
   1.222 +  unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
   1.223 +  int           bits; /* 32 or 64 */
   1.224 +  Elf32_Ehdr    hdr32;
   1.225 +  Elf64_Ehdr    hdr64;
   1.226 +} elf_obj_t;
   1.227 +
   1.228 +int parse_elf_header(elf_obj_t *elf) {
   1.229 +  int res;
   1.230 +  /* Verify ELF Magic numbers */
   1.231 +  COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
   1.232 +  res = elf->e_ident[EI_MAG0] == ELFMAG0;
   1.233 +  res &= elf->e_ident[EI_MAG1] == ELFMAG1;
   1.234 +  res &= elf->e_ident[EI_MAG2] == ELFMAG2;
   1.235 +  res &= elf->e_ident[EI_MAG3] == ELFMAG3;
   1.236 +  res &= elf->e_ident[EI_CLASS] == ELFCLASS32
   1.237 +         || elf->e_ident[EI_CLASS] == ELFCLASS64;
   1.238 +  res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
   1.239 +
   1.240 +  if (!res) goto bail;
   1.241 +
   1.242 +  elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
   1.243 +
   1.244 +  /* Read in relevant values */
   1.245 +  if (elf->e_ident[EI_CLASS] == ELFCLASS32) {
   1.246 +    elf->bits = 32;
   1.247 +    COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
   1.248 +
   1.249 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
   1.250 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
   1.251 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
   1.252 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
   1.253 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
   1.254 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
   1.255 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
   1.256 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
   1.257 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
   1.258 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
   1.259 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
   1.260 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
   1.261 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
   1.262 +  } else { /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
   1.263 +    elf->bits = 64;
   1.264 +    COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
   1.265 +
   1.266 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
   1.267 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
   1.268 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
   1.269 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
   1.270 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
   1.271 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
   1.272 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
   1.273 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
   1.274 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
   1.275 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
   1.276 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
   1.277 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
   1.278 +    ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
   1.279 +  }
   1.280 +
   1.281 +  return 0;
   1.282 +bail:
   1.283 +  log_msg("Failed to parse ELF file header");
   1.284 +  return 1;
   1.285 +}
   1.286 +
   1.287 +int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64) {
   1.288 +  if (hdr32) {
   1.289 +    if (idx >= elf->hdr32.e_shnum)
   1.290 +      goto bail;
   1.291 +
   1.292 +    COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
   1.293 +                elf->sz);
   1.294 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
   1.295 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
   1.296 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
   1.297 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
   1.298 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
   1.299 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
   1.300 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
   1.301 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
   1.302 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
   1.303 +    ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
   1.304 +  } else { /* if (hdr64) */
   1.305 +    if (idx >= elf->hdr64.e_shnum)
   1.306 +      goto bail;
   1.307 +
   1.308 +    COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
   1.309 +                elf->sz);
   1.310 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
   1.311 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
   1.312 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
   1.313 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
   1.314 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
   1.315 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
   1.316 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
   1.317 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
   1.318 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
   1.319 +    ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
   1.320 +  }
   1.321 +
   1.322 +  return 0;
   1.323 +bail:
   1.324 +  return 1;
   1.325 +}
   1.326 +
   1.327 +char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) {
   1.328 +  if (elf->bits == 32) {
   1.329 +    Elf32_Shdr shdr;
   1.330 +
   1.331 +    if (parse_elf_section(elf, s_idx, &shdr, NULL)) {
   1.332 +      log_msg("Failed to parse ELF string table: section %d, index %d\n",
   1.333 +              s_idx, idx);
   1.334 +      return "";
   1.335 +    }
   1.336 +
   1.337 +    return (char *)(elf->buf + shdr.sh_offset + idx);
   1.338 +  } else { /* if (elf->bits == 64) */
   1.339 +    Elf64_Shdr shdr;
   1.340 +
   1.341 +    if (parse_elf_section(elf, s_idx, NULL, &shdr)) {
   1.342 +      log_msg("Failed to parse ELF string table: section %d, index %d\n",
   1.343 +              s_idx, idx);
   1.344 +      return "";
   1.345 +    }
   1.346 +
   1.347 +    return (char *)(elf->buf + shdr.sh_offset + idx);
   1.348 +  }
   1.349 +}
   1.350 +
   1.351 +int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64) {
   1.352 +  if (sym32) {
   1.353 +    COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
   1.354 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
   1.355 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
   1.356 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
   1.357 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
   1.358 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
   1.359 +    ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
   1.360 +  } else { /* if (sym64) */
   1.361 +    COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
   1.362 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
   1.363 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
   1.364 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
   1.365 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
   1.366 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
   1.367 +    ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
   1.368 +  }
   1.369 +  return 0;
   1.370 +bail:
   1.371 +  return 1;
   1.372 +}
   1.373 +
   1.374 +int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode) {
   1.375 +  elf_obj_t    elf;
   1.376 +  unsigned int ofst;
   1.377 +  int          i;
   1.378 +  Elf32_Off    strtab_off32;
   1.379 +  Elf64_Off    strtab_off64; /* save String Table offset for later use */
   1.380 +
   1.381 +  memset(&elf, 0, sizeof(elf));
   1.382 +  elf.buf = buf;
   1.383 +  elf.sz = sz;
   1.384 +
   1.385 +  /* Parse Header */
   1.386 +  if (parse_elf_header(&elf))
   1.387 +    goto bail;
   1.388 +
   1.389 +  if (elf.bits == 32) {
   1.390 +    Elf32_Shdr shdr;
   1.391 +    for (i = 0; i < elf.hdr32.e_shnum; i++) {
   1.392 +      parse_elf_section(&elf, i, &shdr, NULL);
   1.393 +
   1.394 +      if (shdr.sh_type == SHT_STRTAB) {
   1.395 +        char strtsb_name[128];
   1.396 +
   1.397 +        strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
   1.398 +
   1.399 +        if (!(strcmp(strtsb_name, ".shstrtab"))) {
   1.400 +          /* log_msg("found section: %s\n", strtsb_name); */
   1.401 +          strtab_off32 = shdr.sh_offset;
   1.402 +          break;
   1.403 +        }
   1.404 +      }
   1.405 +    }
   1.406 +  } else { /* if (elf.bits == 64) */
   1.407 +    Elf64_Shdr shdr;
   1.408 +    for (i = 0; i < elf.hdr64.e_shnum; i++) {
   1.409 +      parse_elf_section(&elf, i, NULL, &shdr);
   1.410 +
   1.411 +      if (shdr.sh_type == SHT_STRTAB) {
   1.412 +        char strtsb_name[128];
   1.413 +
   1.414 +        strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
   1.415 +
   1.416 +        if (!(strcmp(strtsb_name, ".shstrtab"))) {
   1.417 +          /* log_msg("found section: %s\n", strtsb_name); */
   1.418 +          strtab_off64 = shdr.sh_offset;
   1.419 +          break;
   1.420 +        }
   1.421 +      }
   1.422 +    }
   1.423 +  }
   1.424 +
   1.425 +  /* Parse all Symbol Tables */
   1.426 +  if (elf.bits == 32) {
   1.427 +    Elf32_Shdr shdr;
   1.428 +    for (i = 0; i < elf.hdr32.e_shnum; i++) {
   1.429 +      parse_elf_section(&elf, i, &shdr, NULL);
   1.430 +
   1.431 +      if (shdr.sh_type == SHT_SYMTAB) {
   1.432 +        for (ofst = shdr.sh_offset;
   1.433 +             ofst < shdr.sh_offset + shdr.sh_size;
   1.434 +             ofst += shdr.sh_entsize) {
   1.435 +          Elf32_Sym sym;
   1.436 +
   1.437 +          parse_elf_symbol(&elf, ofst, &sym, NULL);
   1.438 +
   1.439 +          /* For all OBJECTS (data objects), extract the value from the
   1.440 +           * proper data segment.
   1.441 +           */
   1.442 +          /* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
   1.443 +              log_msg("found data object %s\n",
   1.444 +                      parse_elf_string_table(&elf,
   1.445 +                                             shdr.sh_link,
   1.446 +                                             sym.st_name));
   1.447 +           */
   1.448 +
   1.449 +          if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
   1.450 +              && sym.st_size == 4) {
   1.451 +            Elf32_Shdr dhdr;
   1.452 +            int val = 0;
   1.453 +            char section_name[128];
   1.454 +
   1.455 +            parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
   1.456 +
   1.457 +            /* For explanition - refer to _MSC_VER version of code */
   1.458 +            strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
   1.459 +            /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
   1.460 +
   1.461 +            if (strcmp(section_name, ".bss")) {
   1.462 +              if (sizeof(val) != sym.st_size) {
   1.463 +                /* The target value is declared as an int in
   1.464 +                 * *_asm_*_offsets.c, which is 4 bytes on all
   1.465 +                 * targets we currently use. Complain loudly if
   1.466 +                 * this is not true.
   1.467 +                 */
   1.468 +                log_msg("Symbol size is wrong\n");
   1.469 +                goto bail;
   1.470 +              }
   1.471 +
   1.472 +              memcpy(&val,
   1.473 +                     elf.buf + dhdr.sh_offset + sym.st_value,
   1.474 +                     sym.st_size);
   1.475 +            }
   1.476 +
   1.477 +            if (!elf.le_data) {
   1.478 +              log_msg("Big Endian data not supported yet!\n");
   1.479 +              goto bail;
   1.480 +            }
   1.481 +
   1.482 +            switch (mode) {
   1.483 +              case OUTPUT_FMT_RVDS:
   1.484 +                printf("%-40s EQU %5d\n",
   1.485 +                       parse_elf_string_table(&elf,
   1.486 +                                              shdr.sh_link,
   1.487 +                                              sym.st_name),
   1.488 +                       val);
   1.489 +                break;
   1.490 +              case OUTPUT_FMT_GAS:
   1.491 +                printf(".equ %-40s, %5d\n",
   1.492 +                       parse_elf_string_table(&elf,
   1.493 +                                              shdr.sh_link,
   1.494 +                                              sym.st_name),
   1.495 +                       val);
   1.496 +                break;
   1.497 +              default:
   1.498 +                printf("%s = %d\n",
   1.499 +                       parse_elf_string_table(&elf,
   1.500 +                                              shdr.sh_link,
   1.501 +                                              sym.st_name),
   1.502 +                       val);
   1.503 +            }
   1.504 +          }
   1.505 +        }
   1.506 +      }
   1.507 +    }
   1.508 +  } else { /* if (elf.bits == 64) */
   1.509 +    Elf64_Shdr shdr;
   1.510 +    for (i = 0; i < elf.hdr64.e_shnum; i++) {
   1.511 +      parse_elf_section(&elf, i, NULL, &shdr);
   1.512 +
   1.513 +      if (shdr.sh_type == SHT_SYMTAB) {
   1.514 +        for (ofst = shdr.sh_offset;
   1.515 +             ofst < shdr.sh_offset + shdr.sh_size;
   1.516 +             ofst += shdr.sh_entsize) {
   1.517 +          Elf64_Sym sym;
   1.518 +
   1.519 +          parse_elf_symbol(&elf, ofst, NULL, &sym);
   1.520 +
   1.521 +          /* For all OBJECTS (data objects), extract the value from the
   1.522 +           * proper data segment.
   1.523 +           */
   1.524 +          /* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
   1.525 +              log_msg("found data object %s\n",
   1.526 +                      parse_elf_string_table(&elf,
   1.527 +                                             shdr.sh_link,
   1.528 +                                             sym.st_name));
   1.529 +           */
   1.530 +
   1.531 +          if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
   1.532 +              && sym.st_size == 4) {
   1.533 +            Elf64_Shdr dhdr;
   1.534 +            int val = 0;
   1.535 +            char section_name[128];
   1.536 +
   1.537 +            parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
   1.538 +
   1.539 +            /* For explanition - refer to _MSC_VER version of code */
   1.540 +            strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
   1.541 +            /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
   1.542 +
   1.543 +            if ((strcmp(section_name, ".bss"))) {
   1.544 +              if (sizeof(val) != sym.st_size) {
   1.545 +                /* The target value is declared as an int in
   1.546 +                 * *_asm_*_offsets.c, which is 4 bytes on all
   1.547 +                 * targets we currently use. Complain loudly if
   1.548 +                 * this is not true.
   1.549 +                 */
   1.550 +                log_msg("Symbol size is wrong\n");
   1.551 +                goto bail;
   1.552 +              }
   1.553 +
   1.554 +              memcpy(&val,
   1.555 +                     elf.buf + dhdr.sh_offset + sym.st_value,
   1.556 +                     sym.st_size);
   1.557 +            }
   1.558 +
   1.559 +            if (!elf.le_data) {
   1.560 +              log_msg("Big Endian data not supported yet!\n");
   1.561 +              goto bail;
   1.562 +            }
   1.563 +
   1.564 +            switch (mode) {
   1.565 +              case OUTPUT_FMT_RVDS:
   1.566 +                printf("%-40s EQU %5d\n",
   1.567 +                       parse_elf_string_table(&elf,
   1.568 +                                              shdr.sh_link,
   1.569 +                                              sym.st_name),
   1.570 +                       val);
   1.571 +                break;
   1.572 +              case OUTPUT_FMT_GAS:
   1.573 +                printf(".equ %-40s, %5d\n",
   1.574 +                       parse_elf_string_table(&elf,
   1.575 +                                              shdr.sh_link,
   1.576 +                                              sym.st_name),
   1.577 +                       val);
   1.578 +                break;
   1.579 +              default:
   1.580 +                printf("%s = %d\n",
   1.581 +                       parse_elf_string_table(&elf,
   1.582 +                                              shdr.sh_link,
   1.583 +                                              sym.st_name),
   1.584 +                       val);
   1.585 +            }
   1.586 +          }
   1.587 +        }
   1.588 +      }
   1.589 +    }
   1.590 +  }
   1.591 +
   1.592 +  if (mode == OUTPUT_FMT_RVDS)
   1.593 +    printf("    END\n");
   1.594 +
   1.595 +  return 0;
   1.596 +bail:
   1.597 +  log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
   1.598 +  return 1;
   1.599 +}
   1.600 +
   1.601 +#endif
   1.602 +#endif /* defined(__GNUC__) && __GNUC__ */
   1.603 +
   1.604 +
   1.605 +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
   1.606 +/*  See "Microsoft Portable Executable and Common Object File Format Specification"
   1.607 +    for reference.
   1.608 +*/
   1.609 +#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
   1.610 +#define get_le16(x) ((*(x)) | (*(x+1)) << 8)
   1.611 +
   1.612 +int parse_coff(uint8_t *buf, size_t sz) {
   1.613 +  unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
   1.614 +  unsigned int sectionrawdata_ptr;
   1.615 +  unsigned int i;
   1.616 +  uint8_t *ptr;
   1.617 +  uint32_t symoffset;
   1.618 +
   1.619 +  char **sectionlist;  // this array holds all section names in their correct order.
   1.620 +  // it is used to check if the symbol is in .bss or .rdata section.
   1.621 +
   1.622 +  nsections = get_le16(buf + 2);
   1.623 +  symtab_ptr = get_le32(buf + 8);
   1.624 +  symtab_sz = get_le32(buf + 12);
   1.625 +  strtab_ptr = symtab_ptr + symtab_sz * 18;
   1.626 +
   1.627 +  if (nsections > 96) {
   1.628 +    log_msg("Too many sections\n");
   1.629 +    return 1;
   1.630 +  }
   1.631 +
   1.632 +  sectionlist = malloc(nsections * sizeof(sectionlist));
   1.633 +
   1.634 +  if (sectionlist == NULL) {
   1.635 +    log_msg("Allocating first level of section list failed\n");
   1.636 +    return 1;
   1.637 +  }
   1.638 +
   1.639 +  // log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
   1.640 +
   1.641 +  /*
   1.642 +  The size of optional header is always zero for an obj file. So, the section header
   1.643 +  follows the file header immediately.
   1.644 +  */
   1.645 +
   1.646 +  ptr = buf + 20;     // section header
   1.647 +
   1.648 +  for (i = 0; i < nsections; i++) {
   1.649 +    char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
   1.650 +    strncpy(sectionname, ptr, 8);
   1.651 +    // log_msg("COFF: Parsing section %s\n",sectionname);
   1.652 +
   1.653 +    sectionlist[i] = malloc(strlen(sectionname) + 1);
   1.654 +
   1.655 +    if (sectionlist[i] == NULL) {
   1.656 +      log_msg("Allocating storage for %s failed\n", sectionname);
   1.657 +      goto bail;
   1.658 +    }
   1.659 +    strcpy(sectionlist[i], sectionname);
   1.660 +
   1.661 +    if (!strcmp(sectionname, ".rdata")) sectionrawdata_ptr = get_le32(ptr + 20);
   1.662 +
   1.663 +    ptr += 40;
   1.664 +  }
   1.665 +
   1.666 +  // log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
   1.667 +  // log_msg("COFF: raw data pointer ofset for section .rdata is %u\n", sectionrawdata_ptr);
   1.668 +
   1.669 +  /*  The compiler puts the data with non-zero offset in .rdata section, but puts the data with
   1.670 +      zero offset in .bss section. So, if the data in in .bss section, set offset=0.
   1.671 +      Note from Wiki: In an object module compiled from C, the bss section contains
   1.672 +      the local variables (but not functions) that were declared with the static keyword,
   1.673 +      except for those with non-zero initial values. (In C, static variables are initialized
   1.674 +      to zero by default.) It also contains the non-local (both extern and static) variables
   1.675 +      that are also initialized to zero (either explicitly or by default).
   1.676 +      */
   1.677 +  // move to symbol table
   1.678 +  /* COFF symbol table:
   1.679 +      offset      field
   1.680 +      0           Name(*)
   1.681 +      8           Value
   1.682 +      12          SectionNumber
   1.683 +      14          Type
   1.684 +      16          StorageClass
   1.685 +      17          NumberOfAuxSymbols
   1.686 +      */
   1.687 +  ptr = buf + symtab_ptr;
   1.688 +
   1.689 +  for (i = 0; i < symtab_sz; i++) {
   1.690 +    int16_t section = get_le16(ptr + 12); // section number
   1.691 +
   1.692 +    if (section > 0 && ptr[16] == 2) {
   1.693 +      // if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
   1.694 +
   1.695 +      if (get_le32(ptr)) {
   1.696 +        char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
   1.697 +        strncpy(name, ptr, 8);
   1.698 +        // log_msg("COFF: Parsing symbol %s\n",name);
   1.699 +        /* The 64bit Windows compiler doesn't prefix with an _.
   1.700 +         * Check what's there, and bump if necessary
   1.701 +         */
   1.702 +        if (name[0] == '_')
   1.703 +          printf("%-40s EQU ", name + 1);
   1.704 +        else
   1.705 +          printf("%-40s EQU ", name);
   1.706 +      } else {
   1.707 +        // log_msg("COFF: Parsing symbol %s\n",
   1.708 +        //        buf + strtab_ptr + get_le32(ptr+4));
   1.709 +        if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
   1.710 +          printf("%-40s EQU ",
   1.711 +                 buf + strtab_ptr + get_le32(ptr + 4) + 1);
   1.712 +        else
   1.713 +          printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
   1.714 +      }
   1.715 +
   1.716 +      if (!(strcmp(sectionlist[section - 1], ".bss"))) {
   1.717 +        symoffset = 0;
   1.718 +      } else {
   1.719 +        symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
   1.720 +      }
   1.721 +
   1.722 +      // log_msg("      Section: %d\n",section);
   1.723 +      // log_msg("      Class:   %d\n",ptr[16]);
   1.724 +      // log_msg("      Address: %u\n",get_le32(ptr+8));
   1.725 +      // log_msg("      Offset: %u\n", symoffset);
   1.726 +
   1.727 +      printf("%5d\n", symoffset);
   1.728 +    }
   1.729 +
   1.730 +    ptr += 18;
   1.731 +  }
   1.732 +
   1.733 +  printf("    END\n");
   1.734 +
   1.735 +  for (i = 0; i < nsections; i++) {
   1.736 +    free(sectionlist[i]);
   1.737 +  }
   1.738 +
   1.739 +  free(sectionlist);
   1.740 +
   1.741 +  return 0;
   1.742 +bail:
   1.743 +
   1.744 +  for (i = 0; i < nsections; i++) {
   1.745 +    free(sectionlist[i]);
   1.746 +  }
   1.747 +
   1.748 +  free(sectionlist);
   1.749 +
   1.750 +  return 1;
   1.751 +}
   1.752 +#endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */
   1.753 +
   1.754 +int main(int argc, char **argv) {
   1.755 +  output_fmt_t mode = OUTPUT_FMT_PLAIN;
   1.756 +  const char *f;
   1.757 +  uint8_t *file_buf;
   1.758 +  int res;
   1.759 +  FILE *fp;
   1.760 +  long int file_size;
   1.761 +
   1.762 +  if (argc < 2 || argc > 3) {
   1.763 +    fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
   1.764 +    fprintf(stderr, "  <obj file>\tobject file to parse\n");
   1.765 +    fprintf(stderr, "Output Formats:\n");
   1.766 +    fprintf(stderr, "  gas  - compatible with GNU assembler\n");
   1.767 +    fprintf(stderr, "  rvds - compatible with armasm\n");
   1.768 +    goto bail;
   1.769 +  }
   1.770 +
   1.771 +  f = argv[2];
   1.772 +
   1.773 +  if (!strcmp(argv[1], "rvds"))
   1.774 +    mode = OUTPUT_FMT_RVDS;
   1.775 +  else if (!strcmp(argv[1], "gas"))
   1.776 +    mode = OUTPUT_FMT_GAS;
   1.777 +  else
   1.778 +    f = argv[1];
   1.779 +
   1.780 +  fp = fopen(f, "rb");
   1.781 +
   1.782 +  if (!fp) {
   1.783 +    perror("Unable to open file");
   1.784 +    goto bail;
   1.785 +  }
   1.786 +
   1.787 +  if (fseek(fp, 0, SEEK_END)) {
   1.788 +    perror("stat");
   1.789 +    goto bail;
   1.790 +  }
   1.791 +
   1.792 +  file_size = ftell(fp);
   1.793 +  file_buf = malloc(file_size);
   1.794 +
   1.795 +  if (!file_buf) {
   1.796 +    perror("malloc");
   1.797 +    goto bail;
   1.798 +  }
   1.799 +
   1.800 +  rewind(fp);
   1.801 +
   1.802 +  if (fread(file_buf, sizeof(char), file_size, fp) != file_size) {
   1.803 +    perror("read");
   1.804 +    goto bail;
   1.805 +  }
   1.806 +
   1.807 +  if (fclose(fp)) {
   1.808 +    perror("close");
   1.809 +    goto bail;
   1.810 +  }
   1.811 +
   1.812 +#if defined(__GNUC__) && __GNUC__
   1.813 +#if defined(__MACH__)
   1.814 +  res = parse_macho(file_buf, file_size, mode);
   1.815 +#elif defined(__ELF__)
   1.816 +  res = parse_elf(file_buf, file_size, mode);
   1.817 +#endif
   1.818 +#endif
   1.819 +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
   1.820 +  res = parse_coff(file_buf, file_size);
   1.821 +#endif
   1.822 +
   1.823 +  free(file_buf);
   1.824 +
   1.825 +  if (!res)
   1.826 +    return EXIT_SUCCESS;
   1.827 +
   1.828 +bail:
   1.829 +  return EXIT_FAILURE;
   1.830 +}

mercurial