?? htelf.cc
字號:
/* * HT Editor * htelf.cc * * Copyright (C) 1999-2002 Stefan Weyergraf * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "elfstruc.h"#include "log.h"#include "htelf.h"#include "htelfhd.h"#include "htelfshs.h"#include "htelfphs.h"#include "htelfsym.h"#include "htelfrel.h"#include "htelfimg.h"#include "endianess.h"#include "except.h"#include "htiobox.h"#include "stream.h"#include "tools.h"#include "elfstruc.h"#include <stdlib.h>static format_viewer_if *htelf_ifs[] = { &htelfheader_if, &htelfsectionheaders_if, &htelfprogramheaders_if, &htelfimage_if, 0};static ht_view *htelf_init(Bounds *b, File *file, ht_format_group *format_group){ FileOfs header_ofs = 0; ELF_HEADER header; // read header try { file->seek(header_ofs); file->readx(&header, sizeof header); } catch (...) { return NULL; } // check for magic if ((header.e_ident[ELF_EI_MAG0]!=ELFMAG0) || (header.e_ident[ELF_EI_MAG1]!=ELFMAG1) || (header.e_ident[ELF_EI_MAG2]!=ELFMAG2) || (header.e_ident[ELF_EI_MAG3]!=ELFMAG3)) return NULL; switch (header.e_ident[ELF_EI_DATA]) { case ELFDATA2LSB: case ELFDATA2MSB: break; default: LOG_EX(LOG_WARN, "File seems to be ELF. But byte-order" " (ELF_EI_DATA) 0x%02x is unsupported. (byte at offset=0x%x)", header.e_ident[ELF_EI_DATA], header_ofs+5); return NULL; } switch (header.e_ident[ELF_EI_CLASS]) { case ELFCLASS32: case ELFCLASS64: break; default: LOG_EX(LOG_WARN, "File seems to be ELF. But class-value" " (ELF_EI_CLASS) 0x%02x is unsupported. (byte at offset=0x%x)", header.e_ident[ELF_EI_CLASS], header_ofs+4); return NULL; } try { ht_elf *g = new ht_elf(); g->init(b, file, htelf_ifs, format_group, header_ofs); return g; } catch (const Exception &x) { errorbox("error while reading ELF: %y", &x); return NULL; }}format_viewer_if htelf_if = { htelf_init, 0};/**/int FakeAddr::compareTo(const Object *keyb) const{ FakeAddr *b = (FakeAddr*)keyb; if (secidx == b->secidx) return symidx - b->symidx; return secidx - b->secidx;}bool isValidELFSectionIdx(ht_elf_shared_data *elf_shared, int idx){ return idx > 0 && (uint)idx < elf_shared->sheaders.count;}/* * CLASS ht_elf */void ht_elf::init(Bounds *b, File *f, format_viewer_if **ifs, ht_format_group *format_group, FileOfs header_ofs){ ht_format_group::init(b, VO_SELECTABLE | VO_BROWSABLE | VO_RESIZE, DESC_ELF, f, false, true, 0, format_group); VIEW_DEBUG_NAME("ht_elf"); String fn; LOG("%y: ELF: found header at 0x%08qx", &file->getFilename(fn), header_ofs); ht_elf_shared_data *elf_shared = ht_malloc(sizeof(ht_elf_shared_data)); shared_data = elf_shared; elf_shared->header_ofs = header_ofs; elf_shared->shnames = NULL; elf_shared->symtables = 0; elf_shared->reloctables = 0; elf_shared->v_image = NULL; elf_shared->shrelocs = NULL; elf_shared->fake_undefined_shidx = 0; elf_shared->undefined2fakeaddr = NULL; /* read header */ file->seek(header_ofs); file->readx(&elf_shared->ident, sizeof elf_shared->ident); switch (elf_shared->ident.e_ident[ELF_EI_DATA]) { case ELFDATA2LSB: elf_shared->byte_order = little_endian; break; case ELFDATA2MSB: elf_shared->byte_order = big_endian; break; } switch (elf_shared->ident.e_ident[ELF_EI_CLASS]) { case ELFCLASS32: { file->readx(&elf_shared->header32, sizeof elf_shared->header32); createHostStruct(&elf_shared->header32, ELF_HEADER32_struct, elf_shared->byte_order); /* read section headers */ elf_shared->sheaders.count = elf_shared->header32.e_shnum; if (!elf_shared->sheaders.count) throw MsgException("Zero count for section headers"); elf_shared->sheaders.sheaders32 = ht_malloc(elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders32); file->seek(header_ofs+elf_shared->header32.e_shoff); file->readx(elf_shared->sheaders.sheaders32, elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders32); for (uint i=0; i < elf_shared->sheaders.count; i++) { ELF_SECTION_HEADER32 a = elf_shared->sheaders.sheaders32[i]; createHostStruct(elf_shared->sheaders.sheaders32+i, ELF_SECTION_HEADER32_struct, elf_shared->byte_order); } /* read program headers */ elf_shared->pheaders.count = elf_shared->header32.e_phnum;// if (!elf_shared->pheaders.count) throw MsgException("Zero count in program section headers"); if (!elf_shared->pheaders.count) { elf_shared->pheaders.pheaders32 = NULL; } else { elf_shared->pheaders.pheaders32 = ht_malloc(elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders32); file->seek(header_ofs + elf_shared->header32.e_phoff); file->readx(elf_shared->pheaders.pheaders32, elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders32); for (uint i=0; i<elf_shared->pheaders.count; i++) { createHostStruct(elf_shared->pheaders.pheaders32+i, ELF_PROGRAM_HEADER32_struct, elf_shared->byte_order); } // if file is relocatable, relocate it if (elf_shared->header32.e_type == ELF_ET_REL) { /* create a fake section for undefined symbols */ try { fake_undefined_symbols32(); } catch (const Exception &x) { errorbox("error while faking undefined ELF symbols: %y", &x); } /* create streamfile layer for relocations */ try { auto_relocate32(); } catch (const Exception &x) { errorbox("error while auto-relocating ELF symbols: %y", &x); } } } break; } case ELFCLASS64: { file->readx(&elf_shared->header64, sizeof elf_shared->header64); createHostStruct(&elf_shared->header64, ELF_HEADER64_struct, elf_shared->byte_order); /* read section headers */ elf_shared->sheaders.count=elf_shared->header64.e_shnum; if (!elf_shared->sheaders.count) throw MsgException("Zero count for section headers"); elf_shared->sheaders.sheaders64 = ht_malloc(elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders64); file->seek(header_ofs+elf_shared->header64.e_shoff); file->readx(elf_shared->sheaders.sheaders64, elf_shared->sheaders.count*sizeof *elf_shared->sheaders.sheaders64); for (uint i=0; i<elf_shared->sheaders.count; i++) { ELF_SECTION_HEADER64 a = elf_shared->sheaders.sheaders64[i]; createHostStruct(elf_shared->sheaders.sheaders64+i, ELF_SECTION_HEADER64_struct, elf_shared->byte_order); } /* read program headers */ elf_shared->pheaders.count = elf_shared->header64.e_phnum;// if (!elf_shared->pheaders.count) throw MsgException("Zero count in program section headers"); if (!elf_shared->pheaders.count) { elf_shared->pheaders.pheaders64 = NULL; } else { elf_shared->pheaders.pheaders64 = ht_malloc(elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders64); /* FIXME: 64-bit */ file->seek(header_ofs + elf_shared->header64.e_phoff); file->readx(elf_shared->pheaders.pheaders64, elf_shared->pheaders.count*sizeof *elf_shared->pheaders.pheaders64); for (uint i=0; i<elf_shared->pheaders.count; i++) { createHostStruct(elf_shared->pheaders.pheaders64+i, ELF_PROGRAM_HEADER64_struct, elf_shared->byte_order); } /* create a fake section for undefined symbols */ //fake_undefined_symbols(); /* create streamfile layer for relocations */ //auto_relocate(); } break; } } /* init ifs */ ht_format_group::init_ifs(ifs); while (init_if(&htelfsymboltable_if)) elf_shared->symtables++; while (init_if(&htelfreloctable_if)) elf_shared->reloctables++;}void ht_elf::done(){ ht_format_group::done(); ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data; if (elf_shared->shnames) { for (uint i=0; i < elf_shared->sheaders.count; i++) free(elf_shared->shnames[i]); free(elf_shared->shnames); } free(elf_shared->shrelocs); switch (elf_shared->ident.e_ident[ELF_EI_CLASS]) { case ELFCLASS32: free(elf_shared->sheaders.sheaders32); free(elf_shared->pheaders.pheaders32); break; case ELFCLASS64: free(elf_shared->sheaders.sheaders64); free(elf_shared->pheaders.pheaders64); break; } delete elf_shared->undefined2fakeaddr; free(elf_shared);}uint ht_elf::find_reloc_section_for(uint si){ ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data; ELF_SECTION_HEADER32 *s=elf_shared->sheaders.sheaders32; for (uint i=0; i < elf_shared->sheaders.count; i++) { if ((s->sh_type == ELF_SHT_REL || s->sh_type == ELF_SHT_RELA) && s->sh_info == si) { return i; } s++; } return 0;}#define INVENT_BASE 0x100000#define INVENT_STEPPING 0x100000#define INVENT_LIMIT 0xffffffffstatic elf32_addr elf32_invent_address(uint si, ELF_SECTION_HEADER32 *s, uint scount, elf32_addr base = INVENT_BASE){ elf32_addr a = base; assert(s[si].sh_addr == 0); while (a<INVENT_LIMIT-s[si].sh_size) { bool ok = true; for (uint i=0; i<scount; i++) { if ((a >= s[i].sh_addr) && (a < s[i].sh_addr+s[i].sh_size)) { ok = false; break; } } if (ok) return a; a += INVENT_STEPPING; } return 0;}void ht_elf::relocate_section(ht_reloc_file *f, uint si, uint rsi, elf32_addr a){ // relocate section si (using section rsi) to address a ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data; ELF_SECTION_HEADER32 *s=elf_shared->sheaders.sheaders32; FileOfs relh = s[rsi].sh_offset; uint symtabidx = s[rsi].sh_link; if (!isValidELFSectionIdx(elf_shared, symtabidx)) throw MsgfException("invalid symbol table index %d", symtabidx); FileOfs symh = elf_shared->sheaders.sheaders32[symtabidx].sh_offset; if (s[rsi].sh_type != ELF_SHT_REL) throw MsgfException( "invalid section type for section %d (expeecting %d)", rsi, ELF_SHT_REL); uint relnum = s[rsi].sh_size / sizeof (ELF_REL32); for (uint i=0; i < relnum; i++) { // read ELF_REL32 ELF_REL32 r; file->seek(relh + i * sizeof r); file->readx(&r, sizeof r); createHostStruct(&r, ELF_REL32_struct, elf_shared->byte_order); // read ELF_SYMBOL32 uint symbolidx = ELF32_R_SYM(r.r_info); ELF_SYMBOL32 sym; file->seek(symh+symbolidx*sizeof (ELF_SYMBOL32)); file->read(&sym, sizeof sym); createHostStruct(&sym, ELF_SYMBOL32_struct, elf_shared->byte_order); // calc reloc vals uint32 A = 0; uint32 P = r.r_offset+s[si].sh_addr; uint32 S; if ((sym.st_shndx > 0) && (sym.st_shndx < elf_shared->sheaders.count)) { S = sym.st_value + elf_shared->shrelocs[sym.st_shndx].relocAddr; } else if (elf_shared->fake_undefined_shidx >= 0) { FakeAddr s(symtabidx, symbolidx, 0); FakeAddr *fa = (FakeAddr *) elf_shared->undefined2fakeaddr->get( elf_shared->undefined2fakeaddr->find(&s)); if (fa) { S = fa->addr; } else continue; } else { // skip this one // FIXME: nyi continue; } Object *z = new ht_elf32_reloc_entry(ELF32_R_TYPE(r.r_info), A, P, S); f->insert_reloc(r.r_offset+s[si].sh_offset, z); }}#define FAKE_SECTION_BASEADDR 0x4acc0000/* "resolve" undefined references by creating fake section and fake addresses */void ht_elf::fake_undefined_symbols32(){ ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)shared_data; // create a fake section elf_shared->fake_undefined_shidx = elf_shared->sheaders.count; elf_shared->sheaders.count++; elf_shared->sheaders.sheaders32 = (ELF_SECTION_HEADER32*) realloc(elf_shared->sheaders.sheaders32, sizeof (ELF_SECTION_HEADER32)* elf_shared->sheaders.count);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -