1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* 2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * 4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * Use of this source code is governed by a BSD-style license 5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * that can be found in the LICENSE file in the root of the source 6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * tree. An additional intellectual property rights grant can be found 7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * in the file PATENTS. All contributing project authors may 8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * be found in the AUTHORS file in the root of the source tree. 9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */ 10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 12474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdarg.h> 13474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdio.h> 14474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdlib.h> 15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <string.h> 16474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 17474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vpx_config.h" 18474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vpx/vpx_integer.h" 19474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgtypedef enum { 216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org OUTPUT_FMT_PLAIN, 226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org OUTPUT_FMT_RVDS, 236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org OUTPUT_FMT_GAS, 24dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org OUTPUT_FMT_C_HEADER, 25474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} output_fmt_t; 26474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint log_msg(const char *fmt, ...) { 286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int res; 296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org va_list ap; 306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org va_start(ap, fmt); 316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res = vfprintf(stderr, fmt, ap); 326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org va_end(ap); 336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return res; 34474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 35474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 36474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(__GNUC__) && __GNUC__ 3786c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org 3886c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#if defined(FORCE_PARSE_ELF) 3986c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org 4086c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#if defined(__MACH__) 4186c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#undef __MACH__ 4286c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#endif 4386c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org 4486c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#if !defined(__ELF__) 4586c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#define __ELF__ 4686c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#endif 4786c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org#endif 4886c4e4eda13a307f6d1e28ec5019b38733c907cbmichaelbai@chromium.org 49474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(__MACH__) 50474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 51474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <mach-o/loader.h> 52474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <mach-o/nlist.h> 53474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 54eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.orgint print_macho_equ(output_fmt_t mode, uint8_t* name, int val) { 55eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org switch (mode) { 56eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org case OUTPUT_FMT_RVDS: 57eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org printf("%-40s EQU %5d\n", name, val); 58eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org return 0; 59ccd3f2307083382490dba5ef673678852d8e6ea5johannkoenig@chromium.org case OUTPUT_FMT_GAS: 60eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org printf(".set %-40s, %5d\n", name, val); 61eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org return 0; 62ccd3f2307083382490dba5ef673678852d8e6ea5johannkoenig@chromium.org case OUTPUT_FMT_C_HEADER: 63dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org printf("#define %-40s %5d\n", name, val); 64dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org return 0; 65eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org default: 66eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org log_msg("Unsupported mode: %d", mode); 67eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org return 1; 68eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org } 69eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org} 70eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org 71eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.orgint parse_macho(uint8_t *base_buf, size_t sz, output_fmt_t mode) { 726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int i, j; 736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct mach_header header; 746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *buf = base_buf; 756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int base_data_section = 0; 766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int bits = 0; 776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* We can read in mach_header for 32 and 64 bit architectures 796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * because it's identical to mach_header_64 except for the last 806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * element (uint32_t reserved), which we don't use. Then, when 816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * we know which architecture we're looking at, increment buf 826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * appropriately. 836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&header, buf, sizeof(struct mach_header)); 856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (header.magic == MH_MAGIC) { 876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (header.cputype == CPU_TYPE_ARM 886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org || header.cputype == CPU_TYPE_X86) { 896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org bits = 32; 906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org buf += sizeof(struct mach_header); 916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { 926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n"); 936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 94474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else if (header.magic == MH_MAGIC_64) { 966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (header.cputype == CPU_TYPE_X86_64) { 976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org bits = 64; 986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org buf += sizeof(struct mach_header_64); 996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { 1006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n"); 1016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 102474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 1036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { 1046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n", 1056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org MH_MAGIC, MH_MAGIC_64, header.magic); 1066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 1086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (header.filetype != MH_OBJECT) { 1106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n"); 1116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 1126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 1136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < header.ncmds; i++) { 1156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct load_command lc; 1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&lc, buf, sizeof(struct load_command)); 1186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (lc.cmd == LC_SEGMENT) { 1206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *seg_buf = buf; 1216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct section s; 1226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct segment_command seg_c; 1236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&seg_c, seg_buf, sizeof(struct segment_command)); 1256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org seg_buf += sizeof(struct segment_command); 1266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Although each section is given it's own offset, nlist.n_value 1286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * references the offset of the first section. This isn't 1296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * apparent without debug information because the offset of the 1306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * data section is the same as the first section. However, with 1316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * debug sections mixed in, the offset of the debug section 1326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * increases but n_value still references the first section. 1336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 1346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (seg_c.nsects < 1) { 1356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Not enough sections\n"); 136474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org goto bail; 1376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 1386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&s, seg_buf, sizeof(struct section)); 1406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org base_data_section = s.offset; 1416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else if (lc.cmd == LC_SEGMENT_64) { 1426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *seg_buf = buf; 1436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct section_64 s; 1446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct segment_command_64 seg_c; 1456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64)); 1476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org seg_buf += sizeof(struct segment_command_64); 148474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 1496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Explanation in LG_SEGMENT */ 1506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (seg_c.nsects < 1) { 1516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Not enough sections\n"); 152474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org goto bail; 1536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 154474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 1556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&s, seg_buf, sizeof(struct section_64)); 1566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org base_data_section = s.offset; 1576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else if (lc.cmd == LC_SYMTAB) { 1586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (base_data_section != 0) { 1596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct symtab_command sc; 1606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *sym_buf = base_buf; 1616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *str_buf = base_buf; 162474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 1636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&sc, buf, sizeof(struct symtab_command)); 164474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 1656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sc.cmdsize != sizeof(struct symtab_command)) { 1666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Can't find symbol table!\n"); 1676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 168474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 169474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 1706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym_buf += sc.symoff; 1716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org str_buf += sc.stroff; 1726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (j = 0; j < sc.nsyms; j++) { 1746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Location of string is cacluated each time from the 1756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * start of the string buffer. On darwin the symbols 1766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * are prefixed by "_", so we bump the pointer by 1. 1774b95526e5c4eb4fecde1cd642cf991a82c51b9f2johannkoenig@chromium.org * The target value is defined as an int in *_asm_*_offsets.c, 1786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * which is 4 bytes on all targets we currently use. 1796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 1806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (bits == 32) { 1816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct nlist nl; 1826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int val; 1836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&nl, sym_buf, sizeof(struct nlist)); 1856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym_buf += sizeof(struct nlist); 1866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&val, base_buf + base_data_section + nl.n_value, 1886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sizeof(val)); 189eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val); 1906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (bits == 64) */ 1916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org struct nlist_64 nl; 1926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int val; 1936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&nl, sym_buf, sizeof(struct nlist_64)); 1956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym_buf += sizeof(struct nlist_64); 1966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&val, base_buf + base_data_section + nl.n_value, 1986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sizeof(val)); 199eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org print_macho_equ(mode, str_buf + nl.n_un.n_strx + 1, val); 2006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 2016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 2026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 203474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 204474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 2056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org buf += lc.cmdsize; 2066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 2076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 209474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 2106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 211474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 212474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 213474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 214474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#elif defined(__ELF__) 215474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "elf.h" 216474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 217474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define COPY_STRUCT(dst, buf, ofst, sz) do {\ 2186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if(ofst + sizeof((*(dst))) > sz) goto bail;\ 2196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(dst, buf+ofst, sizeof((*(dst))));\ 2206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } while(0) 221474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 222474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define ENDIAN_ASSIGN(val, memb) do {\ 2236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\ 2246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org (val) = (memb);\ 2256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } while(0) 226474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 227474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\ 2286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN(memb, memb);\ 2296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } while(0) 2306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgtypedef struct { 2326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *buf; /* Buffer containing ELF data */ 2336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org size_t sz; /* Buffer size */ 2346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int le_data; /* Data is little-endian */ 2356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 2366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int bits; /* 32 or 64 */ 2376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Ehdr hdr32; 2386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Ehdr hdr64; 239474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} elf_obj_t; 240474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 2416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint parse_elf_header(elf_obj_t *elf) { 2426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int res; 2436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Verify ELF Magic numbers */ 2446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz); 2456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res = elf->e_ident[EI_MAG0] == ELFMAG0; 2466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res &= elf->e_ident[EI_MAG1] == ELFMAG1; 2476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res &= elf->e_ident[EI_MAG2] == ELFMAG2; 2486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res &= elf->e_ident[EI_MAG3] == ELFMAG3; 2496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res &= elf->e_ident[EI_CLASS] == ELFCLASS32 2506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org || elf->e_ident[EI_CLASS] == ELFCLASS64; 2516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res &= elf->e_ident[EI_DATA] == ELFDATA2LSB; 2526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!res) goto bail; 2546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB; 2566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Read in relevant values */ 2586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (elf->e_ident[EI_CLASS] == ELFCLASS32) { 2596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf->bits = 32; 2606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz); 2616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type); 2636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine); 2646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version); 2656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry); 2666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff); 2676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff); 2686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags); 2696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize); 2706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize); 2716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum); 2726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize); 2736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum); 2746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx); 2756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */ 2766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf->bits = 64; 2776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz); 2786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type); 2806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine); 2816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version); 2826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry); 2836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff); 2846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff); 2856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags); 2866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize); 2876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize); 2886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum); 2896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize); 2906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum); 2916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx); 2926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 2936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 2946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 295474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 2966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Failed to parse ELF file header"); 2976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 298474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 299474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64) { 3016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (hdr32) { 3026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (idx >= elf->hdr32.e_shnum) 3036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 3046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 3056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize, 3066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf->sz); 3076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name); 3086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type); 3096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags); 3106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr); 3116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset); 3126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size); 3136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link); 3146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info); 3156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign); 3166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize); 3176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (hdr64) */ 3186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (idx >= elf->hdr64.e_shnum) 3196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 320474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize, 3226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf->sz); 3236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name); 3246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type); 3256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags); 3266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr); 3276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset); 3286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size); 3296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link); 3306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info); 3316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign); 3326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize); 3336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 3346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 3356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 336474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 3376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 338474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 339474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 340d851b91d14ef0bd71acdce7b90c9a8f1af1181adjohannkoenig@chromium.orgconst char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx) { 3416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (elf->bits == 32) { 3426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Shdr shdr; 343474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (parse_elf_section(elf, s_idx, &shdr, NULL)) { 3456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Failed to parse ELF string table: section %d, index %d\n", 3466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org s_idx, idx); 3476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return ""; 348474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 349474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return (char *)(elf->buf + shdr.sh_offset + idx); 3516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (elf->bits == 64) */ 3526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Shdr shdr; 3536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 3546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (parse_elf_section(elf, s_idx, NULL, &shdr)) { 3556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Failed to parse ELF string table: section %d, index %d\n", 3566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org s_idx, idx); 3576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return ""; 358474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 3596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 3606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return (char *)(elf->buf + shdr.sh_offset + idx); 3616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 362474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 363474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64) { 3656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sym32) { 3666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(sym32, elf->buf, ofst, elf->sz); 3676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_name); 3686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_value); 3696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_size); 3706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_info); 3716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_other); 3726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx); 3736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (sym64) */ 3746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org COPY_STRUCT(sym64, elf->buf, ofst, elf->sz); 3756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_name); 3766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_value); 3776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_size); 3786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_info); 3796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_other); 3806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx); 3816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 3826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 383474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 3846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 385474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 386474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode) { 3886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf_obj_t elf; 3896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org unsigned int ofst; 3906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int i; 3916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Off strtab_off32; 3926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Off strtab_off64; /* save String Table offset for later use */ 393474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memset(&elf, 0, sizeof(elf)); 3956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf.buf = buf; 3966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf.sz = sz; 397474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Parse Header */ 3996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (parse_elf_header(&elf)) 4006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 401474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 4026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (elf.bits == 32) { 4036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Shdr shdr; 4046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < elf.hdr32.e_shnum; i++) { 4056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, i, &shdr, NULL); 4066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (shdr.sh_type == SHT_STRTAB) { 4086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char strtsb_name[128]; 4096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name)); 4116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!(strcmp(strtsb_name, ".shstrtab"))) { 4136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* log_msg("found section: %s\n", strtsb_name); */ 4146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strtab_off32 = shdr.sh_offset; 4156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 416474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 4176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 418474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 4196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (elf.bits == 64) */ 4206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Shdr shdr; 4216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < elf.hdr64.e_shnum; i++) { 4226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, i, NULL, &shdr); 4236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (shdr.sh_type == SHT_STRTAB) { 4256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char strtsb_name[128]; 4266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name)); 4286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!(strcmp(strtsb_name, ".shstrtab"))) { 4306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* log_msg("found section: %s\n", strtsb_name); */ 4316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strtab_off64 = shdr.sh_offset; 4326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 433474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 4346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 435474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 4366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 4376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* Parse all Symbol Tables */ 4396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (elf.bits == 32) { 4406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Shdr shdr; 4416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < elf.hdr32.e_shnum; i++) { 4426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, i, &shdr, NULL); 4436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (shdr.sh_type == SHT_SYMTAB) { 4456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (ofst = shdr.sh_offset; 4466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ofst < shdr.sh_offset + shdr.sh_size; 4476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ofst += shdr.sh_entsize) { 4486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Sym sym; 4496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_symbol(&elf, ofst, &sym, NULL); 4516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* For all OBJECTS (data objects), extract the value from the 4536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * proper data segment. 4546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 4556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name) 4566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("found data object %s\n", 4576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 4586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 4596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name)); 4606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 4616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT 4636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org && sym.st_size == 4) { 4646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf32_Shdr dhdr; 4656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int val = 0; 4666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char section_name[128]; 4676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL); 4696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* For explanition - refer to _MSC_VER version of code */ 4716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name)); 4726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */ 4736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (strcmp(section_name, ".bss")) { 4756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sizeof(val) != sym.st_size) { 4766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* The target value is declared as an int in 4774b95526e5c4eb4fecde1cd642cf991a82c51b9f2johannkoenig@chromium.org * *_asm_*_offsets.c, which is 4 bytes on all 4786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * targets we currently use. Complain loudly if 4796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * this is not true. 4806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 4816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Symbol size is wrong\n"); 4826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 4836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 4846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&val, 4866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf.buf + dhdr.sh_offset + sym.st_value, 4876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_size); 4886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 4896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 4906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!elf.le_data) { 4916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Big Endian data not supported yet!\n"); 4926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 4936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 494474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 4956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org switch (mode) { 4966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org case OUTPUT_FMT_RVDS: 4976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU %5d\n", 4986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 4996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 5016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 5026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 5036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org case OUTPUT_FMT_GAS: 5046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf(".equ %-40s, %5d\n", 5056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 5066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 5086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 5096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 510dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org case OUTPUT_FMT_C_HEADER: 511dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org printf("#define %-40s %5d\n", 512dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org parse_elf_string_table(&elf, 513dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org shdr.sh_link, 514dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org sym.st_name), 515dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org val); 516dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org break; 5176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org default: 5186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%s = %d\n", 5196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 5206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 5226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 523474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 5246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 525474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 5266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 527474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 5286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { /* if (elf.bits == 64) */ 5296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Shdr shdr; 5306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < elf.hdr64.e_shnum; i++) { 5316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, i, NULL, &shdr); 5326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (shdr.sh_type == SHT_SYMTAB) { 5346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (ofst = shdr.sh_offset; 5356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ofst < shdr.sh_offset + shdr.sh_size; 5366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ofst += shdr.sh_entsize) { 5376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Sym sym; 5386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_symbol(&elf, ofst, NULL, &sym); 5406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* For all OBJECTS (data objects), extract the value from the 5426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * proper data segment. 5436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 5446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name) 5456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("found data object %s\n", 5466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 5476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name)); 5496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 5506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT 5526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org && sym.st_size == 4) { 5536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Elf64_Shdr dhdr; 5546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int val = 0; 5556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char section_name[128]; 5566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr); 5586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* For explanition - refer to _MSC_VER version of code */ 5606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name)); 5616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */ 5626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if ((strcmp(section_name, ".bss"))) { 5646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sizeof(val) != sym.st_size) { 5656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* The target value is declared as an int in 5664b95526e5c4eb4fecde1cd642cf991a82c51b9f2johannkoenig@chromium.org * *_asm_*_offsets.c, which is 4 bytes on all 5676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * targets we currently use. Complain loudly if 5686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * this is not true. 5696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 5706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Symbol size is wrong\n"); 5716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 5726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 5736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org memcpy(&val, 5756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org elf.buf + dhdr.sh_offset + sym.st_value, 5766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_size); 5776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 5786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!elf.le_data) { 5806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Big Endian data not supported yet!\n"); 5816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 5826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 5836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 5846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org switch (mode) { 5856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org case OUTPUT_FMT_RVDS: 5866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU %5d\n", 5876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 5886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 5906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 5916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 5926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org case OUTPUT_FMT_GAS: 5936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf(".equ %-40s, %5d\n", 5946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 5956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 5966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 5976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 5986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org break; 5996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org default: 6006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%s = %d\n", 6016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org parse_elf_string_table(&elf, 6026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org shdr.sh_link, 6036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sym.st_name), 6046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org val); 605474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 6066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 607474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 6086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 609474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 6106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 611474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (mode == OUTPUT_FMT_RVDS) 6136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf(" END\n"); 614474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 616474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 6176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n"); 6186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 619474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 620474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 621474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif 622474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif /* defined(__GNUC__) && __GNUC__ */ 623474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 624474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 625474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) 626474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* See "Microsoft Portable Executable and Common Object File Format Specification" 627474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org for reference. 628474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org*/ 629474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 ) 630474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define get_le16(x) ((*(x)) | (*(x+1)) << 8) 631474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint parse_coff(uint8_t *buf, size_t sz) { 6336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr; 6346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org unsigned int sectionrawdata_ptr; 6356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org unsigned int i; 6366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *ptr; 6376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint32_t symoffset; 638474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char **sectionlist; // this array holds all section names in their correct order. 6406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // it is used to check if the symbol is in .bss or .rdata section. 641474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org nsections = get_le16(buf + 2); 6436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org symtab_ptr = get_le32(buf + 8); 6446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org symtab_sz = get_le32(buf + 12); 6456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strtab_ptr = symtab_ptr + symtab_sz * 18; 646474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (nsections > 96) { 6486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Too many sections\n"); 6496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 6506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 651474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sectionlist = malloc(nsections * sizeof(sectionlist)); 653474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sectionlist == NULL) { 6556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Allocating first level of section list failed\n"); 6566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 6576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 658474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections); 660474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* 6626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org The size of optional header is always zero for an obj file. So, the section header 6636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org follows the file header immediately. 6646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 665474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ptr = buf + 20; // section header 667474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < nsections; i++) { 6696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 6706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strncpy(sectionname, ptr, 8); 6716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: Parsing section %s\n",sectionname); 672474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org sectionlist[i] = malloc(strlen(sectionname) + 1); 674474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 6756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (sectionlist[i] == NULL) { 6766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org log_msg("Allocating storage for %s failed\n", sectionname); 6776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 6786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 6796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strcpy(sectionlist[i], sectionname); 6806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 68176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org // check if it's .rdata and is not a COMDAT section. 68276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org if (!strcmp(sectionname, ".rdata") && 68376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org (get_le32(ptr + 36) & 0x1000) == 0) { 68476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org sectionrawdata_ptr = get_le32(ptr + 20); 68576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org } 6866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 6876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ptr += 40; 6886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 6896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 6906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: Symbol table at offset %u\n", symtab_ptr); 6916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: raw data pointer ofset for section .rdata is %u\n", sectionrawdata_ptr); 6926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 6936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* The compiler puts the data with non-zero offset in .rdata section, but puts the data with 6946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org zero offset in .bss section. So, if the data in in .bss section, set offset=0. 6956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Note from Wiki: In an object module compiled from C, the bss section contains 6966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org the local variables (but not functions) that were declared with the static keyword, 6976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org except for those with non-zero initial values. (In C, static variables are initialized 6986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org to zero by default.) It also contains the non-local (both extern and static) variables 6996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org that are also initialized to zero (either explicitly or by default). 7006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 7016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // move to symbol table 7026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* COFF symbol table: 7036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org offset field 7046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 0 Name(*) 7056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8 Value 7066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 12 SectionNumber 7076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 14 Type 7086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 16 StorageClass 7096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 17 NumberOfAuxSymbols 7106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 7116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ptr = buf + symtab_ptr; 7126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < symtab_sz; i++) { 7146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int16_t section = get_le16(ptr + 12); // section number 7156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (section > 0 && ptr[16] == 2) { 7176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) { 7186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (get_le32(ptr)) { 7206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 7216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org strncpy(name, ptr, 8); 7226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: Parsing symbol %s\n",name); 7236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org /* The 64bit Windows compiler doesn't prefix with an _. 7246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Check what's there, and bump if necessary 7256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org */ 7266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (name[0] == '_') 7276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU ", name + 1); 7286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org else 7296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU ", name); 7306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { 7316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg("COFF: Parsing symbol %s\n", 7326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // buf + strtab_ptr + get_le32(ptr+4)); 7336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_') 7346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU ", 7356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org buf + strtab_ptr + get_le32(ptr + 4) + 1); 7366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org else 7376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4)); 7386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 739474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!(strcmp(sectionlist[section - 1], ".bss"))) { 7416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org symoffset = 0; 7426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } else { 7436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8)); 7446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 745474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg(" Section: %d\n",section); 7476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg(" Class: %d\n",ptr[16]); 7486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg(" Address: %u\n",get_le32(ptr+8)); 7496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org // log_msg(" Offset: %u\n", symoffset); 750474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf("%5d\n", symoffset); 752474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 753474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ptr += 18; 7556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 756474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org printf(" END\n"); 7586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < nsections; i++) { 7606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org free(sectionlist[i]); 7616fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 762474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org free(sectionlist); 764474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 0; 766474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 767474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org for (i = 0; i < nsections; i++) { 7696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org free(sectionlist[i]); 7706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 771474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org free(sectionlist); 773474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return 1; 775474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 776474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */ 777474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint main(int argc, char **argv) { 7796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org output_fmt_t mode = OUTPUT_FMT_PLAIN; 7806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org const char *f; 7816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint8_t *file_buf; 7826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int res; 7836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org FILE *fp; 7846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org long int file_size; 7856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (argc < 2 || argc > 3) { 7876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]); 7886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fprintf(stderr, " <obj file>\tobject file to parse\n"); 7896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fprintf(stderr, "Output Formats:\n"); 7906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fprintf(stderr, " gas - compatible with GNU assembler\n"); 7916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fprintf(stderr, " rvds - compatible with armasm\n"); 792dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org fprintf(stderr, " cheader - c/c++ header file\n"); 7936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 7946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 7956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org f = argv[2]; 7976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 7986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!strcmp(argv[1], "rvds")) 7996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org mode = OUTPUT_FMT_RVDS; 8006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org else if (!strcmp(argv[1], "gas")) 8016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org mode = OUTPUT_FMT_GAS; 802dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org else if (!strcmp(argv[1], "cheader")) 803dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org mode = OUTPUT_FMT_C_HEADER; 8046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org else 8056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org f = argv[1]; 8066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org fp = fopen(f, "rb"); 8086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!fp) { 8106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org perror("Unable to open file"); 8116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 8126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 8136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (fseek(fp, 0, SEEK_END)) { 8156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org perror("stat"); 8166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 8176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 8186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org file_size = ftell(fp); 8206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org file_buf = malloc(file_size); 8216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!file_buf) { 8236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org perror("malloc"); 8246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 8256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 8266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org rewind(fp); 8286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (fread(file_buf, sizeof(char), file_size, fp) != file_size) { 8306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org perror("read"); 8316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 8326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 8336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 8346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (fclose(fp)) { 8356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org perror("close"); 8366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org goto bail; 8376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 838474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 839474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(__GNUC__) && __GNUC__ 840474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(__MACH__) 841eb258edff400f60da51756318fa4f0d197f77725fischman@chromium.org res = parse_macho(file_buf, file_size, mode); 842474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#elif defined(__ELF__) 8436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res = parse_elf(file_buf, file_size, mode); 844474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif 845474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif 846474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) 8476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org res = parse_coff(file_buf, file_size); 848474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif 849474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 8506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org free(file_buf); 851474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 8526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!res) 8536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return EXIT_SUCCESS; 854474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 855474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail: 8566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return EXIT_FAILURE; 857474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 858