From: Michael Buesch Date: Sun, 18 Nov 2007 13:57:35 +0000 (+0100) Subject: dasm: Rewrite cmdline arg parsing and remove the bin wrapper script. X-Git-Tag: b43-fwcutter-013~80 X-Git-Url: https://jxself.org/git/?a=commitdiff_plain;h=2e928c1b94243e38477f113b92d78876a15439be;p=b43-tools.git dasm: Rewrite cmdline arg parsing and remove the bin wrapper script. Signed-off-by: Michael Buesch --- diff --git a/disassembler/Makefile b/disassembler/Makefile index 3939222..e664722 100644 --- a/disassembler/Makefile +++ b/disassembler/Makefile @@ -1,26 +1,28 @@ -CC = gcc -PREFIX = /usr/local -CFLAGS = -std=gnu99 -O2 -fomit-frame-pointer -Wall -D_BSD_SOURCE -D_GNU_SOURCE -LDFLAGS = +CC ?= gcc -BINARY = b43-dasm.bin -OBJECTS = main.o util.o +PREFIX ?= /usr/local -all: $(BINARY) +CFLAGS ?= -O2 -fomit-frame-pointer +CFLAGS += -std=gnu99 -Wall -D_BSD_SOURCE -D_GNU_SOURCE +LDFLAGS ?= -main.o: util.h list.h +BIN = b43-dasm +OBJECTS = main.o util.o args.o + +all: $(BIN) + +main.o: main.h util.h list.h args.h util.o: util.h -$(BINARY): $(OBJECTS) - $(CC) $(CFLAGS) -o $(BINARY) $(OBJECTS) $(LDFLAGS) +$(BIN): $(OBJECTS) + $(CC) $(CFLAGS) -o $(BIN) $(OBJECTS) $(LDFLAGS) install: all - -install -o 0 -g 0 -m 755 $(BINARY) $(PREFIX)/bin/ - -cp b43-dasm b43-dasm.inst - -sed -i -e 's/installed=0/installed=1/' b43-dasm.inst - -install -o 0 -g 0 -m 755 b43-dasm.inst $(PREFIX)/bin/b43-dasm - -rm -f b43-dasm.inst + -install -o 0 -g 0 -m 755 $(BIN) $(PREFIX)/bin/ clean: - -rm -f *~ *.o *.orig *.rej $(BINARY) + -rm -f *~ *.o *.orig *.rej + +distclean: clean + -rm -f $(BIN) diff --git a/disassembler/args.c b/disassembler/args.c new file mode 100644 index 0000000..2848089 --- /dev/null +++ b/disassembler/args.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2006-2007 Michael Buesch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "args.h" +#include "main.h" +#include "util.h" + +#include +#include +#include +#include +#include + + +int _debug; + +struct cmdline_args cmdargs = { + .arch = 5, /* Default to v5 architecture. */ +}; + +#define ARG_MATCH 0 +#define ARG_NOMATCH 1 +#define ARG_ERROR -1 + +static int do_cmp_arg(char **argv, int *pos, + const char *template, + int allow_merged, + char **param) +{ + char *arg; + char *next_arg; + size_t arg_len, template_len; + + arg = argv[*pos]; + next_arg = argv[*pos + 1]; + arg_len = strlen(arg); + template_len = strlen(template); + + if (param) { + /* Maybe we have a merged parameter here. + * A merged parameter is "-pfoobar" for example. + */ + if (allow_merged && arg_len > template_len) { + if (memcmp(arg, template, template_len) == 0) { + *param = arg + template_len; + return ARG_MATCH; + } + return ARG_NOMATCH; + } else if (arg_len != template_len) + return ARG_NOMATCH; + *param = next_arg; + } + if (strcmp(arg, template) == 0) { + if (param) { + /* Skip the parameter on the next iteration. */ + (*pos)++; + if (*param == 0) { + fprintf(stderr, "%s needs a parameter\n", arg); + return ARG_ERROR; + } + } + return ARG_MATCH; + } + + return ARG_NOMATCH; +} + +/* Simple and lean command line argument parsing. */ +static int cmp_arg(char **argv, int *pos, + const char *long_template, + const char *short_template, + char **param) +{ + int err; + + if (long_template) { + err = do_cmp_arg(argv, pos, long_template, 0, param); + if (err == ARG_MATCH || err == ARG_ERROR) + return err; + } + err = ARG_NOMATCH; + if (short_template) + err = do_cmp_arg(argv, pos, short_template, 1, param); + return err; +} + +static void usage(int argc, char **argv) +{ + fprintf(stderr, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]); + fprintf(stderr, " -a|--arch ARCH The architecture type of the input file\n"); + fprintf(stderr, " -h|--help Print this help\n"); + fprintf(stderr, " -d|--debug Print verbose debugging info\n"); + fprintf(stderr, " Repeat for more verbose debugging\n"); +} + +int parse_args(int argc, char **argv) +{ + int i; + int res; + char *param; + + infile_name = NULL; + outfile_name = NULL; + + for (i = 1; i < argc; i++) { + if ((res = cmp_arg(argv, &i, "--help", "-h", 0)) == ARG_MATCH) { + usage(argc, argv); + return 1; + } else if ((res = cmp_arg(argv, &i, "--debug", "-d", 0)) == ARG_MATCH) { + _debug++; + } else if ((res = cmp_arg(argv, &i, "--arch", "-a", ¶m)) == ARG_MATCH) { + unsigned long arch; + char *tail; + + arch = strtol(param, &tail, 0); + if (strlen(tail) || (arch != 5)) { + fprintf(stderr, "Unsupported architecture \"%s\"\n", + param); + return -1; + } + cmdargs.arch = arch; + } else { + if (!infile_name) { + infile_name = argv[i]; + continue; + } + if (!outfile_name) { + outfile_name = argv[i]; + continue; + } + fprintf(stderr, "Unrecognized argument: %s\n", argv[i]); + goto out_usage; + } + } + if (!infile_name || !outfile_name) + goto out_usage; + + return 0; +out_usage: + usage(argc, argv); + return -1; +} + +int open_input_file(void) +{ + if (strcmp(infile_name, "-") == 0) { + infile = stdin; + } else { + infile = fopen(infile_name, "r"); + if (!infile) { + fprintf(stderr, "Could not open INPUT_FILE %s\n", + infile_name); + return -1; + } + } + + return 0; +} + +void close_input_file(void) +{ + if (strcmp(infile_name, "-") != 0) + fclose(infile); +} + +int open_output_file(void) +{ + if (strcmp(outfile_name, "-") == 0) { + outfile = stdout; + } else { + outfile = fopen(outfile_name, "w+"); + if (!outfile) { + fprintf(stderr, "Could not open OUTPUT_FILE %s\n", + outfile_name); + return -1; + } + } + + return 0; +} + +void close_output_file(void) +{ + if (strcmp(outfile_name, "-") != 0) + fclose(outfile); +} diff --git a/disassembler/args.h b/disassembler/args.h new file mode 100644 index 0000000..d13fa66 --- /dev/null +++ b/disassembler/args.h @@ -0,0 +1,22 @@ +#ifndef B43_DASM_ARGS_H_ +#define B43_DASM_ARGS_H_ + +struct cmdline_args { + unsigned int arch; +}; + +int parse_args(int argc, char **argv); + +int open_input_file(void); +void close_input_file(void); +int open_output_file(void); +void close_output_file(void); + +extern int _debug; +extern struct cmdline_args cmdargs; + +#define IS_DEBUG (_debug > 0) +#define IS_VERBOSE_DEBUG (_debug > 1) +#define IS_INSANE_DEBUG (_debug > 2) + +#endif /* B43_DASM_ARGS_H_ */ diff --git a/disassembler/b43-dasm b/disassembler/b43-dasm deleted file mode 100755 index be48c71..0000000 --- a/disassembler/b43-dasm +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -installed=0 - -if [ $# -ne 2 ]; then - echo "Usage: $0 input_file.fw output_file.asm" - exit 1 -fi - -if [ -z "$B43_DASM" ]; then - if [ $installed -eq 0 ] && [ -x "./b43-dasm.bin" ]; then - B43_DASM="./b43-dasm.bin" - else - B43_DASM="b43-dasm.bin" - fi -fi - -infile="$1" -outfile="$2" - -cat "$infile" | $B43_DASM "$outfile" - diff --git a/disassembler/main.c b/disassembler/main.c index e984480..8ae8040 100644 --- a/disassembler/main.c +++ b/disassembler/main.c @@ -13,6 +13,7 @@ #include "list.h" #include "util.h" +#include "args.h" #include #include @@ -64,6 +65,9 @@ struct statement { }; struct disassembler_context { + /* The architecture of the input file. */ + unsigned int arch; + struct bin_instruction *code; size_t nr_insns; @@ -71,7 +75,9 @@ struct disassembler_context { }; -static FILE *infile; +FILE *infile; +FILE *outfile; +const char *infile_name; const char *outfile_name; @@ -635,48 +641,46 @@ static void resolve_labels(struct disassembler_context *ctx) static void emit_asm(struct disassembler_context *ctx) { struct statement *stmt; - FILE *fd; int first, i; + int err; - fd = fopen(outfile_name, "w+"); - if (!fd) { - fprintf(stderr, "Could not open output file \"%s\"\n", - outfile_name); + err = open_output_file(); + if (err) exit(1); - } - /* FIXME: We currently only support v5 architecture. */ - fprintf(fd, "%%arch 5\n\n"); + + fprintf(outfile, "%%arch %u\n\n", ctx->arch); list_for_each_entry(stmt, &ctx->stmt_list, list) { switch (stmt->type) { case STMT_INSN: - fprintf(fd, "\t%s", stmt->u.insn.name); + fprintf(outfile, "\t%s", stmt->u.insn.name); first = 1; for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) { if (stmt->u.insn.is_labelref == i) { - fprintf(fd, ",%s", + fprintf(outfile, ",%s", stmt->u.insn.labelref->u.label.name); } if (!stmt->u.insn.operands[i]) continue; if (first) - fprintf(fd, "\t"); + fprintf(outfile, "\t"); if (!first) - fprintf(fd, ","); + fprintf(outfile, ","); first = 0; - fprintf(fd, "%s", + fprintf(outfile, "%s", stmt->u.insn.operands[i]); } - fprintf(fd, "\n"); + fprintf(outfile, "\n"); break; case STMT_LABEL: - fprintf(fd, "%s:\n", stmt->u.label.name); + fprintf(outfile, "%s:\n", stmt->u.label.name); break; } } - fclose(fd); + + close_output_file(); } -static void read_input(struct disassembler_context *ctx) +static int read_input(struct disassembler_context *ctx) { size_t size = 0, pos = 0; size_t ret; @@ -684,21 +688,24 @@ static void read_input(struct disassembler_context *ctx) unsigned char tmp[sizeof(uint64_t)]; uint64_t codeword; struct fw_header hdr; + int err; + + err = open_input_file(); + if (err) + goto error; ret = fread(&hdr, 1, sizeof(hdr), infile); - if (!ret || ret != sizeof(hdr)) { + if (ret != sizeof(hdr)) { fprintf(stderr, "Corrupt input file (not fwcutter output)\n"); - exit(1); - } - - if (hdr.ver != 1) { - fprintf(stderr, "Invalid fwcutter header version\n"); - exit(1); + goto err_close; } - if (hdr.type != 'u') { - fprintf(stderr, "Not a microcode image\n"); - exit(1); + fprintf(stderr, "Corrupt input file. Not a microcode image.\n"); + goto err_close; + } + if (hdr.ver != 1) { + fprintf(stderr, "Invalid input file header version.\n"); + goto err_close; } while (1) { @@ -711,7 +718,7 @@ static void read_input(struct disassembler_context *ctx) break; if (ret != sizeof(uint64_t)) { fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n"); - exit(1); + goto err_free_code; } codeword = 0; @@ -735,41 +742,50 @@ static void read_input(struct disassembler_context *ctx) ctx->code = code; ctx->nr_insns = pos; + + close_input_file(); + + return 0; + +err_free_code: + free(code); +err_close: + close_input_file(); +error: + return -1; } static void disassemble(void) { struct disassembler_context ctx; + int err; memset(&ctx, 0, sizeof(ctx)); INIT_LIST_HEAD(&ctx.stmt_list); + ctx.arch = cmdargs.arch; - read_input(&ctx); + err = read_input(&ctx); + if (err) + exit(1); disasm_opcodes(&ctx); resolve_labels(&ctx); emit_asm(&ctx); } -static void usage(int argc, char **argv) -{ - fprintf(stderr, "Usage: %s output_file\n", argv[0]); -} - -static void parse_args(int argc, char **argv) -{ - if (argc != 2) { - usage(argc, argv); - exit(1); - } - outfile_name = argv[1]; -} - int main(int argc, char **argv) { - infile = stdin; - parse_args(argc, argv); + int err, res = 1; + + err = parse_args(argc, argv); + if (err < 0) + goto out; + if (err > 0) { + res = 0; + goto out; + } disassemble(); - + res = 0; +out: /* Lazyman simply leaks all allocated memory. */ - return 0; + return res; } diff --git a/disassembler/main.h b/disassembler/main.h new file mode 100644 index 0000000..d3ceb37 --- /dev/null +++ b/disassembler/main.h @@ -0,0 +1,12 @@ +#ifndef B43_DASM_MAIN_H_ +#define B43_DASM_MAIN_H_ + +#include + + +FILE *infile; +FILE *outfile; +const char *infile_name; +const char *outfile_name; + +#endif /* B43_DASM_MAIN_H_ */