1/* 2 * Copyright © 2018 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27#include <getopt.h> 28 29#include "compiler/brw_eu.h" 30#include "dev/intel_device_info.h" 31#include "util/u_dynarray.h" 32 33enum opt_input_type { 34 OPT_INPUT_BINARY, 35 OPT_INPUT_C_LITERAL, 36}; 37 38static enum opt_input_type input_type = OPT_INPUT_BINARY; 39 40/* Return size of file in bytes pointed by fp */ 41static long 42i965_disasm_get_file_size(FILE *fp) 43{ 44 long size; 45 46 fseek(fp, 0L, SEEK_END); 47 size = ftell(fp); 48 fseek(fp, 0L, SEEK_SET); 49 50 return size; 51} 52 53/* Read hex file which should be in following format: 54 * for example : 55 * { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } 56 */ 57static void * 58i965_disasm_read_c_literal_file(FILE *fp, size_t *end) 59{ 60 struct util_dynarray assembly = {}; 61 uint32_t temp[2]; 62 63 if (fscanf(fp, " { ") == EOF) { 64 fprintf(stderr, "Couldn't find opening `{`\n"); 65 return NULL; 66 } 67 68 if (fscanf(fp, "0x%x , 0x%x", &temp[0], &temp[1]) == 2) { 69 util_dynarray_append(&assembly, uint32_t, temp[0]); 70 util_dynarray_append(&assembly, uint32_t, temp[1]); 71 } else { 72 fprintf(stderr, "Couldn't read hex values\n"); 73 return NULL; 74 } 75 76 while (fscanf(fp, " , 0x%x , 0x%x ", &temp[0], &temp[1]) == 2) { 77 util_dynarray_append(&assembly, uint32_t, temp[0]); 78 util_dynarray_append(&assembly, uint32_t, temp[1]); 79 } 80 81 if (fscanf(fp, "}") == EOF) { 82 fprintf(stderr, "Couldn't find closing `}`\n"); 83 return NULL; 84 } 85 86 *end = assembly.size; 87 return assembly.data; 88} 89 90static void * 91i965_disasm_read_binary(FILE *fp, size_t *end) 92{ 93 size_t size; 94 void *assembly; 95 96 long sz = i965_disasm_get_file_size(fp); 97 if (sz < 0) 98 return NULL; 99 100 *end = (size_t)sz; 101 if (!*end) 102 return NULL; 103 104 assembly = malloc(*end + 1); 105 if (assembly == NULL) 106 return NULL; 107 108 size = fread(assembly, *end, 1, fp); 109 if (!size) { 110 free(assembly); 111 return NULL; 112 } 113 return assembly; 114} 115 116static void 117print_help(const char *progname, FILE *file) 118{ 119 fprintf(file, 120 "Usage: %s [OPTION]...\n" 121 "Disassemble i965 instructions from binary file.\n\n" 122 " --help display this help and exit\n" 123 " --input-path=PATH read binary file from binary file PATH\n" 124 " --type=INPUT_TYPE INPUT_TYPE can be 'bin' (default if omitted),\n" 125 " 'c_literal'.\n" 126 " --gen=platform disassemble instructions for given \n" 127 " platform (3 letter platform name)\n", 128 progname); 129} 130 131int main(int argc, char *argv[]) 132{ 133 FILE *fp = NULL; 134 void *assembly = NULL; 135 char *file_path = NULL; 136 size_t start = 0, end = 0; 137 uint16_t pci_id = 0; 138 int c; 139 int result = EXIT_FAILURE; 140 141 bool help = false; 142 const struct option i965_disasm_opts[] = { 143 { "help", no_argument, (int *) &help, true }, 144 { "input-path", required_argument, NULL, 'i' }, 145 { "type", required_argument, NULL, 't' }, 146 { "gen", required_argument, NULL, 'g'}, 147 { NULL, 0, NULL, 0 } 148 }; 149 150 while ((c = getopt_long(argc, argv, ":i:t:g:h", i965_disasm_opts, NULL)) != -1) { 151 switch (c) { 152 case 'g': { 153 const int id = intel_device_name_to_pci_device_id(optarg); 154 if (id < 0) { 155 fprintf(stderr, "can't parse gen: '%s', expected 3 letter " 156 "platform name\n", optarg); 157 goto end; 158 } else { 159 pci_id = id; 160 } 161 break; 162 } 163 case 'i': 164 file_path = strdup(optarg); 165 fp = fopen(file_path, "r"); 166 if (!fp) { 167 fprintf(stderr, "Unable to read input file : %s\n", 168 file_path); 169 goto end; 170 } 171 break; 172 case 't': 173 if (strcmp(optarg, "c_literal") == 0) { 174 input_type = OPT_INPUT_C_LITERAL; 175 } else if (strcmp(optarg, "bin") == 0) { 176 input_type = OPT_INPUT_BINARY; 177 } else { 178 fprintf(stderr, "invalid value for --type: %s\n", optarg); 179 goto end; 180 } 181 break; 182 case 'h': 183 help = true; 184 print_help(argv[0], stderr); 185 goto end; 186 case 0: 187 break; 188 case ':': 189 fprintf(stderr, "%s: option `-%c' requires an argument\n", 190 argv[0], optopt); 191 goto end; 192 case '?': 193 default: 194 fprintf(stderr, "%s: option `-%c' is invalid: ignored\n", 195 argv[0], optopt); 196 goto end; 197 } 198 } 199 200 if (help || !file_path || !pci_id) { 201 print_help(argv[0], stderr); 202 exit(0); 203 } 204 205 struct intel_device_info devinfo; 206 if (!intel_get_device_info_from_pci_id(pci_id, &devinfo)) { 207 fprintf(stderr, "can't find device information: pci_id=0x%x\n", pci_id); 208 exit(EXIT_FAILURE); 209 } 210 211 struct brw_isa_info isa; 212 brw_init_isa_info(&isa, &devinfo); 213 214 if (input_type == OPT_INPUT_BINARY) 215 assembly = i965_disasm_read_binary(fp, &end); 216 else if (input_type == OPT_INPUT_C_LITERAL) 217 assembly = i965_disasm_read_c_literal_file(fp, &end); 218 219 if (!assembly) { 220 if (end) 221 fprintf(stderr, "Unable to allocate buffer to read input file\n"); 222 else 223 fprintf(stderr, "Failed to read input file\n"); 224 225 goto end; 226 } 227 228 /* Disassemble i965 instructions from buffer assembly */ 229 brw_disassemble_with_labels(&isa, assembly, start, end, stdout); 230 231 result = EXIT_SUCCESS; 232 233end: 234 if (fp) 235 fclose(fp); 236 237 free(file_path); 238 free(assembly); 239 240 exit(result); 241} 242