16258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper/* Find debugging and symbol information for a module in libdwfl.
2159ac52b061c60947a943c102298cd692223274fMark Wielaard   Copyright (C) 2005-2013 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
46258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
76258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
216258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
226258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
236258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper   General Public License for more details.
246258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
286258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
296258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper#include "libdwflP.h"
306258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
31b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehstruct search_state
326258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper{
33b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  Dwfl_Module *mod;
34b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Addr addr;
356258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
36b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Sym *closest_sym;
37b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  bool adjust_st_value;
38b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Word addr_shndx;
39b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  Elf *addr_symelf;
40159ac52b061c60947a943c102298cd692223274fMark Wielaard
41b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* Keep track of the closest symbol we have seen so far.
42b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh     Here we store only symbols with nonzero st_size.  */
43b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  const char *closest_name;
44b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Addr closest_value;
45b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Word closest_shndx;
46b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  Elf *closest_elf;
47159ac52b061c60947a943c102298cd692223274fMark Wielaard
48b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* Keep track of an eligible symbol with st_size == 0 as a fallback.  */
49b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  const char *sizeless_name;
50b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Sym sizeless_sym;
51b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Addr sizeless_value;
52b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Word sizeless_shndx;
53b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  Elf *sizeless_elf;
546258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
55b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* Keep track of the lowest address a relevant sizeless symbol could have.  */
56b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  GElf_Addr min_label;
57b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh};
586258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
59b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh/* Return true iff we consider ADDR to lie in the same section as SYM.  */
60b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehstatic inline bool
61b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehsame_section (struct search_state *state,
62b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      GElf_Addr value, Elf *symelf, GElf_Word shndx)
63b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
64b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* For absolute symbols and the like, only match exactly.  */
65b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (shndx >= SHN_LORESERVE)
66b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    return value == state->addr;
67b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
68b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* If value might not be st_value, the shndx of the symbol might
69b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      not match the section of the value. Explicitly look both up.  */
70b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (! state->adjust_st_value)
71b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
72b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      Dwarf_Addr v;
73b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      if (state->addr_shndx == SHN_UNDEF)
74b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh        {
75b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh          v = state->addr;
76b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh          state->addr_shndx = __libdwfl_find_section_ndx (state->mod, &v);
77b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh        }
78b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
79b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      v = value;
80b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return state->addr_shndx == __libdwfl_find_section_ndx (state->mod, &v);
816258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper    }
826258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
83b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  /* Figure out what section ADDR lies in.  */
84b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (state->addr_shndx == SHN_UNDEF || state->addr_symelf != symelf)
85b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
86b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      GElf_Addr mod_addr = dwfl_deadjust_st_value (state->mod, symelf,
87b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh						   state->addr);
88b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      Elf_Scn *scn = NULL;
89b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state->addr_shndx = SHN_ABS;
90b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state->addr_symelf = symelf;
91b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      while ((scn = elf_nextscn (symelf, scn)) != NULL)
92b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh        {
93b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh          GElf_Shdr shdr_mem;
94b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh          GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
95b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh          if (likely (shdr != NULL)
96b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh              && mod_addr >= shdr->sh_addr
97b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh              && mod_addr < shdr->sh_addr + shdr->sh_size)
98b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh            {
99b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh              state->addr_shndx = elf_ndxscn (scn);
100b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh              break;
101b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh            }
102b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh        }
103b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    }
10442f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath
105b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  return shndx == state->addr_shndx && state->addr_symelf == symelf;
106b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh}
10742f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath
108b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh/* Return GELF_ST_BIND as higher-is-better integer.  */
109b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehstatic inline int
110b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehbinding_value (const GElf_Sym *symp)
111b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
112b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  switch (GELF_ST_BIND (symp->st_info))
113b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
114b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    case STB_GLOBAL:
115b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return 3;
116b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    case STB_WEAK:
117b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return 2;
118b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    case STB_LOCAL:
119b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return 1;
120b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    default:
121b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      return 0;
122b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    }
123b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh}
12442f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath
125b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh/* Try one symbol and associated value from the search table.  */
126b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehstatic inline void
127b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehtry_sym_value (struct search_state *state,
128b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh               GElf_Addr value, GElf_Sym *sym,
129b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh               const char *name, GElf_Word shndx,
130b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh               Elf *elf, bool resolved)
131b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
132159ac52b061c60947a943c102298cd692223274fMark Wielaard    /* Even if we don't choose this symbol, its existence excludes
133159ac52b061c60947a943c102298cd692223274fMark Wielaard       any sizeless symbol (assembly label) that is below its upper
134159ac52b061c60947a943c102298cd692223274fMark Wielaard       bound.  */
135b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    if (value + sym->st_size > state->min_label)
136b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state->min_label = value + sym->st_size;
137159ac52b061c60947a943c102298cd692223274fMark Wielaard
138b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    if (sym->st_size == 0 || state->addr - value < sym->st_size)
139159ac52b061c60947a943c102298cd692223274fMark Wielaard      {
140159ac52b061c60947a943c102298cd692223274fMark Wielaard	/* This symbol is a better candidate than the current one
141159ac52b061c60947a943c102298cd692223274fMark Wielaard	   if it's closer to ADDR or is global when it was local.  */
142b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	if (state->closest_name == NULL
143b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    || state->closest_value < value
144b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    || binding_value (state->closest_sym) < binding_value (sym))
145159ac52b061c60947a943c102298cd692223274fMark Wielaard	  {
146159ac52b061c60947a943c102298cd692223274fMark Wielaard	    if (sym->st_size != 0)
147159ac52b061c60947a943c102298cd692223274fMark Wielaard	      {
148b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		*state->closest_sym = *sym;
149b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->closest_value = value;
150b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->closest_shndx = shndx;
151b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->closest_elf = elf;
152b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->closest_name = name;
153159ac52b061c60947a943c102298cd692223274fMark Wielaard	      }
154b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    else if (state->closest_name == NULL
155b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		     && value >= state->min_label
156b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		     && same_section (state, value,
157b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh				      resolved ? state->mod->main.elf : elf,
158b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh				      shndx))
159159ac52b061c60947a943c102298cd692223274fMark Wielaard	      {
160159ac52b061c60947a943c102298cd692223274fMark Wielaard		/* Handwritten assembly symbols sometimes have no
161159ac52b061c60947a943c102298cd692223274fMark Wielaard		   st_size.  If no symbol with proper size includes
162159ac52b061c60947a943c102298cd692223274fMark Wielaard		   the address, we'll use the closest one that is in
163159ac52b061c60947a943c102298cd692223274fMark Wielaard		   the same section as ADDR.  */
164b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->sizeless_sym = *sym;
165b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->sizeless_value = value;
166b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->sizeless_shndx = shndx;
167b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->sizeless_elf = elf;
168b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		state->sizeless_name = name;
169159ac52b061c60947a943c102298cd692223274fMark Wielaard	      }
170159ac52b061c60947a943c102298cd692223274fMark Wielaard	  }
171159ac52b061c60947a943c102298cd692223274fMark Wielaard	/* When the beginning of its range is no closer,
172159ac52b061c60947a943c102298cd692223274fMark Wielaard	   the end of its range might be.  Otherwise follow
173159ac52b061c60947a943c102298cd692223274fMark Wielaard	   GELF_ST_BIND preference.  If all are equal prefer
174159ac52b061c60947a943c102298cd692223274fMark Wielaard	   the first symbol found.  */
175159ac52b061c60947a943c102298cd692223274fMark Wielaard	else if (sym->st_size != 0
176b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		 && state->closest_value == value
177b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		 && ((state->closest_sym->st_size > sym->st_size
178b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		      && (binding_value (state->closest_sym)
179159ac52b061c60947a943c102298cd692223274fMark Wielaard			  <= binding_value (sym)))
180b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		     || (state->closest_sym->st_size >= sym->st_size
181b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh			 && (binding_value (state->closest_sym)
182159ac52b061c60947a943c102298cd692223274fMark Wielaard			     < binding_value (sym)))))
183159ac52b061c60947a943c102298cd692223274fMark Wielaard	  {
184b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    *state->closest_sym = *sym;
185b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    state->closest_value = value;
186b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    state->closest_shndx = shndx;
187b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    state->closest_elf = elf;
188b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	    state->closest_name = name;
189159ac52b061c60947a943c102298cd692223274fMark Wielaard	  }
190159ac52b061c60947a943c102298cd692223274fMark Wielaard      }
191b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh}
192159ac52b061c60947a943c102298cd692223274fMark Wielaard
193b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh/* Look through the symbol table for a matching symbol.  */
194b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehstatic inline void
195b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehsearch_table (struct search_state *state, int start, int end)
196b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
197ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard      for (int i = start; i < end; ++i)
1986258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	{
199ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	  GElf_Sym sym;
200159ac52b061c60947a943c102298cd692223274fMark Wielaard	  GElf_Addr value;
201ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	  GElf_Word shndx;
202819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard	  Elf *elf;
203159ac52b061c60947a943c102298cd692223274fMark Wielaard	  bool resolved;
204b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	  const char *name = __libdwfl_getsym (state->mod, i, &sym, &value,
205159ac52b061c60947a943c102298cd692223274fMark Wielaard					       &shndx, &elf, NULL,
206b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh					       &resolved,
207b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh					       state->adjust_st_value);
208ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	  if (name != NULL && name[0] != '\0'
209ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	      && sym.st_shndx != SHN_UNDEF
210b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      && value <= state->addr
211ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	      && GELF_ST_TYPE (sym.st_info) != STT_SECTION
212ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	      && GELF_ST_TYPE (sym.st_info) != STT_FILE
213ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard	      && GELF_ST_TYPE (sym.st_info) != STT_TLS)
214c76f0b05676f6207affbfd85e75063db3b6eeccfRoland McGrath	    {
215b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      try_sym_value (state, value, &sym, name, shndx, elf, resolved);
216ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard
217159ac52b061c60947a943c102298cd692223274fMark Wielaard	      /* If this is an addrinfo variant and the value could be
218159ac52b061c60947a943c102298cd692223274fMark Wielaard		 resolved then also try matching the (adjusted) st_value.  */
219b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh	      if (resolved && state->mod->e_type != ET_REL)
220c76f0b05676f6207affbfd85e75063db3b6eeccfRoland McGrath		{
221159ac52b061c60947a943c102298cd692223274fMark Wielaard		  GElf_Addr adjusted_st_value;
222b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		  adjusted_st_value = dwfl_adjusted_st_value (state->mod, elf,
223159ac52b061c60947a943c102298cd692223274fMark Wielaard							      sym.st_value);
224b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		  if (value != adjusted_st_value
225b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		      && adjusted_st_value <= state->addr)
226b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		    try_sym_value (state, adjusted_st_value, &sym, name, shndx,
227159ac52b061c60947a943c102298cd692223274fMark Wielaard				   elf, false);
22842f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath		}
2296258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	    }
2306258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper	}
231b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh}
232b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
233b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh/* Returns the name of the symbol "closest" to ADDR.
234b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh   Never returns symbols at addresses above ADDR.  */
235b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehconst char *
236b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsiehinternal_function
237b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh__libdwfl_addrsym (Dwfl_Module *_mod, GElf_Addr _addr, GElf_Off *off,
238b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		   GElf_Sym *_closest_sym, GElf_Word *shndxp,
239b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh		   Elf **elfp, Dwarf_Addr *biasp, bool _adjust_st_value)
240b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh{
241b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  int syments = INTUSE(dwfl_module_getsymtab) (_mod);
242b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (syments < 0)
243b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    return NULL;
244b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh
245b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  struct search_state state =
246b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    {
247b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .addr = _addr,
248b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .mod = _mod,
249b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .closest_sym = _closest_sym,
250b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .adjust_st_value = _adjust_st_value,
251b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .addr_shndx = SHN_UNDEF,
252b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .addr_symelf = NULL,
253b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .closest_name = NULL,
254b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .closest_value = 0,
255b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .closest_shndx = SHN_UNDEF,
256b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .closest_elf = NULL,
257b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .sizeless_name = NULL,
258b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF },
259b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .sizeless_value = 0,
260b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .sizeless_shndx = SHN_UNDEF,
261b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .sizeless_elf = NULL,
262b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      .min_label = 0
263b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    };
2646258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper
2655083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard  /* First go through global symbols.  mod->first_global and
2665083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard     mod->aux_first_global are setup by dwfl_module_getsymtab to the
267697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     index of the first global symbol in those symbol tables.  Both
268697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     are non-zero when the table exist, except when there is only a
269697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     dynsym table loaded through phdrs, then first_global is zero and
270697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     there will be no auxiliary table.  All symbols with local binding
271697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     come first in the symbol table, then all globals.  The zeroth,
272697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     null entry, in the auxiliary table is skipped if there is a main
273697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard     table.  */
274b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  int first_global = INTUSE (dwfl_module_getsymtab_first_global) (state.mod);
27514c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard  if (first_global < 0)
27614c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard    return NULL;
277b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  search_table (&state, first_global == 0 ? 1 : first_global, syments);
278ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard
279ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard  /* If we found nothing searching the global symbols, then try the locals.
280ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard     Unless we have a global sizeless symbol that matches exactly.  */
281b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (state.closest_name == NULL && first_global > 1
282b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      && (state.sizeless_name == NULL || state.sizeless_value != state.addr))
283b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    search_table (&state, 1, first_global);
284ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard
28542f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath  /* If we found no proper sized symbol to use, fall back to the best
28642f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath     candidate sizeless symbol we found, if any.  */
287b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  if (state.closest_name == NULL
288b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      && state.sizeless_name != NULL
289b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      && state.sizeless_value >= state.min_label)
29042f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath    {
291b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      *state.closest_sym = state.sizeless_sym;
292b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state.closest_value = state.sizeless_value;
293b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state.closest_shndx = state.sizeless_shndx;
294b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state.closest_elf = state.sizeless_elf;
295b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh      state.closest_name = state.sizeless_name;
29642f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath    }
29742f686820a19806da629990bf7ae69a6a2fcfb1fRoland McGrath
298b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  *off = state.addr - state.closest_value;
299159ac52b061c60947a943c102298cd692223274fMark Wielaard
3006258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper  if (shndxp != NULL)
301b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    *shndxp = state.closest_shndx;
302819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard  if (elfp != NULL)
303b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    *elfp = state.closest_elf;
304819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard  if (biasp != NULL)
305b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh    *biasp = dwfl_adjusted_st_value (state.mod, state.closest_elf, 0);
306b1450614fd26d1a9b8ee17fe3f0290d23ddd0748Chih-Hung Hsieh  return state.closest_name;
3076258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper}
308819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard
309819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard
310819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaardconst char *
311819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaarddwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
312819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard		     GElf_Sym *closest_sym, GElf_Word *shndxp)
313819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard{
314159ac52b061c60947a943c102298cd692223274fMark Wielaard  GElf_Off off;
315159ac52b061c60947a943c102298cd692223274fMark Wielaard  return __libdwfl_addrsym (mod, addr, &off, closest_sym, shndxp,
316159ac52b061c60947a943c102298cd692223274fMark Wielaard			    NULL, NULL, true);
317819c349f6339512d6961a6172c539fdf2c2f1328Mark Wielaard}
3186258e7486eb3eed6e50005946795c5fbf73aa106Ulrich DrepperINTDEF (dwfl_module_addrsym)
319159ac52b061c60947a943c102298cd692223274fMark Wielaard
320159ac52b061c60947a943c102298cd692223274fMark Wielaardconst char
321159ac52b061c60947a943c102298cd692223274fMark Wielaard*dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
322159ac52b061c60947a943c102298cd692223274fMark Wielaard		       GElf_Off *offset, GElf_Sym *sym,
323159ac52b061c60947a943c102298cd692223274fMark Wielaard		       GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *bias)
324159ac52b061c60947a943c102298cd692223274fMark Wielaard{
325159ac52b061c60947a943c102298cd692223274fMark Wielaard  return __libdwfl_addrsym (mod, address, offset, sym, shndxp, elfp, bias,
326159ac52b061c60947a943c102298cd692223274fMark Wielaard			    false);
327159ac52b061c60947a943c102298cd692223274fMark Wielaard}
328159ac52b061c60947a943c102298cd692223274fMark WielaardINTDEF (dwfl_module_addrinfo)
329