/* image.cpp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "image.hh" #include "types.hh" using namespace std; image::~image() { map::iterator mapping_iter; mapping_iter = this->_mappings.begin(); while (mapping_iter != this->_mappings.end()) { image::mapping* mapping = (mapping_iter++)->second; delete mapping; this->_mappings.erase(mapping_iter); } } image::mapping::mapping(da_addr_t addr, uint_t size, FILE* file, uint_t offset, bool read, bool write, bool big_endian) : _addr(addr), _file(file), _read(read), _write(write), _big_endian(big_endian), _data(0), _data_offset(0), _mmap_size(0) { int r; if (file != NULL) { struct stat s; r = fstat(fileno(this->_file), &s); if (r < 0) throw 0; this->_size = max(static_cast(0), min(size, static_cast(s.st_size - this->_data_offset))); uint_t page_size = getpagesize(); uint_t mmap_offset = static_cast(this->_data_offset / page_size) * page_size; this->_mmap_size = this->_size + this->_data_offset - mmap_offset; this->_data = mmap(NULL, this->_mmap_size, PROT_READ, MAP_PRIVATE, fileno(this->_file), mmap_offset); if (this->_data == MAP_FAILED) throw 0; this->_data_offset = offset - mmap_offset; } } image::mapping::~mapping() { if (this->_data != NULL) munmap(this->_data, this->_mmap_size); if (this->_file != NULL) fclose(this->_file); } void image::create_mapping(da_addr_t addr, uint_t size, const char *filename, uint_t offset, bool read, bool write, bool big_endian) { FILE* file = NULL; if (filename != NULL) { file = fopen(filename, "rb"); if (file == NULL) throw 0; if (size == 0) { int r = fseek(file, 0, SEEK_END); if (r < 0) throw 0; size = ftell(file); if (size < 0) throw 0; } } image::mapping* mapping = new image::mapping(addr, size, file, offset, read, write, big_endian); this->_mappings[mapping->addr()] = mapping; } void image::remove_mapping(da_addr_t addr) { map::iterator mapping_iter; mapping_iter = this->_mappings.upper_bound(addr); if (mapping_iter != this->_mappings.begin()) { image::mapping* mapping = (--mapping_iter)->second; if (addr < mapping->addr() + mapping->size()) { delete mapping; this->_mappings.erase(mapping_iter); } } } const image::mapping* image::find_mapping(da_addr_t addr) const { map::const_iterator mapping_iter; mapping_iter = this->_mappings.upper_bound(addr); if (mapping_iter != this->_mappings.begin()) { const image::mapping* mapping = (--mapping_iter)->second; if (addr < mapping->addr() + mapping->size()) return mapping; } return NULL; } image::mapping* image::find_mapping(da_addr_t addr) { map::iterator mapping_iter; mapping_iter = this->_mappings.upper_bound(addr); if (mapping_iter != this->_mappings.begin()) { image::mapping* mapping = (--mapping_iter)->second; if (addr < mapping->addr() + mapping->size()) return mapping; } return NULL; } bool image::is_addr_mapped(da_addr_t addr) const { const image::mapping* mapping = this->find_mapping(addr); return (mapping != NULL && mapping->has_file()); } /* no endianness correction is done */ uint_t image::read(da_addr_t addr, uint8_t dest[], uint_t size) const { const image::mapping* src_mapping = this->find_mapping(addr); if (src_mapping == NULL) return 0; if ((addr + size) > (src_mapping->addr() + src_mapping->size())) return 0; const void* src = &src_mapping->data()[addr]; memcpy(dest, src, size); return size; } void image::add_annotation(da_addr_t addr, const string& text, bool before) { int r; map::iterator annot_pos = this->_annot_map.find(addr); if (annot_pos == this->_annot_map.end()) { image::annotation* annot = new image::annotation(); if (before) { annot->pre_text = text; annot->post_text = ""; } else { annot->pre_text = ""; annot->post_text = text; } this->_annot_map[addr] = annot; } else { image::annotation* annot = annot_pos->second; if (before) annot->pre_text += text; else annot->post_text += text; } } void image::add_annotations_from_file(FILE* f) { int r; char *text = NULL; size_t textlen = 0; ssize_t read; uint_t addr = 0; int reading_addr = 1; int pre = 1; uint_t line = 1; while ((read = getline(&text, &textlen, f)) != -1) { if (read == 0 || !strcmp(text, "\n")) { reading_addr = 1; } else if (reading_addr) { errno = 0; char *endptr; addr = strtol(text, &endptr, 16); if ((errno == ERANGE && (addr == LONG_MAX || addr == LONG_MIN)) || (errno != 0 && addr == 0) || (endptr == text)) { free(text); cerr << "Unable to parse address at line " << dec << line << "." << endl; return; } reading_addr = 0; pre = 1; } else if (!strcmp(text, "--\n")) { pre = 0; } else { string s(text, read); this->add_annotation(addr, s, pre); text = NULL; } line += 1; } if (text) free(text); }