1/*===-- disassemble.c - tool for testing libLLVM and llvm-c API -----------===*\
2|*                                                                            *|
3|*                     The LLVM Compiler Infrastructure                       *|
4|*                                                                            *|
5|* This file is distributed under the University of Illinois Open Source      *|
6|* License. See LICENSE.TXT for details.                                      *|
7|*                                                                            *|
8|*===----------------------------------------------------------------------===*|
9|*                                                                            *|
10|* This file implements the --disassemble command in llvm-c-test.             *|
11|* --disassemble reads lines from stdin, parses them as a triple and hex      *|
12|*  machine code, and prints disassembly of the machine code.                 *|
13|*                                                                            *|
14\*===----------------------------------------------------------------------===*/
15
16#include "llvm-c-test.h"
17#include "llvm-c/Disassembler.h"
18#include "llvm-c/Target.h"
19#include <stdio.h>
20#include <stdlib.h>
21
22static void pprint(int pos, unsigned char *buf, int len, const char *disasm) {
23  int i;
24  printf("%04x:  ", pos);
25  for (i = 0; i < 8; i++) {
26    if (i < len) {
27      printf("%02x ", buf[i]);
28    } else {
29      printf("   ");
30    }
31  }
32
33  printf("   %s\n", disasm);
34}
35
36static void do_disassemble(const char *triple, unsigned char *buf, int siz) {
37  LLVMDisasmContextRef D = LLVMCreateDisasm(triple, NULL, 0, NULL, NULL);
38  char outline[1024];
39  int pos;
40
41  if (!D) {
42    printf("ERROR: Couldn't create disassebler for triple %s\n", triple);
43    return;
44  }
45
46  pos = 0;
47  while (pos < siz) {
48    size_t l = LLVMDisasmInstruction(D, buf + pos, siz - pos, 0, outline,
49                                     sizeof(outline));
50    if (!l) {
51      pprint(pos, buf + pos, 1, "\t???");
52      pos++;
53    } else {
54      pprint(pos, buf + pos, l, outline);
55      pos += l;
56    }
57  }
58
59  LLVMDisasmDispose(D);
60}
61
62static void handle_line(char **tokens, int ntokens) {
63  unsigned char disbuf[128];
64  size_t disbuflen = 0;
65  char *triple = tokens[0];
66  int i;
67
68  printf("triple: %s\n", triple);
69
70  for (i = 1; i < ntokens; i++) {
71    disbuf[disbuflen++] = strtol(tokens[i], NULL, 16);
72    if (disbuflen >= sizeof(disbuf)) {
73      fprintf(stderr, "Warning: Too long line, truncating\n");
74      break;
75    }
76  }
77  do_disassemble(triple, disbuf, disbuflen);
78}
79
80int disassemble(void) {
81  LLVMInitializeAllTargetInfos();
82  LLVMInitializeAllTargetMCs();
83  LLVMInitializeAllDisassemblers();
84
85  tokenize_stdin(handle_line);
86
87  return 0;
88}
89