~jonls/libdisarm/master

« back to all changes in this revision

Viewing changes to src/dacli/dacli.c

  • Committer: Jon Lund Steffensen
  • Date: 2013-08-11 09:39:02 UTC
  • Revision ID: git-v1:a5b3c1ed07261da88a155e8b4c2c75ba7ebae810
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * dacli.c - libdisarm command line interface
 
3
 *
 
4
 * Copyright (C) 2007  Jon Lund Steffensen <jonlst@gmail.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
# include <config.h>
 
23
#endif
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include <ctype.h>
 
29
#include <unistd.h>
 
30
 
 
31
#include <libdisarm/disarm.h>
 
32
 
 
33
 
 
34
#define USAGE \
 
35
        "Usage: %s [-EB|-EL] [-h] [-m OFFSET] [-s SKIP] [FILE]\n"
 
36
#define HELP \
 
37
        USAGE \
 
38
        " Disassemble ARM machine code from FILE or standard input.\n" \
 
39
        "  -EB\t\tRead input as big endian data\n" \
 
40
        "  -EL\t\tRead input as little endian data\n" \
 
41
        "  -h\t\tDisplay this help message\n" \
 
42
        "  -m OFFSET\tUse OFFSET as memory address of input\n" \
 
43
        "  -s SKIP\tNumber of bytes to skip before disassembly\n" \
 
44
        "Report bugs to <" PACKAGE_BUGREPORT ">.\n"
 
45
 
 
46
/* Return -1 on error, 0 on EOF, 1 on succesful read. */
 
47
int
 
48
read_hex_input(void *dest, size_t size, FILE *f)
 
49
{
 
50
        int c = fgetc(f);
 
51
        if (c == EOF) return 0;
 
52
        
 
53
        int i;
 
54
        for (i = 0; i < size; i++) {
 
55
                while (isspace(c)) {
 
56
                        c = fgetc(f);
 
57
                }
 
58
 
 
59
                if (c == EOF) return 0;
 
60
 
 
61
                int byte = 0;
 
62
                int j;
 
63
                for (j = 0; j < 2; j++) {
 
64
                        int input;
 
65
                        if (c >= '0' && c <= '9') {
 
66
                                input = c - '0';
 
67
                        } else if (c >= 'a' && c <= 'f') {
 
68
                                input = c - 'a' + 10;
 
69
                        } else if (c >= 'A' && c <= 'F') {
 
70
                                input = c - 'A' + 10;
 
71
                        } else if (j > 0 && isspace(c)) {
 
72
                                break;
 
73
                        } else {
 
74
                                return -1;
 
75
                        }
 
76
                                        
 
77
                        byte = (byte << 4) | input;
 
78
 
 
79
                        c = fgetc(f);
 
80
                        if (c == EOF) break;
 
81
                }
 
82
 
 
83
                ((unsigned char *)dest)[i] = byte;
 
84
        }
 
85
 
 
86
        return 1;
 
87
}
 
88
 
 
89
int
 
90
main(int argc, char *argv[])
 
91
{
 
92
        int r;
 
93
 
 
94
        int hex_input = 0;
 
95
        da_addr_t mem_offset = 0;
 
96
        off_t file_offset = 0;
 
97
        ssize_t disasm_size = -1;
 
98
        int big_endian = 0;
 
99
 
 
100
        int opt;
 
101
        while ((opt = getopt(argc, argv, "c:E:hm:s:x")) != -1) {
 
102
                switch (opt) {
 
103
                case 'c':
 
104
                        disasm_size = atoi(optarg);
 
105
                        break;
 
106
                case 'E':
 
107
                        if (optarg != NULL &&
 
108
                            (optarg[0] == 'B' || optarg[0] == 'L')) {
 
109
                                big_endian = (optarg[0] == 'B');
 
110
                        } else {
 
111
                                fprintf(stderr, USAGE, argv[0]);
 
112
                                exit(EXIT_FAILURE);
 
113
                        }
 
114
                        break;
 
115
                case 'h':
 
116
                        printf(HELP, argv[0]);
 
117
                        exit(EXIT_SUCCESS);
 
118
                        break;
 
119
                case 'm':
 
120
                        mem_offset = atoi(optarg);
 
121
                        break;
 
122
                case 's':
 
123
                        file_offset = atoi(optarg);
 
124
                        break;
 
125
                case 'x':
 
126
                        hex_input = 1;
 
127
                        break;
 
128
                default:
 
129
                        fprintf(stderr, USAGE, argv[0]);
 
130
                        exit(EXIT_FAILURE);
 
131
                }
 
132
        }
 
133
 
 
134
        FILE *f = stdin;
 
135
        
 
136
        if (optind < argc && strcmp(argv[optind], "-")) {
 
137
                f = fopen(argv[optind], "rb");
 
138
                if (f == NULL) {
 
139
                        perror("fopen");
 
140
                        exit(EXIT_FAILURE);
 
141
                }
 
142
 
 
143
                if (file_offset > 0) {
 
144
                        r = fseek(f, file_offset, SEEK_SET);
 
145
                        if (r < 0) {
 
146
                                perror("fseek");
 
147
                                exit(EXIT_FAILURE);
 
148
                        }
 
149
                }
 
150
        }
 
151
 
 
152
        da_addr_t addr = mem_offset;
 
153
 
 
154
        while (disasm_size < 0 || addr < mem_offset + disasm_size) {
 
155
                da_word_t data;
 
156
 
 
157
                if (!hex_input) {
 
158
                        size_t read = fread(&data, sizeof(da_word_t), 1, f);
 
159
                        if (read < 1) {
 
160
                                if (feof(f)) break;
 
161
                                else {
 
162
                                        perror("fread");
 
163
                                        exit(EXIT_FAILURE);
 
164
                                }
 
165
                        }
 
166
                } else {
 
167
                        r = read_hex_input(&data, sizeof(da_word_t), f);
 
168
                        if (r < 0) {
 
169
                                fprintf(stderr, "Unable to parse input.\n");
 
170
                                exit(EXIT_FAILURE);
 
171
                        } else if (r == 0) {
 
172
                                break;
 
173
                        }
 
174
                }
 
175
                
 
176
                da_instr_t instr;
 
177
                da_instr_args_t args;
 
178
                da_instr_parse(&instr, data, big_endian);
 
179
                da_instr_parse_args(&args, &instr);
 
180
 
 
181
                printf("%08x\t", addr);
 
182
                printf("%08x\t", instr.data);
 
183
                da_instr_fprint(stdout, &instr, &args, addr);
 
184
                printf("\n");
 
185
 
 
186
                addr += sizeof(da_word_t);
 
187
        }
 
188
 
 
189
        r = fclose(f);
 
190
        if (r < 0) {
 
191
                perror("fclose");
 
192
                exit(EXIT_FAILURE);
 
193
        }
 
194
        
 
195
        return EXIT_SUCCESS;
 
196
}