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

htelf.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      htelf.cc
00004  *
00005  *      Copyright (C) 1999-2002 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 "htelf.h"
00024 #include "htelfhd.h"
00025 #include "htelfshs.h"
00026 #include "htelfphs.h"
00027 #include "htelfsym.h"
00028 #include "htelfrel.h"
00029 #include "htelfimg.h"
00030 #include "htendian.h"
00031 #include "htexcept.h"
00032 #include "htiobox.h"
00033 #include "stream.h"
00034 #include "tools.h"
00035 
00036 #include "elfstruc.h"
00037 
00038 #include <stdlib.h>
00039 
00040 static format_viewer_if *htelf_ifs[] = {
00041         &htelfheader_if,
00042         &htelfsectionheaders_if,
00043         &htelfprogramheaders_if,
00044         &htelfimage_if,
00045         0
00046 };
00047 
00048 static ht_view *htelf_init(bounds *b, ht_streamfile *file, ht_format_group *format_group)
00049 {
00050         FILEOFS header_ofs = 0;
00051         ELF_HEADER header;
00052         // read header
00053         if (file->seek(header_ofs) != 0) return NULL;
00054         if (file->read(&header, sizeof header) != sizeof header) return NULL;
00055         // check for magic
00056         if ((header.e_ident[ELF_EI_MAG0]!=ELFMAG0) || (header.e_ident[ELF_EI_MAG1]!=ELFMAG1)
00057         ||  (header.e_ident[ELF_EI_MAG2]!=ELFMAG2) || (header.e_ident[ELF_EI_MAG3]!=ELFMAG3))
00058                 return NULL;
00059         switch (header.e_ident[ELF_EI_DATA]) {
00060                 case ELFDATA2LSB:
00061                 case ELFDATA2MSB:
00062                         break;
00063                 default:
00064                         LOG_EX(LOG_WARN, "File seems to be ELF. But byte-order"
00065                                 " (ELF_EI_DATA) 0x%02x is unsupported. (byte at offset=0x%x)",
00066                                 header.e_ident[ELF_EI_DATA], header_ofs+5);
00067                         return NULL;
00068         }
00069         switch (header.e_ident[ELF_EI_CLASS]) {
00070                 case ELFCLASS32:
00071                 case ELFCLASS64:
00072                         break;
00073                 default:
00074                         LOG_EX(LOG_WARN, "File seems to be ELF. But class-value"
00075                                 " (ELF_EI_CLASS) 0x%02x is unsupported. (byte at offset=0x%x)",
00076                                 header.e_ident[ELF_EI_CLASS], header_ofs+4);
00077                         return NULL;
00078         }
00079 
00080         try {
00081                 ht_elf *g = new ht_elf();
00082                 g->init(b, file, htelf_ifs, format_group, header_ofs);
00083                 return g;
00084         } catch (ht_exception *x) {
00085                 errorbox("error while reading ELF: %s", x->what());
00086                 delete x;
00087                 return NULL;
00088         }
00089 }
00090 
00091 format_viewer_if htelf_if = {
00092         htelf_init,
00093         0
00094 };
00095 
00096 
00097 static int compare_keys_sectionAndIdx(Object *key_a, Object *key_b)
00098 {
00099         sectionAndIdx *a = (sectionAndIdx*)key_a;
00100         sectionAndIdx *b = (sectionAndIdx*)key_b;
00101         if (a->secidx == b->secidx) return a->symidx - b->symidx;
00102         return a->secidx - b->secidx;
00103 }
00104 
00105 bool isValidELFSectionIdx(ht_elf_shared_data *elf_shared, int idx)
00106 {
00107         return (idx > 0) && (idx<(int)elf_shared->sheaders.count);
00108 }
00109 
00110 /*
00111  *      CLASS ht_elf
00112  */
00113 void ht_elf::init(bounds *b, ht_streamfile *f, format_viewer_if **ifs, ht_format_group *format_group, FILEOFS header_ofs)
00114 {
00115         ht_format_group::init(b, VO_SELECTABLE | VO_BROWSABLE | VO_RESIZE, DESC_ELF, f, false, true, 0, format_group);
00116         VIEW_DEBUG_NAME("ht_elf");
00117 
00118         LOG("%s: ELF: found header at %08x", file->get_filename(), header_ofs);
00119 
00120         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)malloc(sizeof(ht_elf_shared_data));
00121 
00122         shared_data = elf_shared;
00123         elf_shared->header_ofs = header_ofs;
00124         elf_shared->shnames = NULL;
00125         elf_shared->symtables = 0;
00126         elf_shared->reloctables = 0;
00127         elf_shared->v_image = NULL;
00128         elf_shared->shrelocs = NULL;
00129         elf_shared->fake_undefined_shidx = 0;
00130         elf_shared->undefined2fakeaddr = NULL;
00131 
00132         /* read header */
00133         if (file->seek(header_ofs)) throw new ht_msg_exception("seek error");
00134         if (file->read(&elf_shared->ident, sizeof elf_shared->ident) != sizeof elf_shared->ident)
00135                 throw new ht_msg_exception("read error");
00136         switch (elf_shared->ident.e_ident[ELF_EI_DATA]) {
00137                 case ELFDATA2LSB:
00138                         elf_shared->byte_order = little_endian;
00139                         break;
00140                 case ELFDATA2MSB:
00141                         elf_shared->byte_order = big_endian;
00142                         break;
00143         }
00144 
00145         switch (elf_shared->ident.e_ident[ELF_EI_CLASS]) {
00146                 case ELFCLASS32: {
00147                         if (file->read(&elf_shared->header32, sizeof elf_shared->header32)
00148                         != sizeof elf_shared->header32)
00149                                 throw new ht_msg_exception("read error");
00150                         create_host_struct(&elf_shared->header32, ELF_HEADER32_struct, elf_shared->byte_order);
00151                         /* read section headers */
00152                         elf_shared->sheaders.count=elf_shared->header32.e_shnum;
00153                         elf_shared->sheaders.sheaders32=(ELF_SECTION_HEADER32*)malloc(elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders32);
00154                         if (file->seek(header_ofs+elf_shared->header32.e_shoff)) throw new ht_msg_exception("seek error");
00155                         if (file->read(elf_shared->sheaders.sheaders32, elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders32)
00156                         != elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders32)
00157                                 throw new ht_msg_exception("read error");
00158                         for (uint i=0; i<elf_shared->sheaders.count; i++) {
00159                                 ELF_SECTION_HEADER32 a = elf_shared->sheaders.sheaders32[i];
00160                                 create_host_struct(elf_shared->sheaders.sheaders32+i, ELF_SECTION_HEADER32_struct, elf_shared->byte_order);
00161                         }
00162         
00163                         /* read program headers */
00164                         elf_shared->pheaders.count=elf_shared->header32.e_phnum;
00165                         elf_shared->pheaders.pheaders32=(ELF_PROGRAM_HEADER32*)malloc(elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders32);
00166                         if (file->seek(header_ofs+elf_shared->header32.e_phoff)) throw new ht_msg_exception("seek error");
00167                         if (file->read(elf_shared->pheaders.pheaders32, elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders32)
00168                         != elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders32)
00169                                 throw new ht_msg_exception("read error");
00170                         for (uint i=0; i<elf_shared->pheaders.count; i++) {
00171                                 create_host_struct(elf_shared->pheaders.pheaders32+i, ELF_PROGRAM_HEADER32_struct, elf_shared->byte_order);
00172                         }
00173                         // if file is relocatable, relocate it
00174                         if (elf_shared->header32.e_type == ELF_ET_REL) {
00175                                 /* create a fake section for undefined symbols */
00176                                 try {
00177                                         fake_undefined_symbols32();
00178                                 } catch (ht_exception *x) {
00179                                         errorbox("error while faking undefined ELF symbols: %s", x->what());
00180                                         delete x;
00181                                 }
00182 
00183                                 /* create streamfile layer for relocations */
00184                                 try {
00185                                         auto_relocate32();
00186                                 } catch (ht_exception *x) {
00187                                         errorbox("error while auto-relocating ELF symbols: %s", x->what());
00188                                         delete x;
00189                                 }
00190                         }
00191                         break;
00192                 }
00193                 case ELFCLASS64: {
00194                         if (file->read(&elf_shared->header64, sizeof elf_shared->header64)
00195                         != sizeof elf_shared->header64)
00196                                 throw new ht_msg_exception("read error");
00197                         create_host_struct(&elf_shared->header64, ELF_HEADER64_struct, elf_shared->byte_order);
00198                         /* read section headers */
00199                         elf_shared->sheaders.count=elf_shared->header64.e_shnum;
00200                         elf_shared->sheaders.sheaders64=(ELF_SECTION_HEADER64*)malloc(elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders64);
00201                         /* FIXME: 64-bit */
00202                         if (file->seek(header_ofs+elf_shared->header64.e_shoff.lo)) throw new ht_msg_exception("seek error");
00203                         if (file->read(elf_shared->sheaders.sheaders64, elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders64)
00204                         != elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders64)
00205                                 throw new ht_msg_exception("read error");
00206                         for (uint i=0; i<elf_shared->sheaders.count; i++) {
00207                                 ELF_SECTION_HEADER64 a = elf_shared->sheaders.sheaders64[i];
00208                                 create_host_struct(elf_shared->sheaders.sheaders64+i, ELF_SECTION_HEADER64_struct, elf_shared->byte_order);
00209                         }
00210 
00211                         /* read program headers */
00212                         elf_shared->pheaders.count=elf_shared->header64.e_phnum;
00213                         elf_shared->pheaders.pheaders64=(ELF_PROGRAM_HEADER64*)malloc(elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders64);
00214                         /* FIXME: 64-bit */
00215                         if (file->seek(header_ofs+elf_shared->header64.e_phoff.lo)) throw new ht_msg_exception("seek error");
00216                         if (file->read(elf_shared->pheaders.pheaders64, elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders64)
00217                         != elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders64)
00218                                 throw new ht_msg_exception("read error");
00219                         for (uint i=0; i<elf_shared->pheaders.count; i++) {
00220                                 create_host_struct(elf_shared->pheaders.pheaders64+i, ELF_PROGRAM_HEADER64_struct, elf_shared->byte_order);
00221                         }
00222                         /* create a fake section for undefined symbols */
00223 //                      fake_undefined_symbols();
00224 
00225                         /* create streamfile layer for relocations */
00226 //                      auto_relocate();
00227                         break;
00228                 }
00229         }
00230         /* init ifs */
00231         ht_format_group::init_ifs(ifs);
00232         while (init_if(&htelfsymboltable_if)) elf_shared->symtables++;
00233         while (init_if(&htelfreloctable_if)) elf_shared->reloctables++;
00234 }
00235 
00236 void ht_elf::done()
00237 {
00238         ht_format_group::done();
00239         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data;
00240         if (elf_shared->shnames) {
00241                 for (uint i=0; i < elf_shared->sheaders.count; i++)
00242                         free(elf_shared->shnames[i]);
00243                 free(elf_shared->shnames);
00244         }               
00245         if (elf_shared->shrelocs) free(elf_shared->shrelocs);
00246         switch (elf_shared->ident.e_ident[ELF_EI_CLASS]) {
00247                 case ELFCLASS32:
00248                         if (elf_shared->sheaders.sheaders32) free(elf_shared->sheaders.sheaders32);
00249                         if (elf_shared->pheaders.pheaders32) free(elf_shared->pheaders.pheaders32);
00250                         break;
00251                 case ELFCLASS64:
00252                         if (elf_shared->sheaders.sheaders64) free(elf_shared->sheaders.sheaders64);
00253                         if (elf_shared->pheaders.pheaders64) free(elf_shared->pheaders.pheaders64);
00254                         break;
00255         }
00256         if (elf_shared->undefined2fakeaddr) {
00257                 elf_shared->undefined2fakeaddr->destroy();
00258                 delete elf_shared->undefined2fakeaddr;
00259         }
00260         free(elf_shared);
00261 }
00262 
00263 uint ht_elf::find_reloc_section_for(uint si)
00264 {
00265         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data;
00266 
00267         ELF_SECTION_HEADER32 *s=elf_shared->sheaders.sheaders32;
00268         for (uint i=0; i<elf_shared->sheaders.count; i++) {
00269                 if (((s->sh_type==ELF_SHT_REL) || (s->sh_type==ELF_SHT_RELA)) &&
00270                 (s->sh_info==si)) {
00271                         return i;
00272                 }
00273                 s++;
00274         }
00275         return 0;
00276 }
00277 
00278 #define INVENT_BASE     0x100000
00279 #define INVENT_STEPPING 0x100000
00280 #define INVENT_LIMIT    0xffffffff
00281 
00282 static elf32_addr elf32_invent_address(uint si, ELF_SECTION_HEADER32 *s, uint scount, elf32_addr base = INVENT_BASE)
00283 {
00284         elf32_addr a = base;
00285         assert(s[si].sh_addr == 0);
00286         while (a<INVENT_LIMIT-s[si].sh_size) {
00287                 bool ok = true;
00288                 for (uint i=0; i<scount; i++) {
00289                         if ((a >= s[i].sh_addr)
00290                         && (a < s[i].sh_addr+s[i].sh_size)) {
00291                                 ok = false;
00292                                 break;
00293                         }
00294                 }
00295                 if (ok) return a;
00296                 a += INVENT_STEPPING;
00297         }
00298         return 0;
00299 }
00300 
00301 void ht_elf::relocate_section(ht_reloc_file *f, uint si, uint rsi, elf32_addr a)
00302 {
00303         // relocate section si (using section rsi) to address a
00304         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data;
00305         ELF_SECTION_HEADER32 *s=elf_shared->sheaders.sheaders32;
00306 
00307         FILEOFS relh = s[rsi].sh_offset;
00308 
00309         uint symtabidx = s[rsi].sh_link;
00310         if (!isValidELFSectionIdx(elf_shared, symtabidx)) throw new ht_msg_exception("invalid symbol table index %d", symtabidx);
00311         FILEOFS symh = elf_shared->sheaders.sheaders32[symtabidx].sh_offset;
00312 
00313         if (s[rsi].sh_type != ELF_SHT_REL) throw new ht_msg_exception(
00314                 "invalid section type for section %d (expeecting %d)",
00315                 rsi, ELF_SHT_REL);
00316 
00317         uint relnum = s[rsi].sh_size / sizeof (ELF_REL32);
00318         for (uint i=0; i<relnum; i++) {
00319                 // read ELF_REL32
00320                 ELF_REL32 r;
00321                 if (file->seek(relh+i*sizeof r)) throw new ht_msg_exception("seek error");
00322                 if (file->read(&r, sizeof r) != sizeof r)
00323                         throw new ht_msg_exception("read error reading relocations for section %d [REL32]", si);
00324                 create_host_struct(&r, ELF_REL32_struct, elf_shared->byte_order);
00325 
00326                 // read ELF_SYMBOL32
00327                 uint symbolidx = ELF32_R_SYM(r.r_info);
00328                 ELF_SYMBOL32 sym;
00329                 if (file->seek(symh+symbolidx*sizeof (ELF_SYMBOL32))) throw new ht_msg_exception("seek error");
00330                 if (file->read(&sym, sizeof sym) != sizeof sym)
00331                         throw new ht_msg_exception("read error reading relocations for section %d [SYM-LOOKUP]", si);
00332                 create_host_struct(&sym, ELF_SYMBOL32_struct, elf_shared->byte_order);
00333 
00334                 // calc reloc vals
00335                 uint32 A = 0;
00336                 uint32 P = r.r_offset+s[si].sh_addr;
00337                 uint32 S;
00338                 if ((sym.st_shndx > 0) && (sym.st_shndx < elf_shared->sheaders.count)) {
00339                         S = sym.st_value + elf_shared->shrelocs[sym.st_shndx].relocAddr;
00340                 } else if (elf_shared->fake_undefined_shidx >= 0) {
00341                         sectionAndIdx s(symtabidx, symbolidx);
00342                         ht_data_uint32 *addr = (ht_data_uint32 *)elf_shared->undefined2fakeaddr->get(&s);
00343                         if (addr) {
00344                                 S = addr->value;
00345                         } else continue;
00346                 } else {
00347                         // skip this one
00348                         // FIXME: nyi
00349                         continue;
00350                 }
00351                 Object *z = new ht_elf32_reloc_entry(
00352                         ELF32_R_TYPE(r.r_info), A, P, S);
00353                 f->insert_reloc(r.r_offset+s[si].sh_offset, z);
00354         }
00355 }
00356 
00357 #define FAKE_SECTION_BASEADDR   0x4acc0000
00358 /* "resolve" undefined references by creating fake section and fake addresses */
00359 void ht_elf::fake_undefined_symbols32()
00360 {
00361         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data;
00362         // create a fake section
00363         elf_shared->fake_undefined_shidx = elf_shared->sheaders.count;
00364         elf_shared->sheaders.count++;
00365         elf_shared->sheaders.sheaders32 = (ELF_SECTION_HEADER32*)
00366                 realloc(elf_shared->sheaders.sheaders32, sizeof (ELF_SECTION_HEADER32)* elf_shared->sheaders.count);
00367 
00368         ELF_SECTION_HEADER32 *s = elf_shared->sheaders.sheaders32;
00369         s[elf_shared->fake_undefined_shidx].sh_name = 0;
00370         s[elf_shared->fake_undefined_shidx].sh_type = ELF_SHT_NOBITS;
00371         s[elf_shared->fake_undefined_shidx].sh_flags = ELF_SHF_WRITE | ELF_SHF_ALLOC;
00372         s[elf_shared->fake_undefined_shidx].sh_addr = 0;
00373         s[elf_shared->fake_undefined_shidx].sh_offset = 0;
00374         s[elf_shared->fake_undefined_shidx].sh_size = 0;        // filled in below
00375         s[elf_shared->fake_undefined_shidx].sh_link = 0;
00376         s[elf_shared->fake_undefined_shidx].sh_info = 0;
00377         s[elf_shared->fake_undefined_shidx].sh_addralign = 0;
00378         s[elf_shared->fake_undefined_shidx].sh_entsize = 0;
00379         elf32_addr a = elf32_invent_address(elf_shared->fake_undefined_shidx,
00380                 s, elf_shared->sheaders.count, FAKE_SECTION_BASEADDR);
00381         s[elf_shared->fake_undefined_shidx].sh_addr = a;
00382         LOG("fake section %d", elf_shared->fake_undefined_shidx);
00383         // allocate fake addresses
00384         elf_shared->undefined2fakeaddr = new ht_stree();
00385         ((ht_stree*)elf_shared->undefined2fakeaddr)->init(compare_keys_sectionAndIdx);
00386         uint32 nextFakeAddr = FAKE_SECTION_BASEADDR;
00387         for (uint secidx = 0; secidx < elf_shared->sheaders.count; secidx++) {
00388                 if (elf_shared->sheaders.sheaders32[secidx].sh_type == ELF_SHT_SYMTAB) {
00389                         FILEOFS symh = elf_shared->sheaders.sheaders32[secidx].sh_offset;
00390                         uint symnum = elf_shared->sheaders.sheaders32[secidx].sh_size / sizeof (ELF_SYMBOL32);
00391                         for (uint symidx = 1; symidx < symnum; symidx++) {
00392                                 ELF_SYMBOL32 sym;
00393                                 if (file->seek(symh+symidx*sizeof (ELF_SYMBOL32))) throw new ht_msg_exception("seek error");
00394                                 if (file->read(&sym, sizeof sym))
00395                                         throw new ht_msg_exception("read error [looking up symbol]");
00396                                 create_host_struct(&sym, ELF_SYMBOL32_struct, elf_shared->byte_order);
00397                                 if (sym.st_shndx == ELF_SHN_UNDEF) {
00398                                         elf_shared->undefined2fakeaddr->insert(
00399                                                 new sectionAndIdx(secidx, symidx),
00400                                                 new ht_data_uint32(nextFakeAddr));
00401                                         nextFakeAddr += 4;
00402                                 }
00403                         }
00404                 }
00405         }
00406         elf_shared->fake_undefined_size = nextFakeAddr-FAKE_SECTION_BASEADDR;
00407         s[elf_shared->fake_undefined_shidx].sh_size = elf_shared->fake_undefined_size;
00408 }
00409 
00410 void ht_elf::auto_relocate32()
00411 {
00412         ht_elf32_reloc_file *rf = new ht_elf32_reloc_file();
00413         rf->init(file, false, (ht_elf_shared_data*)shared_data);
00414 
00415         bool reloc_needed = false;
00416 
00417         ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data;
00418 
00419         ELF_SECTION_HEADER32 *s=elf_shared->sheaders.sheaders32;
00420 
00421         elf_shared->shrelocs = (ht_elf_reloc_section32*)malloc(elf_shared->sheaders.count * sizeof (ht_elf_reloc_section32));
00422 
00423         /* relocate sections */
00424         for (uint i=0; i<elf_shared->sheaders.count; i++) {
00425                 elf_shared->shrelocs[i].relocAddr = 0;
00426                 if ((s[i].sh_type == ELF_SHT_PROGBITS) && (s[i].sh_addr == 0)) {
00427                         uint j = find_reloc_section_for(i);
00428                         if (j) {
00429                                 elf32_addr a = elf32_invent_address(i, s, elf_shared->sheaders.count);
00430                                 if (a) {
00431                                         reloc_needed = true;
00432                                         // update section header entry
00433                                         s[i].sh_addr = a;
00434                                         elf_shared->shrelocs[i].relocAddr = a;
00435                                         elf_shared->shrelocs[i].relocShIdx = j;
00436                                 }
00437                         }
00438                 }
00439         }
00440 
00441         /* apply relocations to section descriptors */
00442         for (uint i=0; i<elf_shared->sheaders.count; i++) {
00443                 if (elf_shared->shrelocs[i].relocAddr) {
00444                         //LOG("section %d to %08x", i, elf_shared->shrelocs[i].relocAddr);
00445                         try {
00446                                 relocate_section(rf, i, elf_shared->shrelocs[i].relocShIdx, elf_shared->shrelocs[i].relocAddr);
00447                         } catch (ht_exception *x) {
00448                                 LOG("error while relocating section %d: %s", i, x->what());
00449                                 delete x;
00450                         }
00451                 }
00452         }
00453 
00454         if (reloc_needed) {
00455                 rf->finalize();
00456                 own_file = true;
00457                 file = rf;
00458                 LOG("%s: ELF: relocation layer enabled (invented relocation addresses)", file->get_filename());
00459         } else {
00460                 free(elf_shared->shrelocs);
00461                 elf_shared->shrelocs = NULL;
00462                 rf->done();
00463                 delete rf;
00464         }
00465 }
00466 
00467 bool ht_elf::loc_enum_next(ht_format_loc *loc)
00468 {
00469         ht_elf_shared_data *sh = (ht_elf_shared_data*)shared_data;
00470         if (loc_enum) {
00471                 loc->name = "elf";
00472                 loc->start = sh->header_ofs;
00473                 loc->length = file->get_size()-loc->start;      /* FIXME: ENOTOK */
00474 
00475                 loc_enum = false;
00476                 return true;
00477         }
00478         return false;
00479 }
00480 
00481 void ht_elf::loc_enum_start()
00482 {
00483         loc_enum = true;
00484 }
00485 
00486 /*
00487  *      address conversion routines
00488  */
00489 bool elf_phys_and_mem_section(elf_section_header *sh, uint elfclass)
00490 {
00491         switch (elfclass) {
00492                 case ELFCLASS32: {
00493                         ELF_SECTION_HEADER32 *s = &sh->sheaders32;
00494                         return (s->sh_type == ELF_SHT_PROGBITS) && s->sh_addr;
00495                 }
00496                 case ELFCLASS64: {
00497                         ELF_SECTION_HEADER64 *s = &sh->sheaders64;
00498                         return ((s->sh_type==ELF_SHT_PROGBITS) && ((s->sh_addr.lo!=0) || (s->sh_addr.hi!=0)));
00499                 }
00500         }
00501         return false;
00502 }
00503 
00504 bool elf_valid_section(elf_section_header *sh, uint elfclass)
00505 {
00506         switch (elfclass) {
00507                 case ELFCLASS32: {
00508                         ELF_SECTION_HEADER32 *s = &sh->sheaders32;
00509                         return (((s->sh_type==ELF_SHT_PROGBITS) || (s->sh_type==ELF_SHT_NOBITS)) && (s->sh_addr!=0));
00510                 }
00511                 case ELFCLASS64: {
00512                         ELF_SECTION_HEADER64 *s = &sh->sheaders64;
00513                         return (((s->sh_type==ELF_SHT_PROGBITS) || (s->sh_type==ELF_SHT_NOBITS)) && ((s->sh_addr.lo!=0) || (s->sh_addr.hi!=0)));
00514                 }
00515         }
00516         return false;
00517 }
00518 
00519 bool elf_addr_to_ofs(elf_section_headers *section_headers, uint elfclass, ELFAddress addr, dword *ofs)
00520 {
00521         switch (elfclass) {
00522                 case ELFCLASS32: {
00523                         ELF_SECTION_HEADER32 *s = section_headers->sheaders32;
00524                         for (uint i=0; i < section_headers->count; i++) {
00525                                 if ((elf_phys_and_mem_section((elf_section_header*)s, elfclass)) && (addr.a32 >= s->sh_addr) && (addr.a32 < s->sh_addr+s->sh_size)) {
00526                                         *ofs = addr.a32 - s->sh_addr + s->sh_offset;
00527                                         return true;
00528                                 }
00529                                 s++;
00530                         }
00531                         break;
00532                 }
00533                 case ELFCLASS64: {
00534                         ELF_SECTION_HEADER64 *s = section_headers->sheaders64;
00535                         for (uint i=0; i < section_headers->count; i++) {
00536                                 if ((elf_phys_and_mem_section((elf_section_header*)s, elfclass)) && (qword_cmp(addr.a64, s->sh_addr) >= 0) && (addr.a64 < s->sh_addr + s->sh_size)) {
00537                                         qword qofs = addr.a64 - s->sh_addr + s->sh_offset;
00538                                         *ofs = qofs.lo;
00539                                         return true;
00540                                 }
00541                                 s++;
00542                         }
00543                         break;
00544                 }
00545         }
00546         return false;
00547 }
00548 
00549 bool elf_addr_to_section(elf_section_headers *section_headers, uint elfclass, ELFAddress addr, int *section)
00550 {
00551         switch (elfclass) {
00552                 case ELFCLASS32: {
00553                         ELF_SECTION_HEADER32 *s = section_headers->sheaders32;
00554                         for (uint i = 0; i < section_headers->count; i++) {
00555                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (addr.a32 >= s->sh_addr) && (addr.a32 < s->sh_addr + s->sh_size)) {
00556                                         *section = i;
00557                                         return true;
00558                                 }
00559                                 s++;
00560                         }
00561                         break;
00562                 }
00563                 case ELFCLASS64: {
00564                         ELF_SECTION_HEADER64 *s = section_headers->sheaders64;
00565                         for (uint i = 0; i < section_headers->count; i++) {
00566                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (qword_cmp(addr.a64, s->sh_addr) >= 0) && (addr.a64 < s->sh_addr + s->sh_size)) {
00567                                         *section = i;
00568                                         return true;
00569                                 }
00570                                 s++;
00571                         }
00572                         break;
00573                 }
00574         }
00575         return false;
00576 }
00577 
00578 bool elf_addr_is_valid(elf_section_headers *section_headers, uint elfclass, ELFAddress addr)
00579 {
00580         switch (elfclass) {
00581                 case ELFCLASS32: {
00582                         ELF_SECTION_HEADER32 *s = section_headers->sheaders32;
00583                         for (uint i=0; i<section_headers->count; i++) {
00584                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (addr.a32 >= s->sh_addr) && (addr.a32 < s->sh_addr + s->sh_size)) {
00585                                         return true;
00586                                 }
00587                                 s++;
00588                         }
00589                         break;
00590                 }
00591                 case ELFCLASS64: {
00592                         ELF_SECTION_HEADER64 *s = section_headers->sheaders64;
00593                         for (uint i=0; i<section_headers->count; i++) {
00594                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (qword_cmp(addr.a64, s->sh_addr) >= 0) && (addr.a64 < s->sh_addr + s->sh_size)) {
00595                                         return true;
00596                                 }
00597                                 s++;
00598                         }
00599                         break;
00600                 }
00601         }
00602         return false;
00603 }
00604 
00605 bool elf_addr_is_physical(elf_section_headers *section_headers, uint elfclass, ELFAddress addr)
00606 {
00607         return false;
00608 }
00609 
00610 
00611 /*
00612  *      offset conversion routines
00613  */
00614 
00615 bool elf_ofs_to_addr(elf_section_headers *section_headers, uint elfclass, dword ofs, ELFAddress *addr)
00616 {
00617         switch (elfclass) {
00618                 case ELFCLASS32: {
00619                         ELF_SECTION_HEADER32 *s = section_headers->sheaders32;
00620                         for (uint i = 0; i < section_headers->count; i++) {
00621                                 if ((elf_phys_and_mem_section((elf_section_header*)s, elfclass)) && (ofs>=s->sh_offset) && (ofs<s->sh_offset+s->sh_size)) {
00622                                         addr->a32 = ofs - s->sh_offset + s->sh_addr;
00623                                         return true;
00624                                 }
00625                                 s++;
00626                         }
00627                         break;
00628                 }
00629                 case ELFCLASS64: {
00630                         ELF_SECTION_HEADER64 *s = section_headers->sheaders64;
00631                         qword qofs = to_qword(ofs);
00632                         for (uint i = 0; i < section_headers->count; i++) {
00633                                 if ((elf_phys_and_mem_section((elf_section_header*)s, elfclass)) && (qword_cmp(qofs, s->sh_offset)>=0) && (qofs < s->sh_offset + s->sh_size)) {
00634                                         addr->a64 = qofs - s->sh_offset + s->sh_addr;
00635                                         return true;
00636                                 }
00637                                 s++;
00638                         }
00639                         break;
00640                 }
00641         }
00642         return false;
00643 }
00644 
00645 bool elf_ofs_to_section(elf_section_headers *section_headers, uint elfclass, dword ofs, int *section)
00646 {
00647         switch (elfclass) {
00648                 case ELFCLASS32: {
00649                         ELF_SECTION_HEADER32 *s=section_headers->sheaders32;
00650                         for (uint i=0; i<section_headers->count; i++) {
00651                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (ofs >= s->sh_offset) && (ofs<s->sh_offset+s->sh_size)) {
00652                                         *section = i;
00653                                         return true;
00654                                 }
00655                                 s++;
00656                         }
00657                         break;
00658                 }
00659                 case ELFCLASS64: {
00660                         ELF_SECTION_HEADER64 *s = section_headers->sheaders64;
00661                         qword qofs;
00662                         qofs.hi = 0; qofs.lo = ofs;
00663                         for (uint i=0; i < section_headers->count; i++) {
00664                                 if ((elf_valid_section((elf_section_header*)s, elfclass)) && (qword_cmp(qofs, s->sh_offset)>=0) && (qofs < s->sh_offset + s->sh_size)) {
00665                                         *section = i;
00666                                         return true;
00667                                 }
00668                                 s++;
00669                         }
00670                         break;
00671                 }
00672         }
00673         return false;
00674 }
00675 
00676 bool elf_ofs_to_addr_and_section(elf_section_headers *section_headers, uint elfclass, dword ofs, ELFAddress *addr, int *section)
00677 {
00678         return false;
00679 }
00680 
00681 /*
00682  *      ht_elf32_reloc_entry
00683  */
00684 //ht_elf32_reloc_entry::ht_elf32_reloc_entry(uint symtabidx, elf32_addr addr, uint t, uint symbolidx, elf32_addr addend, ht_elf_shared_data *data, ht_streamfile *file)
00685 ht_elf32_reloc_entry::ht_elf32_reloc_entry(uint t, uint32 A, uint32 P, uint32 S)
00686 {
00687         type = t;
00688         switch (type) {
00689                 case ELF_R_386_32:
00690                         relocs.r_32 = S+A;
00691                         break;
00692                 case ELF_R_386_PC32:
00693                         relocs.r_pc32 = S+A-P;
00694                         break;
00695         }
00696 }
00697 
00698 /*
00699  *      ht_elf32_reloc_file
00700  */
00701 
00702 void    ht_elf32_reloc_file::init(ht_streamfile *s, bool os, ht_elf_shared_data *d)
00703 {
00704         ht_reloc_file::init(s, os);
00705         data = d;
00706 }
00707 
00708 void    ht_elf32_reloc_file::reloc_apply(Object *reloc, byte *buf)
00709 {
00710         ht_elf32_reloc_entry *e=(ht_elf32_reloc_entry*)reloc;
00711 
00712         switch (e->type) {
00713                 case ELF_R_386_32: {
00714                         uint32 v = create_host_int(buf, 4, data->byte_order);
00715                         v += e->relocs.r_32;
00716                         create_foreign_int(buf, v, 4, data->byte_order);
00717                         break;
00718                 }
00719                 case ELF_R_386_PC32: {
00720                         uint32 v = create_host_int(buf, 4, data->byte_order);
00721                         v += e->relocs.r_pc32;
00722                         create_foreign_int(buf, v, 4, data->byte_order);
00723                         break;
00724                 }
00725         }
00726 }
00727 
00728 bool    ht_elf32_reloc_file::reloc_unapply(Object *reloc, byte *data)
00729 {
00730         return false;
00731 //      ht_elf32_reloc_entry *e=(ht_elf32_reloc_entry*)reloc;
00732 }

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