dwfl_module_addrsym.c revision 6258e7486eb3eed6e50005946795c5fbf73aa106
16258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper/* Find debugging and symbol information for a module in libdwfl.
26258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
36258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   This file is part of Red Hat elfutils.
46258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
56258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Red Hat elfutils is free software; you can redistribute it and/or modify
66258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   it under the terms of the GNU General Public License as published by the
76258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Free Software Foundation; version 2 of the License.
86258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
96258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Red Hat elfutils is distributed in the hope that it will be useful, but
106258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
116258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
126258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   General Public License for more details.
136258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
146258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   You should have received a copy of the GNU General Public License along
156258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   with Red Hat elfutils; if not, write to the Free Software Foundation,
166258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
176258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
186258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   In addition, as a special exception, Red Hat, Inc. gives You the
196258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   additional right to link the code of Red Hat elfutils with code licensed
206258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   under any Open Source Initiative certified open source license
216258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   (http://www.opensource.org/licenses/index.php) which requires the
226258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   distribution of source code with any binary distribution and to
236258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   distribute linked combinations of the two.  Non-GPL Code permitted under
246258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   this exception must only link to the code of Red Hat elfutils through
256258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   those well defined interfaces identified in the file named EXCEPTION
266258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   found in the source code files (the "Approved Interfaces").  The files
276258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   of Non-GPL Code may instantiate templates or use macros or inline
286258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   functions from the Approved Interfaces without causing the resulting
296258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   work to be covered by the GNU General Public License.  Only Red Hat,
306258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Inc. may make changes or additions to the list of Approved Interfaces.
316258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Red Hat's grant of this exception is conditioned upon your not adding
326258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   any new exceptions.  If you wish to add a new Approved Interface or
336258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   exception, please contact Red Hat.  You must obey the GNU General Public
346258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   License in all respects for all of the Red Hat elfutils code and other
356258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   code used in conjunction with Red Hat elfutils except the Non-GPL Code
366258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   covered by this exception.  If you modify this file, you may extend this
376258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   exception to your version of the file, but you are not obligated to do
386258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   so.  If you do not wish to provide this exception without modification,
396258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   you must delete this exception statement from your version and license
406258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   this file solely under the GPL without exception.
416258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
426258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Red Hat elfutils is an included package of the Open Invention Network.
436258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   An included package of the Open Invention Network is a package for which
446258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Open Invention Network licensees cross-license their patents.  No patent
456258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   license is granted, either expressly or impliedly, by designation as an
466258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   included package.  Should you wish to participate in the Open Invention
476258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   Network licensing program, please visit www.openinventionnetwork.com
486258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   <http://www.openinventionnetwork.com>.  */
496258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
506258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper#include "libdwflP.h"
516258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
526258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepperconst char *
536258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepperdwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
546258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		     GElf_Sym *closest_sym, GElf_Word *shndxp)
556258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper{
566258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  int syments = INTUSE(dwfl_module_getsymtab) (mod);
576258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  if (syments < 0)
586258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    return NULL;
596258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
606258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  /* Return true iff we consider ADDR to lie in the same section as SYM.  */
616258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  GElf_Word addr_shndx = SHN_UNDEF;
626258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  inline bool same_section (const GElf_Sym *sym, GElf_Word shndx)
636258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    {
646258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      /* For absolute symbols and the like, only match exactly.  */
656258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      if (shndx >= SHN_LORESERVE)
666258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	return sym->st_value == addr;
676258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
686258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      /* Ignore section and other special symbols.  */
696258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      switch (GELF_ST_TYPE (sym->st_info))
706258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	{
716258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	case STT_SECTION:
726258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	case STT_FILE:
736258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	case STT_TLS:
746258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  return false;
756258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	}
766258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
776258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      /* Figure out what section ADDR lies in.  */
786258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      if (addr_shndx == SHN_UNDEF)
796258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	{
806258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  GElf_Addr mod_addr = addr - mod->symfile->bias;
816258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  Elf_Scn *scn = NULL;
826258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  addr_shndx = SHN_ABS;
836258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  while ((scn = elf_nextscn (mod->symfile->elf, scn)) != NULL)
846258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    {
856258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      GElf_Shdr shdr_mem;
866258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
876258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      if (likely (shdr != NULL)
886258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		  && mod_addr >= shdr->sh_addr
896258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		  && mod_addr < shdr->sh_addr + shdr->sh_size)
906258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		{
916258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		  addr_shndx = elf_ndxscn (scn);
926258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		  break;
936258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper		}
946258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    }
956258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	}
966258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
976258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      return shndx == addr_shndx;
986258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    }
996258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
1006258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  /* Look through the symbol table for a matching symbol.  */
1016258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  const char *closest_name = NULL;
1026258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  closest_sym->st_value = 0;
1036258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  GElf_Word closest_shndx = SHN_UNDEF;
1046258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  for (int i = 1; i < syments; ++i)
1056258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    {
1066258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      GElf_Sym sym;
1076258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      GElf_Word shndx;
1086258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx);
1096258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper      if (name != NULL && sym.st_value <= addr)
1106258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	{
1116258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  inline void closest (void)
1126258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    {
1136258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      *closest_sym = sym;
1146258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      closest_shndx = shndx;
1156258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      closest_name = name;
1166258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    }
1176258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
1186258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  if (addr < sym.st_value + sym.st_size)
1196258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    {
1206258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      closest ();
1216258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      break;
1226258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    }
1236258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
1246258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  /* Handwritten assembly symbols sometimes have no st_size.
1256258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	     If no symbol with proper size includes the address, we'll
1266258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	     use the closest one that is in the same section as ADDR.   */
1276258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	  if (sym.st_size == 0 && sym.st_value >= closest_sym->st_value
1286258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	      && same_section (&sym, shndx))
1296258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    closest ();
1306258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	}
1316258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    }
1326258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
1336258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  if (shndxp != NULL)
1346258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    *shndxp = closest_shndx;
1356258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  return closest_name;
1366258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper}
1376258e7486eb3eed6e50005946795c5fbf73aa106Ulrich DrepperINTDEF (dwfl_module_addrsym)
138