/* $Id$ */ /* Copyright (c) 2011 Pierre Pronchery */ /* This file is part of DeforaOS Devel asm */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "Asm/format.h" #include "format.h" #include "../config.h" /* Format */ /* private */ /* types */ struct _Format { char * arch; FormatPluginHelper helper; Plugin * handle; FormatPlugin * plugin; /* internal */ /* file */ char const * filename; FILE * fp; /* deassembly */ Code * code; }; /* prototypes */ /* callbacks */ static char const * _format_get_filename(Format * format); static ssize_t _format_read(Format * format, void * buf, size_t size); static off_t _format_seek(Format * format, off_t offset, int whence); static ssize_t _format_write(Format * format, void const * buf, size_t size); /* public */ /* functions */ /* format_new */ Format * format_new(char const * format, char const * arch) { Format * f; Plugin * handle; FormatPlugin * plugin; if(format == NULL) { error_set_code(1, "%s", strerror(EINVAL)); return NULL; } if((handle = plugin_new(LIBDIR, PACKAGE, "format", format)) == NULL) return NULL; if((plugin = plugin_lookup(handle, "format_plugin")) == NULL || (f = object_new(sizeof(*f))) == NULL) { plugin_delete(handle); return NULL; } f->arch = string_new(arch); memset(&f->helper, 0, sizeof(f->helper)); f->plugin = plugin; f->handle = handle; if(f->arch == NULL) { format_delete(f); return NULL; } return f; } /* format_delete */ void format_delete(Format * format) { plugin_delete(format->handle); string_delete(format->arch); object_delete(format); } /* accessors */ /* format_get_name */ char const * format_get_name(Format * format) { return format->plugin->name; } /* useful */ /* format_decode */ static int _decode_callback(Format * format, char const * section, off_t offset, size_t size, off_t base); static AsmString * _get_string_by_id_callback(Format * format, AsmId id); static int _set_function_callback(Format * format, int id, char const * name, off_t offset, ssize_t size); static int _set_string_callback(Format * format, int id, char const * name, off_t offset, ssize_t size); int format_decode(Format * format, Code * code) { int ret; if(format->plugin->decode == NULL) return error_set_code(1, "%s: %s", format_get_name(format), "Disassembly is not supported"); format->helper.decode = _decode_callback; format->helper.get_string_by_id = _get_string_by_id_callback; format->helper.set_function = _set_string_callback; format->helper.set_string = _set_string_callback; format->code = code; ret = format->plugin->decode(format->plugin); format->code = NULL; format->helper.set_string = NULL; format->helper.set_function = NULL; format->helper.get_string_by_id = NULL; format->helper.decode = NULL; return ret; } static int _decode_callback(Format * format, char const * section, off_t offset, size_t size, off_t base) { #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__, section, offset, size, base); #endif return code_decode_at(format->code, section, offset, size, base); } static AsmString * _get_string_by_id_callback(Format * format, AsmId id) { return code_get_string_by_id(format->code, id); } static int _set_function_callback(Format * format, int id, char const * name, off_t offset, ssize_t size) { return code_set_function(format->code, id, name, offset, size); } static int _set_string_callback(Format * format, int id, char const * name, off_t offset, ssize_t size) { return code_set_string(format->code, id, name, offset, size); } /* format_exit */ int format_exit(Format * format) { int ret = 0; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif if(format->plugin->exit != NULL) ret = format->plugin->exit(format->plugin); format->helper.format = NULL; format->helper.decode = NULL; format->helper.read = NULL; format->helper.seek = NULL; format->plugin->helper = NULL; format->fp = NULL; format->filename = NULL; return ret; } /* format_function */ int format_function(Format * format, char const * function) { if(format->plugin->function == NULL) return 0; return format->plugin->function(format->plugin, function); } /* format_init */ int format_init(Format * format, char const * filename, FILE * fp) { #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename, (void *)fp); #endif format->filename = filename; format->fp = fp; format->helper.format = format; format->helper.decode = NULL; format->helper.get_filename = _format_get_filename; format->helper.read = _format_read; format->helper.seek = _format_seek; format->helper.write = _format_write; format->plugin->helper = &format->helper; if(format->plugin->init != NULL) return format->plugin->init(format->plugin, format->arch); return 0; } /* format_section */ int format_section(Format * format, char const * section) { if(format->plugin->section == NULL) return 0; return format->plugin->section(format->plugin, section); } /* private */ /* functions */ /* format_get_filename */ static char const * _format_get_filename(Format * format) { return format->filename; } /* format_read */ static ssize_t _format_read(Format * format, void * buf, size_t size) { if(fread(buf, size, 1, format->fp) == 1) return size; if(ferror(format->fp)) return -error_set_code(1, "%s: %s", format->filename, strerror(errno)); if(feof(format->fp)) return -error_set_code(1, "%s: %s", format->filename, "End of file reached"); return -error_set_code(1, "%s: %s", format->filename, "Read error"); } /* format_seek */ static off_t _format_seek(Format * format, off_t offset, int whence) { if(whence == SEEK_SET) { if(fseek(format->fp, offset, whence) == 0) return offset; } else if(whence == SEEK_CUR || whence == SEEK_END) { if(fseek(format->fp, offset, whence) == 0) return ftello(format->fp); } else return -error_set_code(1, "%s: %s", format->filename, "Invalid argument for seeking"); return -error_set_code(1, "%s: %s", format->filename, strerror(errno)); } /* format_write */ static ssize_t _format_write(Format * format, void const * buf, size_t size) { if(fwrite(buf, size, 1, format->fp) == 1) return size; if(ferror(format->fp)) return -error_set_code(1, "%s: %s", format->filename, strerror(errno)); if(feof(format->fp)) return -error_set_code(1, "%s: %s", format->filename, "End of file reached"); return -error_set_code(1, "%s: %s", format->filename, "Write error"); }