Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htmacho.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      htmacho.cc
00004  *
00005  *      Copyright (C) 2003 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "elfstruc.h"
00022 #include "log.h"
00023 #include "htmacho.h"
00024 #include "htmachohd.h"
00025 #include "htmachoimg.h"
00026 #include "htendian.h"
00027 #include "stream.h"
00028 #include "tools.h"
00029 
00030 #include "machostruc.h"
00031 
00032 #include <stdlib.h>
00033 
00034 static format_viewer_if *htmacho_ifs[] = {
00035         &htmachoheader_if,
00036         &htmachoimage_if,
00037         0
00038 };
00039 
00040 static ht_view *htmacho_init(bounds *b, ht_streamfile *file, ht_format_group *format_group)
00041 {
00042         byte magic[4];
00043         file->seek(0);
00044         file->read(&magic, sizeof magic);
00045         if (memcmp(magic, "\xfe\xed\xfa\xce", 4) == 0) {
00046                 ht_macho *g = new ht_macho();
00047                 g->init(b, file, htmacho_ifs, format_group, 0, big_endian);
00048                 return g;
00049         } else if (memcmp(magic, "\xce\xfa\xed\xfe", 4) == 0) {
00050                 ht_macho *g = new ht_macho();
00051                 g->init(b, file, htmacho_ifs, format_group, 0, little_endian);
00052                 return g;
00053         }
00054         return NULL;
00055 }
00056 
00057 format_viewer_if htmacho_if = {
00058         htmacho_init,
00059         0
00060 };
00061 
00062 /*
00063  *      CLASS ht_macho
00064  */
00065 void ht_macho::init(bounds *b, ht_streamfile *f, format_viewer_if **ifs, ht_format_group *format_group, FILEOFS header_ofs, endianess image_endianess)
00066 {
00067         ht_format_group::init(b, VO_SELECTABLE | VO_BROWSABLE | VO_RESIZE, DESC_MACHO, f, false, true, 0, format_group);
00068         VIEW_DEBUG_NAME("ht_macho");
00069 
00070         LOG("%s: Mach-O: found header at %08x", file->get_filename(), header_ofs);
00071         
00072         ht_macho_shared_data *macho_shared=(ht_macho_shared_data *)malloc(sizeof(ht_macho_shared_data));
00073 
00074         shared_data = macho_shared;
00075         macho_shared->image_endianess = image_endianess;
00076         macho_shared->header_ofs = header_ofs;
00077         macho_shared->cmds.count = 0;
00078         macho_shared->cmds.cmds = NULL;
00079 /*      macho_shared->shnames=NULL;
00080         macho_shared->symtables=0;
00081         macho_shared->reloctables=0;
00082         macho_shared->v_image=NULL;
00083         macho_shared->htrelocs=NULL;
00084         macho_shared->fake_undefined_section=0;*/
00085 
00086         FILEOFS ofs;
00087         /* read header */
00088         file->seek(header_ofs);
00089         file->read(&macho_shared->header, sizeof macho_shared->header);
00090         create_host_struct(&macho_shared->header, MACHO_HEADER_struct, image_endianess);
00091 
00092         /* read commands */
00093         UINT nsections = 0;
00094         ofs = header_ofs+sizeof macho_shared->header;
00095         macho_shared->cmds.count = macho_shared->header.ncmds;
00096         macho_shared->cmds.cmds = (MACHO_COMMAND_U**)malloc(sizeof (MACHO_COMMAND_U*) * macho_shared->header.ncmds);
00097         for (UINT i=0; i<macho_shared->cmds.count; i++) {
00098                 MACHO_COMMAND cmd;
00099                 file->seek(ofs);
00100                 file->read(&cmd, sizeof cmd);
00101                 create_host_struct(&cmd, MACHO_COMMAND_struct, image_endianess);
00102                 if (cmd.cmdsize>1024) break;
00103                 macho_shared->cmds.cmds[i] = (MACHO_COMMAND_U*)malloc(cmd.cmdsize);
00104                 file->seek(ofs);
00105                 if (file->read(macho_shared->cmds.cmds[i], cmd.cmdsize) != cmd.cmdsize) {
00106                         free(macho_shared->cmds.cmds[i]);
00107                         break;
00108                 }
00109                 switch (cmd.cmd) {
00110                         case LC_SEGMENT:
00111                                 create_host_struct(macho_shared->cmds.cmds[i], MACHO_SEGMENT_COMMAND_struct, image_endianess);
00112                                 // already count sections (needed for reading sections, see below)
00113                                 nsections += macho_shared->cmds.cmds[i]->segment.nsects;
00114                                 break;
00115                         case LC_SYMTAB:
00116                                 create_host_struct(macho_shared->cmds.cmds[i], MACHO_SYMTAB_COMMAND_struct, image_endianess);
00117                                 break;
00118                         case LC_THREAD:
00119                         case LC_UNIXTHREAD: {
00120                                 MACHO_THREAD_COMMAND *c = (MACHO_THREAD_COMMAND*)macho_shared->cmds.cmds[i];
00121                                 create_host_struct(macho_shared->cmds.cmds[i], MACHO_THREAD_COMMAND_struct, image_endianess);
00122                                 switch (macho_shared->header.cputype) {
00123                                 case MACHO_CPU_TYPE_I386:
00124                                         switch (c->flavor) {
00125                                         case -1:
00126                                                 create_host_struct(&c->state, MACHO_I386_THREAD_STATE_struct, image_endianess);
00127                                                 break;
00128                                         }
00129                                         break;
00130                                 case MACHO_CPU_TYPE_POWERPC:
00131                                         switch (c->flavor) {
00132                                         case FLAVOR_PPC_THREAD_STATE:
00133                                                 create_host_struct(&c->state, MACHO_PPC_THREAD_STATE_struct, image_endianess);
00134                                                 break;
00135                                         }
00136                                         break;
00137                                 }
00138                         }
00139                         default:
00140                                 create_host_struct(macho_shared->cmds.cmds[i], MACHO_COMMAND_struct, image_endianess);
00141                 }
00142                 ofs += cmd.cmdsize;
00143         }
00144 
00145         /* read sections */
00146         ofs = header_ofs+sizeof macho_shared->header;
00147         macho_shared->sections.count = nsections;
00148         macho_shared->sections.sections = (MACHO_SECTION*)malloc(sizeof (MACHO_SECTION) * macho_shared->sections.count);
00149         UINT sec = 0;
00150         for (UINT i=0; i<macho_shared->cmds.count; i++) {
00151                 if (macho_shared->cmds.cmds[i]->cmd.cmd == LC_SEGMENT) {
00152                         FILEOFS sofs = ofs+sizeof (MACHO_SEGMENT_COMMAND);
00153                         file->seek(sofs);
00154                         for (UINT j=0; j<macho_shared->cmds.cmds[i]->segment.nsects; j++) {
00155                                 file->read(&macho_shared->sections.sections[sec], sizeof (MACHO_SECTION));
00156                                 create_host_struct(&macho_shared->sections.sections[sec], MACHO_SECTION_struct, image_endianess);
00157                                 sec++;
00158                         }
00159                 }
00160                 ofs += macho_shared->cmds.cmds[i]->cmd.cmdsize;
00161         }
00162 
00163         /* init ifs */
00164         ht_format_group::init_ifs(ifs);
00165 }
00166 
00167 void ht_macho::done()
00168 {
00169         ht_format_group::done();
00170 }
00171 
00172 /*
00173  *      address conversion routines
00174  */
00175 
00176 bool macho_phys_and_mem_section(MACHO_SECTION *s, UINT machoclass)
00177 {
00178         return true;
00179 }
00180 
00181 bool macho_valid_section(MACHO_SECTION *s, UINT machoclass)
00182 {
00183         return true;
00184 }
00185 
00186 bool macho_addr_to_ofs(macho_sections *sections, UINT machoclass, MACHOAddress addr, dword *ofs)
00187 {
00188         MACHO_SECTION *s = sections->sections;
00189         for (UINT i=0; i < sections->count; i++) {
00190                 if (macho_phys_and_mem_section(s, machoclass) &&
00191                 (addr >= s->vmaddr) && (addr < s->vmaddr+s->vmsize)) {
00192                         *ofs = addr - s->vmaddr + s->fileoff;
00193                         return true;
00194                 }
00195                 s++;
00196         }
00197         return false;
00198 }
00199 
00200 bool macho_addr_to_section(macho_sections *sections, UINT machoclass, MACHOAddress addr, int *section)
00201 {
00202         MACHO_SECTION *s = sections->sections;
00203         for (UINT i=0; i < sections->count; i++) {
00204                 if ((macho_valid_section(s, machoclass)) && (addr >= s->vmaddr) && (addr < s->vmaddr + s->vmsize)) {
00205                         *section = i;
00206                         return true;
00207                 }
00208                 s++;
00209         }
00210         return false;
00211 }
00212 
00213 bool macho_addr_is_valid(macho_sections *sections, UINT machoclass, MACHOAddress addr)
00214 {
00215         MACHO_SECTION *s = sections->sections;
00216         for (UINT i=0; i < sections->count; i++) {
00217                 if ((macho_valid_section(s, machoclass)) && (addr >= s->vmaddr) && (addr < s->vmaddr + s->vmsize)) {
00218                         return true;
00219                 }
00220                 s++;
00221         }
00222         return false;
00223 }
00224 
00225 /*bool macho_addr_is_physical(macho_sections *sections, UINT machoclass, ELFAddress addr)
00226 {
00227         return false;
00228 }*/
00229 
00230 /*
00231  *      offset conversion routines
00232  */
00233 
00234 bool macho_ofs_to_addr(macho_sections *sections, UINT machoclass, dword ofs, MACHOAddress *addr)
00235 {
00236         MACHO_SECTION *s = sections->sections;
00237         for (UINT i=0; i < sections->count; i++) {
00238                 if ((macho_phys_and_mem_section(s, machoclass)) && (ofs>=s->fileoff) && (ofs<s->fileoff+s->vmsize)) {
00239                         *addr = ofs - s->fileoff + s->vmaddr;
00240                         return true;
00241                 }
00242                 s++;
00243         }
00244         return false;
00245 }
00246 
00247 bool macho_ofs_to_section(macho_sections *sections, UINT machoclass, dword ofs, dword *section)
00248 {
00249         MACHO_SECTION *s = sections->sections;
00250         for (UINT i=0; i < sections->count; i++) {
00251                 if ((macho_valid_section(s, machoclass)) && (ofs >= s->fileoff) && (ofs<s->fileoff+s->vmsize)) {
00252                         *section = i;
00253                         return true;
00254                 }
00255                 s++;
00256         }
00257         return false;
00258 }
00259 
00260 /*bool macho_ofs_to_addr_and_section(macho_sections *sections, UINT machoclass, dword ofs, ELFAddress *addr, int *section)
00261 {
00262         return false;
00263 }*/

Generated on Fri May 7 21:15:35 2004 by doxygen 1.3.5