/* ----------------------------------------------------------------------------- * elf.c * * ELF file management. This file contains functions for accessing ELF * file data from a raw memory mapped ELF file (as performed by the * functions in object.c). * * Author(s) : David Beazley (beazley@cs.uchicago.edu) * * Copyright (C) 2000. The University of Chicago. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * See the file COPYING for a complete copy of the LGPL. * ----------------------------------------------------------------------------- */ #include "wad.h" static char cvs[] = "$Header: /cvsroot/swig/SWIG/Tools/WAD/Wad/elf.c,v 1.14 2001/06/20 15:12:53 beazley Exp $"; #ifdef WAD_SOLARIS #include #endif #ifdef WAD_LINUX #include #endif /* --- What's needed here (high level interface) : - Mapping of addresses to symbols - Mapping of symbols to file+line */ /* ----------------------------------------------------------------------------- * wad_elf_check() * * Checks to see if an object file is an ELF file. Returns 1 on success and * changes the type flag of wo to indicate the type of ELF file. * ----------------------------------------------------------------------------- */ int wad_elf_check(WadObjectFile *wo) { if (strncmp((char *)wo->ptr,ELFMAG, SELFMAG) != 0) return 0; /* Probably need to put some kind of 32/64 bit check here */ return 1; } /* ----------------------------------------------------------------------------- * wad_elf_phdrcnt() * * Return number of entries in the ELF program header section * ----------------------------------------------------------------------------- */ int wad_elf_phdrcnt(WadObjectFile *wo) { Elf32_Ehdr *eh; eh = (Elf32_Ehdr *) wo->ptr; return eh->e_phnum; } /* ----------------------------------------------------------------------------- * wad_elf_phdrpos() * * Return the location of the ELF program header. * ----------------------------------------------------------------------------- */ void * wad_elf_phdrpos(WadObjectFile *wo) { Elf32_Ehdr *eh; char *c; eh = (Elf32_Ehdr *) wo->ptr; c = (char *) wo->ptr; return (void *) (c+eh->e_phoff); } /* ----------------------------------------------------------------------------- * wad_elf_shdrcnt() * * Return number of entries in the ELF section header * ----------------------------------------------------------------------------- */ int wad_elf_shdrcnt(WadObjectFile *wo) { Elf32_Ehdr *eh; eh = (Elf32_Ehdr *) wo->ptr; return eh->e_shnum; } /* ----------------------------------------------------------------------------- * wad_elf_shdrpos() * * Return the location of the section headers * ----------------------------------------------------------------------------- */ void * wad_elf_shdrpos(WadObjectFile *wo) { Elf32_Ehdr *eh; char *c; eh = (Elf32_Ehdr *) wo->ptr; c = (char *) wo->ptr; return (void *) (c+eh->e_shoff); } /* ----------------------------------------------------------------------------- * wad_elf_section_header() * * Get a specific section number * ----------------------------------------------------------------------------- */ void *wad_elf_section_header(WadObjectFile *wo, int sn) { Elf32_Ehdr *eh; char *r; eh = (Elf32_Ehdr *) wo->ptr; if ((sn < 0) || (sn >= eh->e_shnum)) return 0; r = (char *) wad_elf_shdrpos(wo) + (sn*eh->e_shentsize); return (void *) r; } /* ----------------------------------------------------------------------------- * wad_elf_section_data() * * Get section data * ----------------------------------------------------------------------------- */ void *wad_elf_section_data(WadObjectFile *wo, int sn) { Elf32_Shdr *sh; char *r; sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn); if (!sh) return 0; r = ((char *) wo->ptr) + sh->sh_offset; return r; } /* ----------------------------------------------------------------------------- * wad_elf_section_size() * Return section size * ----------------------------------------------------------------------------- */ int wad_elf_section_size(WadObjectFile *wo, int sn) { Elf32_Shdr *sh; sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn); if (!sh) return -1; return sh->sh_size; } /* ----------------------------------------------------------------------------- * wad_elf_section_name() * * Returns the name of an ELF section * ----------------------------------------------------------------------------- */ char *wad_elf_section_name(WadObjectFile *wo, int sn) { Elf32_Ehdr *eh; Elf32_Shdr *sh; char *sectionstr; eh = (Elf32_Ehdr *) wo->ptr; /* Get the string table */ sectionstr = (char *) wad_elf_section_data(wo,eh->e_shstrndx); if (!sectionstr) { return 0; } /* Get the section header for the section */ sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn); if (!sh) return 0; return sectionstr + sh->sh_name; } /* ----------------------------------------------------------------------------- * wad_elf_section_byname() * * Get section data given a section name * ----------------------------------------------------------------------------- */ int wad_elf_section_byname(WadObjectFile *wo, char *name) { int i; char *sn; int n; n = wad_elf_shdrcnt(wo); for (i = 0; i pc; base = (unsigned long) f->segment->base; nsymtab = wad_elf_section_byname(f->object,secname); if (nsymtab < 0) return 0; nstrtab = wad_elf_section_byname(f->object,strname); if (nstrtab < 0) return 0; symtab_size = wad_elf_section_size(f->object,nsymtab); sym = (Elf32_Sym *) wad_elf_section_data(f->object,nsymtab); str = (char *) wad_elf_section_data(f->object,nstrtab); nsym = (symtab_size/sizeof(Elf32_Sym)); for (i = 0; i < nsym; i++) { name = str + sym[i].st_name; /* Look for filename in case the symbol maps to a local symbol */ if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) { localfile = name; } if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) { wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx); } if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) { #ifdef WAD_LINUX /* If the section index is 0, the symbol is undefined */ if (sym[i].st_shndx == 0) continue; #endif f->sym_name = name; f->sym_nlen = strlen(name); f->sym_base = base + sym[i].st_value; f->sym_size = sym[i].st_size; if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) { f->sym_file = localfile; f->sym_bind = SYM_LOCAL; } else { f->sym_bind = SYM_GLOBAL; } return 1; } } return 0; } void wad_elf_find_symbol(WadFrame *f) { /* We simply try a few possible sections */ if (elf_search_section_sym(f,".symtab",".strtab")) return; if (elf_search_section_sym(f,".dynsym",".dynstr")) return; /* Hmmm. No match found. Oh well */ return; } /* ----------------------------------------------------------------------------- * wad_elf_debug_info() * * Gather debugging information about a function (if possible) * ----------------------------------------------------------------------------- */ int wad_elf_debug_info(WadFrame *f) { int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr; int ret; void *stab; char *stabstr; int stabsize; nstab = wad_elf_section_byname(f->object,".stab"); nstabstr = wad_elf_section_byname(f->object,".stabstr"); nstabindex = wad_elf_section_byname(f->object,".stab.index"); nstabindexstr = wad_elf_section_byname(f->object,".stab.indexstr"); nstabexcl = wad_elf_section_byname(f->object,".stab.excl"); nstabexclstr = wad_elf_section_byname(f->object,".stab.exclstr"); #ifdef DEBUG_DEBUG wad_printf("nstab = %d\n", nstab); wad_printf("nstabstr = %d\n", nstabstr); wad_printf("nstabindex = %d\n", nstabindex); wad_printf("nstabindexstr = %d\n", nstabindexstr); wad_printf("nstabexcl = %d\n", nstabexcl); wad_printf("nstabexclstr = %d\n", nstabexclstr); #endif /* Now start searching stabs */ /* Look in the .stab section */ if (nstab > 0) { stab = wad_elf_section_data(f->object,nstab); stabsize = wad_elf_section_size(f->object,nstab); stabstr = (char *) wad_elf_section_data(f->object,nstabstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.excl section. A solaris oddity? */ if (nstabexcl > 0) { stab = wad_elf_section_data(f->object,nstabexcl); stabsize = wad_elf_section_size(f->object, nstabexcl); stabstr = (char *) wad_elf_section_data(f->object, nstabexclstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.index section. A Solaris oddity? */ if (nstabindex > 0) { stab = wad_elf_section_data(f->object,nstabindex); stabsize = wad_elf_section_size(f->object, nstabindex); stabstr = (char *) wad_elf_section_data(f->object, nstabindexstr); if (wad_search_stab(stab,stabsize,stabstr, f)) { /* Hmmm. Might be in a different file */ WadObjectFile *wo1, *wold; char objfile[MAX_PATH]; /* printf("DEBUG %s\n", f->sym_name); */ wad_strcpy(objfile, f->loc_objfile); wo1 = wad_object_load(objfile); if (wo1) { wold = f->object; f->object = wo1; wad_find_debug(f); f->object = wold; return ret; } else { /* wad_printf("couldn't load %s\n", objfile); */ } /* if (!ret) return wad_search_stab(stab,stabsize,stabstr,f);*/ return ret; } } return 0; } /* ----------------------------------------------------------------------------- * wad_elf_debug() * * Print some debugging information about an object * ----------------------------------------------------------------------------- */ void wad_elf_debug(WadObjectFile *wo) { int i; wad_printf("ELF Debug : obj = %x (%s)\n", wo, wo->path); wad_printf(" phdrcnt = %d\n", wad_elf_phdrcnt(wo)); wad_printf(" phdrpos = %x\n", wad_elf_phdrpos(wo)); wad_printf(" shdrcnt = %d\n", wad_elf_shdrcnt(wo)); wad_printf(" shdrpos = %x\n", wad_elf_shdrpos(wo)); for (i = 0; i < wad_elf_shdrcnt(wo); i++) { wad_printf(" section '%s': data = 0x%x, size = %d\n", wad_elf_section_name(wo,i), wad_elf_section_data(wo,i), wad_elf_section_size(wo,i)); } } /* general purpose functions exposed to the outside world */ /* ----------------------------------------------------------------------------- * wad_find_symbol() * ----------------------------------------------------------------------------- */ void wad_find_symbol(WadFrame *f) { if (wad_debug_mode & DEBUG_SYMBOL) { wad_printf("wad: Searching for 0x%08x --> ", f->pc); } if (f->object) wad_elf_find_symbol(f); if (wad_debug_mode & DEBUG_SYMBOL) { if (f->sym_name) { wad_printf("%s", f->sym_name); if (f->sym_file) wad_printf(" in '%s'\n", f->sym_file); else wad_printf("\n"); } else { wad_printf("?\n"); } } } void wad_find_debug(WadFrame *f) { /* if (f->debug_check) return; */ if (f->object) { wad_elf_debug_info(f); } /* f->debug_check = 1; */ }