1da0c48c4Sopenharmony_ci/* Find debugging and symbol information for a module in libdwfl.
2da0c48c4Sopenharmony_ci   Copyright (C) 2005-2013 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of either
7da0c48c4Sopenharmony_ci
8da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
9da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
10da0c48c4Sopenharmony_ci       your option) any later version
11da0c48c4Sopenharmony_ci
12da0c48c4Sopenharmony_ci   or
13da0c48c4Sopenharmony_ci
14da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
15da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
16da0c48c4Sopenharmony_ci       your option) any later version
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci   or both in parallel, as here.
19da0c48c4Sopenharmony_ci
20da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
21da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23da0c48c4Sopenharmony_ci   General Public License for more details.
24da0c48c4Sopenharmony_ci
25da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
26da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
27da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
30da0c48c4Sopenharmony_ci# include <config.h>
31da0c48c4Sopenharmony_ci#endif
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci#include "libdwflP.h"
34da0c48c4Sopenharmony_ci
35da0c48c4Sopenharmony_cistruct search_state
36da0c48c4Sopenharmony_ci{
37da0c48c4Sopenharmony_ci  Dwfl_Module *mod;
38da0c48c4Sopenharmony_ci  GElf_Addr addr;
39da0c48c4Sopenharmony_ci
40da0c48c4Sopenharmony_ci  GElf_Sym *closest_sym;
41da0c48c4Sopenharmony_ci  bool adjust_st_value;
42da0c48c4Sopenharmony_ci  GElf_Word addr_shndx;
43da0c48c4Sopenharmony_ci  Elf *addr_symelf;
44da0c48c4Sopenharmony_ci
45da0c48c4Sopenharmony_ci  /* Keep track of the closest symbol we have seen so far.
46da0c48c4Sopenharmony_ci     Here we store only symbols with nonzero st_size.  */
47da0c48c4Sopenharmony_ci  const char *closest_name;
48da0c48c4Sopenharmony_ci  GElf_Addr closest_value;
49da0c48c4Sopenharmony_ci  GElf_Word closest_shndx;
50da0c48c4Sopenharmony_ci  Elf *closest_elf;
51da0c48c4Sopenharmony_ci
52da0c48c4Sopenharmony_ci  /* Keep track of an eligible symbol with st_size == 0 as a fallback.  */
53da0c48c4Sopenharmony_ci  const char *sizeless_name;
54da0c48c4Sopenharmony_ci  GElf_Sym sizeless_sym;
55da0c48c4Sopenharmony_ci  GElf_Addr sizeless_value;
56da0c48c4Sopenharmony_ci  GElf_Word sizeless_shndx;
57da0c48c4Sopenharmony_ci  Elf *sizeless_elf;
58da0c48c4Sopenharmony_ci
59da0c48c4Sopenharmony_ci  /* Keep track of the lowest address a relevant sizeless symbol could have.  */
60da0c48c4Sopenharmony_ci  GElf_Addr min_label;
61da0c48c4Sopenharmony_ci};
62da0c48c4Sopenharmony_ci
63da0c48c4Sopenharmony_ci/* Return true iff we consider ADDR to lie in the same section as SYM.  */
64da0c48c4Sopenharmony_cistatic inline bool
65da0c48c4Sopenharmony_cisame_section (struct search_state *state,
66da0c48c4Sopenharmony_ci	      GElf_Addr value, Elf *symelf, GElf_Word shndx)
67da0c48c4Sopenharmony_ci{
68da0c48c4Sopenharmony_ci  /* For absolute symbols and the like, only match exactly.  */
69da0c48c4Sopenharmony_ci  if (shndx >= SHN_LORESERVE)
70da0c48c4Sopenharmony_ci    return value == state->addr;
71da0c48c4Sopenharmony_ci
72da0c48c4Sopenharmony_ci  /* If value might not be st_value, the shndx of the symbol might
73da0c48c4Sopenharmony_ci      not match the section of the value. Explicitly look both up.  */
74da0c48c4Sopenharmony_ci  if (! state->adjust_st_value)
75da0c48c4Sopenharmony_ci    {
76da0c48c4Sopenharmony_ci      Dwarf_Addr v;
77da0c48c4Sopenharmony_ci      if (state->addr_shndx == SHN_UNDEF)
78da0c48c4Sopenharmony_ci        {
79da0c48c4Sopenharmony_ci          v = state->addr;
80da0c48c4Sopenharmony_ci          state->addr_shndx = __libdwfl_find_section_ndx (state->mod, &v);
81da0c48c4Sopenharmony_ci        }
82da0c48c4Sopenharmony_ci
83da0c48c4Sopenharmony_ci      v = value;
84da0c48c4Sopenharmony_ci      return state->addr_shndx == __libdwfl_find_section_ndx (state->mod, &v);
85da0c48c4Sopenharmony_ci    }
86da0c48c4Sopenharmony_ci
87da0c48c4Sopenharmony_ci  /* Figure out what section ADDR lies in.  */
88da0c48c4Sopenharmony_ci  if (state->addr_shndx == SHN_UNDEF || state->addr_symelf != symelf)
89da0c48c4Sopenharmony_ci    {
90da0c48c4Sopenharmony_ci      GElf_Addr mod_addr = dwfl_deadjust_st_value (state->mod, symelf,
91da0c48c4Sopenharmony_ci						   state->addr);
92da0c48c4Sopenharmony_ci      Elf_Scn *scn = NULL;
93da0c48c4Sopenharmony_ci      state->addr_shndx = SHN_ABS;
94da0c48c4Sopenharmony_ci      state->addr_symelf = symelf;
95da0c48c4Sopenharmony_ci      while ((scn = elf_nextscn (symelf, scn)) != NULL)
96da0c48c4Sopenharmony_ci        {
97da0c48c4Sopenharmony_ci          GElf_Shdr shdr_mem;
98da0c48c4Sopenharmony_ci          GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
99da0c48c4Sopenharmony_ci          if (likely (shdr != NULL)
100da0c48c4Sopenharmony_ci              && mod_addr >= shdr->sh_addr
101da0c48c4Sopenharmony_ci              && mod_addr < shdr->sh_addr + shdr->sh_size)
102da0c48c4Sopenharmony_ci            {
103da0c48c4Sopenharmony_ci              state->addr_shndx = elf_ndxscn (scn);
104da0c48c4Sopenharmony_ci              break;
105da0c48c4Sopenharmony_ci            }
106da0c48c4Sopenharmony_ci        }
107da0c48c4Sopenharmony_ci    }
108da0c48c4Sopenharmony_ci
109da0c48c4Sopenharmony_ci  return shndx == state->addr_shndx && state->addr_symelf == symelf;
110da0c48c4Sopenharmony_ci}
111da0c48c4Sopenharmony_ci
112da0c48c4Sopenharmony_ci/* Return GELF_ST_BIND as higher-is-better integer.  */
113da0c48c4Sopenharmony_cistatic inline int
114da0c48c4Sopenharmony_cibinding_value (const GElf_Sym *symp)
115da0c48c4Sopenharmony_ci{
116da0c48c4Sopenharmony_ci  switch (GELF_ST_BIND (symp->st_info))
117da0c48c4Sopenharmony_ci    {
118da0c48c4Sopenharmony_ci    case STB_GLOBAL:
119da0c48c4Sopenharmony_ci      return 3;
120da0c48c4Sopenharmony_ci    case STB_WEAK:
121da0c48c4Sopenharmony_ci      return 2;
122da0c48c4Sopenharmony_ci    case STB_LOCAL:
123da0c48c4Sopenharmony_ci      return 1;
124da0c48c4Sopenharmony_ci    default:
125da0c48c4Sopenharmony_ci      return 0;
126da0c48c4Sopenharmony_ci    }
127da0c48c4Sopenharmony_ci}
128da0c48c4Sopenharmony_ci
129da0c48c4Sopenharmony_ci/* Try one symbol and associated value from the search table.  */
130da0c48c4Sopenharmony_cistatic inline void
131da0c48c4Sopenharmony_citry_sym_value (struct search_state *state,
132da0c48c4Sopenharmony_ci               GElf_Addr value, GElf_Sym *sym,
133da0c48c4Sopenharmony_ci               const char *name, GElf_Word shndx,
134da0c48c4Sopenharmony_ci               Elf *elf, bool resolved)
135da0c48c4Sopenharmony_ci{
136da0c48c4Sopenharmony_ci    /* Even if we don't choose this symbol, its existence excludes
137da0c48c4Sopenharmony_ci       any sizeless symbol (assembly label) that is below its upper
138da0c48c4Sopenharmony_ci       bound.  */
139da0c48c4Sopenharmony_ci    if (value + sym->st_size > state->min_label)
140da0c48c4Sopenharmony_ci      state->min_label = value + sym->st_size;
141da0c48c4Sopenharmony_ci
142da0c48c4Sopenharmony_ci    if (sym->st_size == 0 || state->addr - value < sym->st_size)
143da0c48c4Sopenharmony_ci      {
144da0c48c4Sopenharmony_ci	/* This symbol is a better candidate than the current one
145da0c48c4Sopenharmony_ci	   if it's closer to ADDR or is global when it was local.  */
146da0c48c4Sopenharmony_ci	if (state->closest_name == NULL
147da0c48c4Sopenharmony_ci	    || state->closest_value < value
148da0c48c4Sopenharmony_ci	    || binding_value (state->closest_sym) < binding_value (sym))
149da0c48c4Sopenharmony_ci	  {
150da0c48c4Sopenharmony_ci	    if (sym->st_size != 0)
151da0c48c4Sopenharmony_ci	      {
152da0c48c4Sopenharmony_ci		*state->closest_sym = *sym;
153da0c48c4Sopenharmony_ci		state->closest_value = value;
154da0c48c4Sopenharmony_ci		state->closest_shndx = shndx;
155da0c48c4Sopenharmony_ci		state->closest_elf = elf;
156da0c48c4Sopenharmony_ci		state->closest_name = name;
157da0c48c4Sopenharmony_ci	      }
158da0c48c4Sopenharmony_ci	    else if (state->closest_name == NULL
159da0c48c4Sopenharmony_ci		     && value >= state->min_label
160da0c48c4Sopenharmony_ci		     && same_section (state, value,
161da0c48c4Sopenharmony_ci				      resolved ? state->mod->main.elf : elf,
162da0c48c4Sopenharmony_ci				      shndx))
163da0c48c4Sopenharmony_ci	      {
164da0c48c4Sopenharmony_ci		/* Handwritten assembly symbols sometimes have no
165da0c48c4Sopenharmony_ci		   st_size.  If no symbol with proper size includes
166da0c48c4Sopenharmony_ci		   the address, we'll use the closest one that is in
167da0c48c4Sopenharmony_ci		   the same section as ADDR.  */
168da0c48c4Sopenharmony_ci		state->sizeless_sym = *sym;
169da0c48c4Sopenharmony_ci		state->sizeless_value = value;
170da0c48c4Sopenharmony_ci		state->sizeless_shndx = shndx;
171da0c48c4Sopenharmony_ci		state->sizeless_elf = elf;
172da0c48c4Sopenharmony_ci		state->sizeless_name = name;
173da0c48c4Sopenharmony_ci	      }
174da0c48c4Sopenharmony_ci	  }
175da0c48c4Sopenharmony_ci	/* When the beginning of its range is no closer,
176da0c48c4Sopenharmony_ci	   the end of its range might be.  Otherwise follow
177da0c48c4Sopenharmony_ci	   GELF_ST_BIND preference.  If all are equal prefer
178da0c48c4Sopenharmony_ci	   the first symbol found.  */
179da0c48c4Sopenharmony_ci	else if (sym->st_size != 0
180da0c48c4Sopenharmony_ci		 && state->closest_value == value
181da0c48c4Sopenharmony_ci		 && ((state->closest_sym->st_size > sym->st_size
182da0c48c4Sopenharmony_ci		      && (binding_value (state->closest_sym)
183da0c48c4Sopenharmony_ci			  <= binding_value (sym)))
184da0c48c4Sopenharmony_ci		     || (state->closest_sym->st_size >= sym->st_size
185da0c48c4Sopenharmony_ci			 && (binding_value (state->closest_sym)
186da0c48c4Sopenharmony_ci			     < binding_value (sym)))))
187da0c48c4Sopenharmony_ci	  {
188da0c48c4Sopenharmony_ci	    *state->closest_sym = *sym;
189da0c48c4Sopenharmony_ci	    state->closest_value = value;
190da0c48c4Sopenharmony_ci	    state->closest_shndx = shndx;
191da0c48c4Sopenharmony_ci	    state->closest_elf = elf;
192da0c48c4Sopenharmony_ci	    state->closest_name = name;
193da0c48c4Sopenharmony_ci	  }
194da0c48c4Sopenharmony_ci      }
195da0c48c4Sopenharmony_ci}
196da0c48c4Sopenharmony_ci
197da0c48c4Sopenharmony_ci/* Look through the symbol table for a matching symbol.  */
198da0c48c4Sopenharmony_cistatic inline void
199da0c48c4Sopenharmony_cisearch_table (struct search_state *state, int start, int end)
200da0c48c4Sopenharmony_ci{
201da0c48c4Sopenharmony_ci      for (int i = start; i < end; ++i)
202da0c48c4Sopenharmony_ci	{
203da0c48c4Sopenharmony_ci	  GElf_Sym sym;
204da0c48c4Sopenharmony_ci	  GElf_Addr value;
205da0c48c4Sopenharmony_ci	  GElf_Word shndx;
206da0c48c4Sopenharmony_ci	  Elf *elf;
207da0c48c4Sopenharmony_ci	  bool resolved;
208da0c48c4Sopenharmony_ci	  const char *name = __libdwfl_getsym (state->mod, i, &sym, &value,
209da0c48c4Sopenharmony_ci					       &shndx, &elf, NULL,
210da0c48c4Sopenharmony_ci					       &resolved,
211da0c48c4Sopenharmony_ci					       state->adjust_st_value);
212da0c48c4Sopenharmony_ci	  if (name != NULL && name[0] != '\0'
213da0c48c4Sopenharmony_ci	      && sym.st_shndx != SHN_UNDEF
214da0c48c4Sopenharmony_ci	      && value <= state->addr
215da0c48c4Sopenharmony_ci	      && GELF_ST_TYPE (sym.st_info) != STT_SECTION
216da0c48c4Sopenharmony_ci	      && GELF_ST_TYPE (sym.st_info) != STT_FILE
217da0c48c4Sopenharmony_ci	      && GELF_ST_TYPE (sym.st_info) != STT_TLS)
218da0c48c4Sopenharmony_ci	    {
219da0c48c4Sopenharmony_ci	      try_sym_value (state, value, &sym, name, shndx, elf, resolved);
220da0c48c4Sopenharmony_ci
221da0c48c4Sopenharmony_ci	      /* If this is an addrinfo variant and the value could be
222da0c48c4Sopenharmony_ci		 resolved then also try matching the (adjusted) st_value.  */
223da0c48c4Sopenharmony_ci	      if (resolved && state->mod->e_type != ET_REL)
224da0c48c4Sopenharmony_ci		{
225da0c48c4Sopenharmony_ci		  GElf_Addr adjusted_st_value;
226da0c48c4Sopenharmony_ci		  adjusted_st_value = dwfl_adjusted_st_value (state->mod, elf,
227da0c48c4Sopenharmony_ci							      sym.st_value);
228da0c48c4Sopenharmony_ci		  if (value != adjusted_st_value
229da0c48c4Sopenharmony_ci		      && adjusted_st_value <= state->addr)
230da0c48c4Sopenharmony_ci		    try_sym_value (state, adjusted_st_value, &sym, name, shndx,
231da0c48c4Sopenharmony_ci				   elf, false);
232da0c48c4Sopenharmony_ci		}
233da0c48c4Sopenharmony_ci	    }
234da0c48c4Sopenharmony_ci	}
235da0c48c4Sopenharmony_ci}
236da0c48c4Sopenharmony_ci
237da0c48c4Sopenharmony_ci/* Returns the name of the symbol "closest" to ADDR.
238da0c48c4Sopenharmony_ci   Never returns symbols at addresses above ADDR.
239da0c48c4Sopenharmony_ci
240da0c48c4Sopenharmony_ci   Wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo.
241da0c48c4Sopenharmony_ci   adjust_st_value set to true returns adjusted SYM st_value, set to false
242da0c48c4Sopenharmony_ci   it will not adjust SYM at all, but does match against resolved values.   */
243da0c48c4Sopenharmony_cistatic const char *
244da0c48c4Sopenharmony_ci__libdwfl_addrsym (Dwfl_Module *_mod, GElf_Addr _addr, GElf_Off *off,
245da0c48c4Sopenharmony_ci		   GElf_Sym *_closest_sym, GElf_Word *shndxp,
246da0c48c4Sopenharmony_ci		   Elf **elfp, Dwarf_Addr *biasp, bool _adjust_st_value)
247da0c48c4Sopenharmony_ci{
248da0c48c4Sopenharmony_ci  int syments = INTUSE(dwfl_module_getsymtab) (_mod);
249da0c48c4Sopenharmony_ci  if (syments < 0)
250da0c48c4Sopenharmony_ci    return NULL;
251da0c48c4Sopenharmony_ci
252da0c48c4Sopenharmony_ci  struct search_state state =
253da0c48c4Sopenharmony_ci    {
254da0c48c4Sopenharmony_ci      .addr = _addr,
255da0c48c4Sopenharmony_ci      .mod = _mod,
256da0c48c4Sopenharmony_ci      .closest_sym = _closest_sym,
257da0c48c4Sopenharmony_ci      .adjust_st_value = _adjust_st_value,
258da0c48c4Sopenharmony_ci      .addr_shndx = SHN_UNDEF,
259da0c48c4Sopenharmony_ci      .addr_symelf = NULL,
260da0c48c4Sopenharmony_ci      .closest_name = NULL,
261da0c48c4Sopenharmony_ci      .closest_value = 0,
262da0c48c4Sopenharmony_ci      .closest_shndx = SHN_UNDEF,
263da0c48c4Sopenharmony_ci      .closest_elf = NULL,
264da0c48c4Sopenharmony_ci      .sizeless_name = NULL,
265da0c48c4Sopenharmony_ci      .sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF },
266da0c48c4Sopenharmony_ci      .sizeless_value = 0,
267da0c48c4Sopenharmony_ci      .sizeless_shndx = SHN_UNDEF,
268da0c48c4Sopenharmony_ci      .sizeless_elf = NULL,
269da0c48c4Sopenharmony_ci      .min_label = 0
270da0c48c4Sopenharmony_ci    };
271da0c48c4Sopenharmony_ci
272da0c48c4Sopenharmony_ci  /* First go through global symbols.  mod->first_global and
273da0c48c4Sopenharmony_ci     mod->aux_first_global are setup by dwfl_module_getsymtab to the
274da0c48c4Sopenharmony_ci     index of the first global symbol in those symbol tables.  Both
275da0c48c4Sopenharmony_ci     are non-zero when the table exist, except when there is only a
276da0c48c4Sopenharmony_ci     dynsym table loaded through phdrs, then first_global is zero and
277da0c48c4Sopenharmony_ci     there will be no auxiliary table.  All symbols with local binding
278da0c48c4Sopenharmony_ci     come first in the symbol table, then all globals.  The zeroth,
279da0c48c4Sopenharmony_ci     null entry, in the auxiliary table is skipped if there is a main
280da0c48c4Sopenharmony_ci     table.  */
281da0c48c4Sopenharmony_ci  int first_global = INTUSE (dwfl_module_getsymtab_first_global) (state.mod);
282da0c48c4Sopenharmony_ci  if (first_global < 0)
283da0c48c4Sopenharmony_ci    return NULL;
284da0c48c4Sopenharmony_ci  search_table (&state, first_global == 0 ? 1 : first_global, syments);
285da0c48c4Sopenharmony_ci
286da0c48c4Sopenharmony_ci  /* If we found nothing searching the global symbols, then try the locals.
287da0c48c4Sopenharmony_ci     Unless we have a global sizeless symbol that matches exactly.  */
288da0c48c4Sopenharmony_ci  if (state.closest_name == NULL && first_global > 1
289da0c48c4Sopenharmony_ci      && (state.sizeless_name == NULL || state.sizeless_value != state.addr))
290da0c48c4Sopenharmony_ci    search_table (&state, 1, first_global);
291da0c48c4Sopenharmony_ci
292da0c48c4Sopenharmony_ci  /* If we found no proper sized symbol to use, fall back to the best
293da0c48c4Sopenharmony_ci     candidate sizeless symbol we found, if any.  */
294da0c48c4Sopenharmony_ci  if (state.closest_name == NULL
295da0c48c4Sopenharmony_ci      && state.sizeless_name != NULL
296da0c48c4Sopenharmony_ci      && state.sizeless_value >= state.min_label)
297da0c48c4Sopenharmony_ci    {
298da0c48c4Sopenharmony_ci      *state.closest_sym = state.sizeless_sym;
299da0c48c4Sopenharmony_ci      state.closest_value = state.sizeless_value;
300da0c48c4Sopenharmony_ci      state.closest_shndx = state.sizeless_shndx;
301da0c48c4Sopenharmony_ci      state.closest_elf = state.sizeless_elf;
302da0c48c4Sopenharmony_ci      state.closest_name = state.sizeless_name;
303da0c48c4Sopenharmony_ci    }
304da0c48c4Sopenharmony_ci
305da0c48c4Sopenharmony_ci  *off = state.addr - state.closest_value;
306da0c48c4Sopenharmony_ci
307da0c48c4Sopenharmony_ci  if (shndxp != NULL)
308da0c48c4Sopenharmony_ci    *shndxp = state.closest_shndx;
309da0c48c4Sopenharmony_ci  if (elfp != NULL)
310da0c48c4Sopenharmony_ci    *elfp = state.closest_elf;
311da0c48c4Sopenharmony_ci  if (biasp != NULL)
312da0c48c4Sopenharmony_ci    *biasp = dwfl_adjusted_st_value (state.mod, state.closest_elf, 0);
313da0c48c4Sopenharmony_ci  return state.closest_name;
314da0c48c4Sopenharmony_ci}
315da0c48c4Sopenharmony_ci
316da0c48c4Sopenharmony_ci
317da0c48c4Sopenharmony_ciconst char *
318da0c48c4Sopenharmony_cidwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
319da0c48c4Sopenharmony_ci		     GElf_Sym *closest_sym, GElf_Word *shndxp)
320da0c48c4Sopenharmony_ci{
321da0c48c4Sopenharmony_ci  GElf_Off off;
322da0c48c4Sopenharmony_ci  return __libdwfl_addrsym (mod, addr, &off, closest_sym, shndxp,
323da0c48c4Sopenharmony_ci			    NULL, NULL, true);
324da0c48c4Sopenharmony_ci}
325da0c48c4Sopenharmony_ciINTDEF (dwfl_module_addrsym)
326da0c48c4Sopenharmony_ci
327da0c48c4Sopenharmony_ciconst char
328da0c48c4Sopenharmony_ci*dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
329da0c48c4Sopenharmony_ci		       GElf_Off *offset, GElf_Sym *sym,
330da0c48c4Sopenharmony_ci		       GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *bias)
331da0c48c4Sopenharmony_ci{
332da0c48c4Sopenharmony_ci  return __libdwfl_addrsym (mod, address, offset, sym, shndxp, elfp, bias,
333da0c48c4Sopenharmony_ci			    false);
334da0c48c4Sopenharmony_ci}
335da0c48c4Sopenharmony_ciINTDEF (dwfl_module_addrinfo)
336