i965_disasm.c revision 7ec681f3
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 struct intel_device_info * 117i965_disasm_init(uint16_t pci_id) 118{ 119 struct intel_device_info *devinfo; 120 121 devinfo = malloc(sizeof *devinfo); 122 if (devinfo == NULL) 123 return NULL; 124 125 if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) { 126 fprintf(stderr, "can't find device information: pci_id=0x%x\n", 127 pci_id); 128 exit(EXIT_FAILURE); 129 } 130 131 return devinfo; 132} 133 134static void 135print_help(const char *progname, FILE *file) 136{ 137 fprintf(file, 138 "Usage: %s [OPTION]...\n" 139 "Disassemble i965 instructions from binary file.\n\n" 140 " --help display this help and exit\n" 141 " --input-path=PATH read binary file from binary file PATH\n" 142 " --type=INPUT_TYPE INPUT_TYPE can be 'bin' (default if omitted),\n" 143 " 'c_literal'.\n" 144 " --gen=platform disassemble instructions for given \n" 145 " platform (3 letter platform name)\n", 146 progname); 147} 148 149int main(int argc, char *argv[]) 150{ 151 FILE *fp = NULL; 152 void *assembly = NULL; 153 char *file_path = NULL; 154 size_t start = 0, end = 0; 155 uint16_t pci_id = 0; 156 int c; 157 struct intel_device_info *devinfo = NULL; 158 int result = EXIT_FAILURE; 159 160 bool help = false; 161 const struct option i965_disasm_opts[] = { 162 { "help", no_argument, (int *) &help, true }, 163 { "input-path", required_argument, NULL, 'i' }, 164 { "type", required_argument, NULL, 't' }, 165 { "gen", required_argument, NULL, 'g'}, 166 { NULL, 0, NULL, 0 } 167 }; 168 169 while ((c = getopt_long(argc, argv, ":i:t:g:h", i965_disasm_opts, NULL)) != -1) { 170 switch (c) { 171 case 'g': { 172 const int id = intel_device_name_to_pci_device_id(optarg); 173 if (id < 0) { 174 fprintf(stderr, "can't parse gen: '%s', expected 3 letter " 175 "platform name\n", optarg); 176 goto end; 177 } else { 178 pci_id = id; 179 } 180 break; 181 } 182 case 'i': 183 file_path = strdup(optarg); 184 fp = fopen(file_path, "r"); 185 if (!fp) { 186 fprintf(stderr, "Unable to read input file : %s\n", 187 file_path); 188 goto end; 189 } 190 break; 191 case 't': 192 if (strcmp(optarg, "c_literal") == 0) { 193 input_type = OPT_INPUT_C_LITERAL; 194 } else if (strcmp(optarg, "bin") == 0) { 195 input_type = OPT_INPUT_BINARY; 196 } else { 197 fprintf(stderr, "invalid value for --type: %s\n", optarg); 198 goto end; 199 } 200 break; 201 case 'h': 202 help = true; 203 print_help(argv[0], stderr); 204 goto end; 205 case 0: 206 break; 207 case ':': 208 fprintf(stderr, "%s: option `-%c' requires an argument\n", 209 argv[0], optopt); 210 goto end; 211 case '?': 212 default: 213 fprintf(stderr, "%s: option `-%c' is invalid: ignored\n", 214 argv[0], optopt); 215 goto end; 216 } 217 } 218 219 if (help || !file_path || !pci_id) { 220 print_help(argv[0], stderr); 221 exit(0); 222 } 223 224 devinfo = i965_disasm_init(pci_id); 225 if (!devinfo) { 226 fprintf(stderr, "Unable to allocate memory for " 227 "intel_device_info struct instance.\n"); 228 goto end; 229 } 230 231 if (input_type == OPT_INPUT_BINARY) 232 assembly = i965_disasm_read_binary(fp, &end); 233 else if (input_type == OPT_INPUT_C_LITERAL) 234 assembly = i965_disasm_read_c_literal_file(fp, &end); 235 236 if (!assembly) { 237 if (end) 238 fprintf(stderr, "Unable to allocate buffer to read input file\n"); 239 else 240 fprintf(stderr, "Failed to read input file\n"); 241 242 goto end; 243 } 244 245 /* Disassemble i965 instructions from buffer assembly */ 246 brw_disassemble_with_labels(devinfo, assembly, start, end, stdout); 247 248 result = EXIT_SUCCESS; 249 250end: 251 if (fp) 252 fclose(fp); 253 254 free(file_path); 255 free(assembly); 256 free(devinfo); 257 258 exit(result); 259} 260