1eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm/* libunwind - a platform-independent unwind library
21f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm   Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
3eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
5eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmThis file is part of libunwind.
6eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
7eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
8eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidma copy of this software and associated documentation files (the
9eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm"Software"), to deal in the Software without restriction, including
10eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
11eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
12eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
13eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmthe following conditions:
14eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
15eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmThe above copyright notice and this permission notice shall be
16eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmincluded in all copies or substantial portions of the Software.
17eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
18eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
26eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm/* Locate an FDE via the ELF data-structures defined by LSB v1.3
27eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm   (http://www.linuxbase.org/spec/).  */
28eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
29eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#include <stddef.h>
303842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include <stdio.h>
313842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include <limits.h>
32eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
33e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm#include "dwarf_i.h"
34eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#include "dwarf-eh.h"
3503ba50ccaadbf962e9865d60e2171dc8e52ee24ehp.com!davidm#include "libunwind_i.h"
36eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
378241bb15a8ae2484d05238176284c5bed56eed24mostang.com!davidmstruct table_entry
388241bb15a8ae2484d05238176284c5bed56eed24mostang.com!davidm  {
39e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm    int32_t start_ip_offset;
40e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm    int32_t fde_offset;
418241bb15a8ae2484d05238176284c5bed56eed24mostang.com!davidm  };
428241bb15a8ae2484d05238176284c5bed56eed24mostang.com!davidm
43eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#ifndef UNW_REMOTE_ONLY
44eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#ifdef __linux
463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include "os-linux.h"
473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#endif
483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
491f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidmstatic int
501f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidmlinear_search (unw_addr_space_t as, unw_word_t ip,
511f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	       unw_word_t eh_frame_start, unw_word_t eh_frame_end,
521f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	       unw_word_t fde_count,
531f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	       unw_proc_info_t *pi, int need_unwind_info, void *arg)
541f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm{
551f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
561f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  unw_word_t i = 0, fde_addr, addr = eh_frame_start;
571f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  int ret;
581f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
591f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  while (i++ < fde_count && addr < eh_frame_end)
601f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm    {
611f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm      fde_addr = addr;
623842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
631f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  < 0)
641f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	return ret;
651f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
661f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm      if (ip >= pi->start_ip && ip < pi->end_ip)
671f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	{
681f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  if (!need_unwind_info)
691f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	    return 1;
701f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  addr = fde_addr;
711f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
723842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz						       need_unwind_info, 0,
733842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz						       arg))
741f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	      < 0)
751f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	    return ret;
761f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  return 1;
771f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	}
781f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm    }
791f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  return -UNW_ENOINFO;
801f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm}
810fed502a81dd6d9eff4da9ff26d895a16ab828cfKen Werner#endif /* !UNW_REMOTE_ONLY */
821f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
83a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma#ifdef CONFIG_DEBUG_FRAME
843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* Load .debug_frame section from FILE.  Allocates and returns space
853842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   in *BUF, and sets *BUFSIZE to its size.  IS_LOCAL is 1 if using the
863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   local process, in which case we can search the system debug file
873842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   directory; 0 for other address spaces, in which case we do not; or
883842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   -1 for recursive calls following .gnu_debuglink.  Returns 0 on
893842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   success, 1 on error.  Succeeds even if the file contains no
903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   .debug_frame.  */
913842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* XXX: Could use mmap; but elf_map_image keeps tons mapped in.  */
923842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
933842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstatic int
943842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzload_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
953842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{
963842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  FILE *f;
973842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  Elf_W (Ehdr) ehdr;
983842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  Elf_W (Half) shstrndx;
99546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  Elf_W (Shdr) *sec_hdrs = NULL;
100546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  char *stringtab = NULL;
1013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  unsigned int i;
1023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  size_t linksize = 0;
1033842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  char *linkbuf = NULL;
1043842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1053842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  *buf = NULL;
1063842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  *bufsize = 0;
1073842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  f = fopen (file, "r");
1093842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (!f)
1113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    return 1;
1123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
113546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)
114546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    goto file_error;
1153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  shstrndx = ehdr.e_shstrndx;
1173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  Debug (4, "opened file '%s'. Section header at offset %d\n",
1193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz         file, (int) ehdr.e_shoff);
1203842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  fseek (f, ehdr.e_shoff, SEEK_SET);
1223842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
123546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  if (fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum)
124546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    goto file_error;
1253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
126a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma  Debug (4, "loading string table of size %zd\n",
1273842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	   sec_hdrs[shstrndx].sh_size);
1283842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  stringtab = malloc (sec_hdrs[shstrndx].sh_size);
1293842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
130546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
131546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    goto file_error;
1323842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1333842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
1343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
1353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      char *secname = &stringtab[sec_hdrs[i].sh_name];
1363842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1373842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (strcmp (secname, ".debug_frame") == 0)
1383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz        {
1393842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  *bufsize = sec_hdrs[i].sh_size;
1403842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  *buf = malloc (*bufsize);
1413842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1423842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
143546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma	  if (fread (*buf, 1, *bufsize, f) != *bufsize)
144546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma	    goto file_error;
1453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
146a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma	  Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
1473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 *bufsize, sec_hdrs[i].sh_offset);
1483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
149b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma      else if (strcmp (secname, ".gnu_debuglink") == 0)
1503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
1513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  linksize = sec_hdrs[i].sh_size;
1523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  linkbuf = malloc (linksize);
1533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1543842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
155546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma	  if (fread (linkbuf, 1, linksize, f) != linksize)
156546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma	    goto file_error;
1573842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
158a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma	  Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
159b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma		 linksize, sec_hdrs[i].sh_offset);
1603842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
1613842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
1623842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1633842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  free (stringtab);
1643842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  free (sec_hdrs);
1653842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1663842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  fclose (f);
1673842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
168b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma  /* Ignore separate debug files which contain a .gnu_debuglink section. */
169b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma  if (linkbuf && is_local == -1)
170b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma    {
171b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma      free (linkbuf);
172b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma      return 1;
173b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma    }
174b115ab645a44071f0a51742f5804dbceebd3f1acArun Sharma
1753842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
1763842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
1773842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      char *newname, *basedir, *p;
1783842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      static const char *debugdir = "/usr/lib/debug";
1793842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      int ret;
1803842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1813842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      /* XXX: Don't bother with the checksum; just search for the file.  */
1823842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      basedir = malloc (strlen (file) + 1);
1833842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      newname = malloc (strlen (linkbuf) + strlen (debugdir)
1843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz			+ strlen (file) + 9);
1853842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      p = strrchr (file, '/');
1873842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (p != NULL)
1883842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
1893842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  memcpy (basedir, file, p - file);
1903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  basedir[p - file] = '\0';
1913842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
1923842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      else
1933842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	basedir[0] = 0;
1943842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
1953842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      strcpy (newname, basedir);
1963842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      strcat (newname, "/");
1973842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      strcat (newname, linkbuf);
1983842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      ret = load_debug_frame (newname, buf, bufsize, -1);
1993842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2003842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (ret == 1)
2013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
2023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcpy (newname, basedir);
2033842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcat (newname, "/.debug/");
2043842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcat (newname, linkbuf);
2053842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  ret = load_debug_frame (newname, buf, bufsize, -1);
2063842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
2073842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (ret == 1 && is_local == 1)
2093842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
2103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcpy (newname, debugdir);
2113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcat (newname, basedir);
2123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcat (newname, "/");
2133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  strcat (newname, linkbuf);
2143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  ret = load_debug_frame (newname, buf, bufsize, -1);
2153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
2163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      free (basedir);
2183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      free (newname);
2193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
2203842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  free (linkbuf);
2213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2223842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  return 0;
223546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
224546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma/* An error reading image file. Release resources and return error code */
225546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharmafile_error:
22690d7baea352631f93ec7a9688fc59f58f148c19dTommi Rantala  free(stringtab);
22790d7baea352631f93ec7a9688fc59f58f148c19dTommi Rantala  free(sec_hdrs);
22890d7baea352631f93ec7a9688fc59f58f148c19dTommi Rantala  free(linkbuf);
229984761515e6aafe8f27d0fda1151e2f81e2832e0Christopher Ferris  free(*buf);
230546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  fclose(f);
231546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
232546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  return 1;
2333842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
2343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* Locate the binary which originated the contents of address ADDR. Return
236a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma   the name of the binary in *name (space is allocated by the caller)
237a2c27a4ab724cf129cf956df4c6fb779bd2f5366Arun Sharma   Returns 0 if a binary is successfully found, or 1 if an error occurs.  */
2383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
239bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris/* ANDROID support update. */
240bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris/* Removed the find_binary_for_address function. */
241bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris/* End of ANDROID update. */
2423842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2433842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* Locate and/or try to load a debug_frame section for address ADDR.  Return
2443842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   pointer to debug frame descriptor, or zero if not found.  */
2453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstatic struct unw_debug_frame_list *
247059676cb00cfdd3be17dfdeb25547037737f1b68Ken Wernerlocate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
248059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner		   unw_word_t start, unw_word_t end)
2493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{
2503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  struct unw_debug_frame_list *w, *fdesc = 0;
2513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  int err;
2523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  char *buf;
2533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  size_t bufsize;
254bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* ANDROID support update. */
255bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  char *name = NULL;
256bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* End of ANDROID update. */
257cc6cc088ba4077f5b6cfa3931a1737b03fc0446eChristopher Ferris
2583842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  /* First, see if we loaded this frame already.  */
2593842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2603842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  for (w = as->debug_frames; w; w = w->next)
2613842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
262250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura      Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
2633842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (addr >= w->start && addr < w->end)
2643842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	return w;
2653842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
2663842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
267bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* ANDROID support update. */
2683842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  /* If the object name we receive is blank, there's still a chance of locating
269bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris     the file by looking at the maps cache. */
2703842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2713842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (strcmp (dlname, "") == 0)
2723842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
273bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris#ifdef UNW_LOCAL_ONLY
274bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      name = map_local_get_image_name (addr);
275bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris#else
276bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      struct map_info *map = map_find_from_addr (as->map_list, addr);
277bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      if (map)
278bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris        name = strdup (map->path);
279984761515e6aafe8f27d0fda1151e2f81e2832e0Christopher Ferris#endif
280bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      if (!name)
281bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* End of ANDROID update. */
2823842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz        {
2833842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
2843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 (uint64_t) addr);
2853842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz          return 0;
2863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
2873842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
2883842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else
2893842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    name = (char*) dlname;
2903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2913842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
2923842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2933842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (!err)
2943842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
2953842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc = malloc (sizeof (struct unw_debug_frame_list));
2963842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
2973842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->start = start;
2983842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->end = end;
2993842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->debug_frame = buf;
3003842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->debug_frame_size = bufsize;
3013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->index = NULL;
3023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      fdesc->next = as->debug_frames;
3033842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3043842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      as->debug_frames = fdesc;
3053842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
306984761515e6aafe8f27d0fda1151e2f81e2832e0Christopher Ferris
307bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* ANDROID support update. */
308bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  if (name != dlname)
309bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris    free(name);
310bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  /* End of ANDROID update. */
311984761515e6aafe8f27d0fda1151e2f81e2832e0Christopher Ferris
3123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  return fdesc;
3133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
3143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstruct debug_frame_tab
3163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  {
3173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    struct table_entry *tab;
3183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    uint32_t length;
3193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    uint32_t size;
3203842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  };
3213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3223842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstatic void
3233842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzdebug_frame_tab_append (struct debug_frame_tab *tab,
3243842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz			unw_word_t fde_offset, unw_word_t start_ip)
3253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{
3263842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  unsigned int length = tab->length;
3273842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3283842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (length == tab->size)
3293842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
3303842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      tab->size *= 2;
3313842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
3323842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
3333842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  tab->tab[length].fde_offset = fde_offset;
3353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  tab->tab[length].start_ip_offset = start_ip;
3363842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3373842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  tab->length = length + 1;
3383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
3393842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3403842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstatic void
3413842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzdebug_frame_tab_shrink (struct debug_frame_tab *tab)
3423842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{
3433842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (tab->size > tab->length)
3443842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
3453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
3463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      tab->size = tab->length;
3473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
3483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
3493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzstatic int
3513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzdebug_frame_tab_compare (const void *a, const void *b)
3523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{
3533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  const struct table_entry *fa = a, *fb = b;
3543842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
3553842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (fa->start_ip_offset > fb->start_ip_offset)
3563842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    return 1;
3573842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else if (fa->start_ip_offset < fb->start_ip_offset)
3583842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    return -1;
3593842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else
3603842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    return 0;
3613842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
3623842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
363546463d1e78d52197ff2c204f793c343abb97dc5Arun SharmaPROTECTED int
364059676cb00cfdd3be17dfdeb25547037737f1b68Ken Wernerdwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
365059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner			unw_word_t segbase, const char* obj_name,
366059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner			unw_word_t start, unw_word_t end)
367546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma{
368546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  unw_dyn_info_t *di;
369546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  struct unw_debug_frame_list *fdesc = 0;
370546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  unw_accessors_t *a;
371546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  unw_word_t addr;
372546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
373059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
374546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  di = di_debug;
375546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
376059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
377546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
378546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  if (!fdesc)
379546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    {
380546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      Debug (15, "couldn't load .debug_frame\n");
381546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      return found;
382546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    }
383546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  else
384546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    {
385546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      char *buf;
386546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      size_t bufsize;
387546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      unw_word_t item_start, item_end = 0;
388546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      uint32_t u32val = 0;
389546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      uint64_t cie_id = 0;
390fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala      struct debug_frame_tab tab;
391546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
392546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      Debug (15, "loaded .debug_frame\n");
393546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
394546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      buf = fdesc->debug_frame;
395546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      bufsize = fdesc->debug_frame_size;
396546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
397546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      if (bufsize == 0)
398546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma       {
399546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         Debug (15, "zero-length .debug_frame\n");
400546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         return found;
401546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma       }
402546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
403546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      /* Now create a binary-search table, if it does not already exist.  */
404546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      if (!fdesc->index)
405546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma       {
406546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         addr = (unw_word_t) (uintptr_t) buf;
407546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
408546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         a = unw_get_accessors (unw_local_addr_space);
409546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
410546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         /* Find all FDE entries in debug_frame, and make into a sorted
411546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            index.  */
412546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
413fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         tab.length = 0;
414fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         tab.size = 16;
415fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         tab.tab = calloc (tab.size, sizeof (struct table_entry));
416546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
417546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma         while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
418546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma           {
419546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             uint64_t id_for_cie;
420546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             item_start = addr;
421546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
422546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
423546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
424546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             if (u32val == 0)
425546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               break;
426546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             else if (u32val != 0xffffffff)
427546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               {
428546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 uint32_t cie_id32 = 0;
429546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 item_end = addr + u32val;
430546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
431546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                NULL);
432546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 cie_id = cie_id32;
433546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 id_for_cie = 0xffffffff;
434546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               }
435546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             else
436546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               {
437546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 uint64_t u64val = 0;
438546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 /* Extended length.  */
439546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
440546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 item_end = addr + u64val;
441546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
442546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
443546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 id_for_cie = 0xffffffffffffffffull;
444546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               }
445546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
446546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
447546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
448546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             if (cie_id == id_for_cie)
449546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               ;
450546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
451546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             else
452546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               {
453546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 unw_word_t fde_addr = item_start;
454546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 unw_proc_info_t this_pi;
455546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 int err;
456546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
457546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 /*Debug (1, "Found FDE at %.8x\n", item_start);*/
458546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
459546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
460546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                                         a, &fde_addr,
461546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                                         &this_pi, 0,
462546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                                         (uintptr_t) buf,
463546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                                         NULL);
464546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 if (err == 0)
465546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                   {
466546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                     Debug (15, "start_ip = %lx, end_ip = %lx\n",
467546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                            (long) this_pi.start_ip, (long) this_pi.end_ip);
468fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala                     debug_frame_tab_append (&tab,
469546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                             item_start - (unw_word_t) (uintptr_t) buf,
470546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                                             this_pi.start_ip);
471546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                   }
472546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                 /*else
473546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                   Debug (1, "FDE parse failed\n");*/
474546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma               }
475546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
476546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma             addr = item_end;
477546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma           }
478546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
479fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         debug_frame_tab_shrink (&tab);
480fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         qsort (tab.tab, tab.length, sizeof (struct table_entry),
481546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma                debug_frame_tab_compare);
482fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         /* for (i = 0; i < tab.length; i++)
483546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            {
484546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            fprintf (stderr, "ip %x, fde offset %x\n",
485fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala            (int) tab.tab[i].start_ip_offset,
486fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala            (int) tab.tab[i].fde_offset);
487546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            }*/
488fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         fdesc->index = tab.tab;
489fce25d74c93e897439e5183fea7d8dbaf55848feTommi Rantala         fdesc->index_size = tab.length;
490546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma       }
491546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
492546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      di->format = UNW_INFO_FORMAT_TABLE;
493546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      di->start_ip = fdesc->start;
494546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      di->end_ip = fdesc->end;
495059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner      di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
496546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      di->u.ti.table_data = (unw_word_t *) fdesc;
497546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
498059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner      di->u.ti.segbase = segbase;
499546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
500546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      found = 1;
501546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma      Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
502546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            "gp=0x%lx, table_data=0x%lx\n",
503546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            (char *) (uintptr_t) di->u.ti.name_ptr,
504546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            (long) di->u.ti.segbase, (long) di->u.ti.table_len,
505546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma            (long) di->gp, (long) di->u.ti.table_data);
506546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma    }
507546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma  return found;
508546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma}
509546463d1e78d52197ff2c204f793c343abb97dc5Arun Sharma
510b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov#endif /* CONFIG_DEBUG_FRAME */
511b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov
5120fed502a81dd6d9eff4da9ff26d895a16ab828cfKen Werner#ifndef UNW_REMOTE_ONLY
5130fed502a81dd6d9eff4da9ff26d895a16ab828cfKen Werner
5140b9f591823474c9651acdffec68256e077e4d601Ken Werner/* ptr is a pointer to a dwarf_callback_data structure and, on entry,
5153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz   member ip contains the instruction-pointer we're looking
516eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm   for.  */
5170b9f591823474c9651acdffec68256e077e4d601Ken WernerHIDDEN int
5180b9f591823474c9651acdffec68256e077e4d601Ken Wernerdwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
519eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
5200b9f591823474c9651acdffec68256e077e4d601Ken Werner  struct dwarf_callback_data *cb_data = ptr;
5211f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  unw_dyn_info_t *di = &cb_data->di;
522eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
5231e644990c9afe9054ba7693929139f298cb3e53aKen Werner  unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
524786882ff8c0d1317558a4a805b2be319e64cb6a9Arun Sharma  Elf_W(Addr) load_base, max_load_addr = 0;
5251f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  int ret, need_unwind_info = cb_data->need_unwind_info;
5261f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  unw_proc_info_t *pi = cb_data->pi;
527eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  struct dwarf_eh_frame_hdr *hdr;
528eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unw_accessors_t *a;
529eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  long n;
5303842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  int found = 0;
5311e644990c9afe9054ba7693929139f298cb3e53aKen Werner#ifdef CONFIG_DEBUG_FRAME
5321e644990c9afe9054ba7693929139f298cb3e53aKen Werner  unw_word_t start, end;
5331e644990c9afe9054ba7693929139f298cb3e53aKen Werner#endif /* CONFIG_DEBUG_FRAME*/
534eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
5351f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  ip = cb_data->ip;
5361f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
537eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  /* Make sure struct dl_phdr_info is at least as big as we need.  */
538eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
539eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	     + sizeof (info->dlpi_phnum))
540eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    return -1;
541eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
542e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm  Debug (15, "checking %s, base=0x%lx)\n",
543eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	 info->dlpi_name, (long) info->dlpi_addr);
544eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
545eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  phdr = info->dlpi_phdr;
546eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  load_base = info->dlpi_addr;
547eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  p_text = NULL;
548eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  p_eh_hdr = NULL;
549eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  p_dynamic = NULL;
550eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
551eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  /* See if PC falls into one of the loaded segments.  Find the
552eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm     eh-header segment at the same time.  */
553eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  for (n = info->dlpi_phnum; --n >= 0; phdr++)
554eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
555eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      if (phdr->p_type == PT_LOAD)
556eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	{
557eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	  Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
5581f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
5591f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
560eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	    p_text = phdr;
5611f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
5621f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	  if (vaddr + phdr->p_filesz > max_load_addr)
5631f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm	    max_load_addr = vaddr + phdr->p_filesz;
564eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	}
565eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      else if (phdr->p_type == PT_GNU_EH_FRAME)
566eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	p_eh_hdr = phdr;
567eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      else if (phdr->p_type == PT_DYNAMIC)
568eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	p_dynamic = phdr;
569eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
5703842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
5713842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (!p_text)
572eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    return 0;
573eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
5743842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (p_eh_hdr)
575eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
5763842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (p_dynamic)
5773842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
5783842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  /* For dynamicly linked executables and shared libraries,
5793842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	     DT_PLTGOT is the value that data-relative addresses are
5803842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	     relative to for that object.  We call this the "gp".  */
5813842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
5823842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  for (; dyn->d_tag != DT_NULL; ++dyn)
5833842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	    if (dyn->d_tag == DT_PLTGOT)
5843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	      {
5853842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		/* Assume that _DYNAMIC is writable and GLIBC has
5863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		   relocated it (true for x86 at least).  */
5873842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		di->gp = dyn->d_un.d_ptr;
5883842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		break;
5893842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	      }
5903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
5913842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      else
5923842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	/* Otherwise this is a static executable with no _DYNAMIC.  Assume
5933842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	   that data-relative addresses are relative to 0, i.e.,
5943842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	   absolute.  */
5953842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	di->gp = 0;
5963842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      pi->gp = di->gp;
5973842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
5983842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
5993842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (hdr->version != DW_EH_VERSION)
6003842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
6013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  Debug (1, "table `%s' has unexpected version %d\n",
6023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 info->dlpi_name, hdr->version);
6033842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  return 0;
6043842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
6053842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6063842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      a = unw_get_accessors (unw_local_addr_space);
6073842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      addr = (unw_word_t) (uintptr_t) (hdr + 1);
6083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6093842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      /* (Optionally) read eh_frame_ptr: */
6103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
6113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					     &addr, hdr->eh_frame_ptr_enc, pi,
6123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					     &eh_frame_start, NULL)) < 0)
6133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	return ret;
6143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      /* (Optionally) read fde_count: */
6163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
6173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					     &addr, hdr->fde_count_enc, pi,
6183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					     &fde_count, NULL)) < 0)
6193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	return ret;
6203842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
6223842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
6233842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  /* If there is no search table or it has an unsupported
6243842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	     encoding, fall back on linear search.  */
6253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  if (hdr->table_enc == DW_EH_PE_omit)
626bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* ANDROID support update. */
627bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	    {
628bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* End of ANDROID update. */
629bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	      Debug (4, "table `%s' lacks search table; doing linear search\n",
630bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris		     info->dlpi_name);
631bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* ANDROID support update. */
632bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	    }
633bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* End of ANDROID update. */
6343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  else
635bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* ANDROID support update. */
636bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	    {
637bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* End of ANDROID update. */
638bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	      Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
639bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris		     info->dlpi_name, hdr->table_enc);
640bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* ANDROID support update. */
641bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris	    }
642bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris            /* End of ANDROID update. */
6433842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6443842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  eh_frame_end = max_load_addr;	/* XXX can we do better? */
6453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  if (hdr->fde_count_enc == DW_EH_PE_omit)
6473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	    fde_count = ~0UL;
6483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
6493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	    abort ();
6503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  /* XXX we know how to build a local binary search table for
6523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	     .debug_frame, so we could do that here too.  */
6533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  cb_data->single_fde = 1;
6543842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  found = linear_search (unw_local_addr_space, ip,
6553842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz				 eh_frame_start, eh_frame_end, fde_count,
6563842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz				 pi, need_unwind_info, NULL);
6573842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  if (found != 1)
6583842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	    found = 0;
6593842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
6603842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      else
6613842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	{
6623842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
6633842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->start_ip = p_text->p_vaddr + load_base;
6643842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
6653842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
6663842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->u.rti.table_data = addr;
6673842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
6683842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
6693842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz				 / sizeof (unw_word_t));
6703842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  /* For the binary-search table in the eh_frame_hdr, data-relative
6713842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	     means relative to the start of that section... */
6723842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
6733842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
6743842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  found = 1;
6753842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
6763842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
6773842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 (long) di->u.rti.segbase, (long) di->u.rti.table_len,
6783842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz		 (long) di->gp, (long) di->u.rti.table_data);
6793842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	}
680eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
681eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
682b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov#ifdef CONFIG_DEBUG_FRAME
683059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  /* Find the start/end of the described region by parsing the phdr_info
684059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner     structure.  */
685059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  start = (unw_word_t) -1;
686059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  end = 0;
687059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner
688059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  for (n = 0; n < info->dlpi_phnum; n++)
689059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner    {
690059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner      if (info->dlpi_phdr[n].p_type == PT_LOAD)
691059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner        {
692059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	  unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
693059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner          unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
694059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner
695059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	  if (seg_start < start)
696059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	    start = seg_start;
697059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner
698059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	  if (seg_end > end)
699059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	    end = seg_end;
700059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner	}
701059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner    }
702059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner
703059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner  found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
704059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner				  info->dlpi_addr, info->dlpi_name, start,
705059676cb00cfdd3be17dfdeb25547037737f1b68Ken Werner				  end);
706b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov#endif  /* CONFIG_DEBUG_FRAME */
7071f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
7083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  return found;
709eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
710eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
711eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmHIDDEN int
712eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmdwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
713eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm		      unw_proc_info_t *pi, int need_unwind_info, void *arg)
714eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
7150b9f591823474c9651acdffec68256e077e4d601Ken Werner  struct dwarf_callback_data cb_data;
7161f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  intrmask_t saved_mask;
717d3fad3af128215bbf3b39b289ff396a2126a12b1mostang.com!davidm  int ret;
718eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
719eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  Debug (14, "looking for IP=0x%lx\n", (long) ip);
720eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
7213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  memset (&cb_data, 0, sizeof (cb_data));
7221f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  cb_data.ip = ip;
7231f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  cb_data.pi = pi;
7241f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  cb_data.need_unwind_info = need_unwind_info;
7253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  cb_data.di.format = -1;
7263842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  cb_data.di_debug.format = -1;
7271f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
728fc2934aadeff468b751113d56093429fd6bc4832Paul Pluzhnikov  SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
7290b9f591823474c9651acdffec68256e077e4d601Ken Werner  ret = dl_iterate_phdr (dwarf_callback, &cb_data);
730fc2934aadeff468b751113d56093429fd6bc4832Paul Pluzhnikov  SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
731d3fad3af128215bbf3b39b289ff396a2126a12b1mostang.com!davidm
732d3fad3af128215bbf3b39b289ff396a2126a12b1mostang.com!davidm  if (ret <= 0)
733eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
734eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      Debug (14, "IP=0x%lx not found\n", (long) ip);
735eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      return -UNW_ENOINFO;
736eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
737eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
7381f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  if (cb_data.single_fde)
7391f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm    /* already got the result in *pi */
7401f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm    return 0;
7413842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
7423842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  /* search the table: */
7433842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (cb_data.di.format != -1)
7443842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
7451f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm				      pi, need_unwind_info, arg);
7463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else
7473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    ret = -UNW_ENOINFO;
7483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
7493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
7503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
7513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz				     need_unwind_info, arg);
7523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  return ret;
753eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
754eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
755eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmstatic inline const struct table_entry *
7563842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzlookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
757eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
758eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unsigned long table_len = table_size / sizeof (struct table_entry);
759890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala  const struct table_entry *e = NULL;
760eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unsigned long lo, hi, mid;
761eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
762eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  /* do a binary search for right entry: */
763eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  for (lo = 0, hi = table_len; lo < hi;)
764eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
765eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      mid = (lo + hi) / 2;
766eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      e = table + mid;
76743e5ee28c00813fb53f6642304b33a49b70b6d62Arun Sharma      Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
768eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      if (rel_ip < e->start_ip_offset)
769eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	hi = mid;
770eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      else
771271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky	lo = mid + 1;
772eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
773271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  if (hi <= 0)
774271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky	return NULL;
775271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  e = table + hi - 1;
776271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  return e;
777eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
778eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
779eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#endif /* !UNW_REMOTE_ONLY */
780eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
781eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#ifndef UNW_LOCAL_ONLY
782eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
783eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm/* Lookup an unwind-table entry in remote memory.  Returns 1 if an
784eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm   entry is found, 0 if no entry is found, negative if an error
785eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm   occurred reading remote memory.  */
786eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmstatic int
787eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmremote_lookup (unw_addr_space_t as,
788271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky	       unw_word_t table, size_t table_size, int32_t rel_ip,
789eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	       struct table_entry *e, void *arg)
790eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
791eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unsigned long table_len = table_size / sizeof (struct table_entry);
792eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unw_accessors_t *a = unw_get_accessors (as);
793eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unsigned long lo, hi, mid;
794e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm  unw_word_t e_addr = 0;
795271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  int32_t start;
796eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  int ret;
797eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
798eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  /* do a binary search for right entry: */
799eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  for (lo = 0, hi = table_len; lo < hi;)
800eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
801eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      mid = (lo + hi) / 2;
802eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      e_addr = table + mid * sizeof (struct table_entry);
803e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm      if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
804eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	return ret;
805eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
806eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      if (rel_ip < start)
807eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	hi = mid;
808eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      else
809271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky	lo = mid + 1;
810eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
811271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  if (hi <= 0)
812eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    return 0;
813271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  e_addr = table + (hi - 1) * sizeof (struct table_entry);
814271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky  if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
815271f7069440b03152a957b5a79abb12e5f2bd605com[davidm]!marky   || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0)
816eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    return ret;
817eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  return 1;
818eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
819eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
820e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm#endif /* !UNW_LOCAL_ONLY */
821eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
82221595821bfe3b1a5b353d92104b14812242c58behp.com!davidmPROTECTED int
823eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmdwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
824eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm			   unw_dyn_info_t *di, unw_proc_info_t *pi,
825eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm			   int need_unwind_info, void *arg)
826eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
8273842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  const struct table_entry *e = NULL, *table;
828eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unw_word_t segbase = 0, fde_addr;
829eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  unw_accessors_t *a;
830eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#ifndef UNW_LOCAL_ONLY
831eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  struct table_entry ent;
832eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#endif
8331f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  int ret;
8343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  unw_word_t debug_frame_base;
8353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  size_t table_len;
836eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
8373842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#ifdef UNW_REMOTE_ONLY
8383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
8393842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#else
840eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
8413842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  || di->format == UNW_INFO_FORMAT_TABLE);
8423842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#endif
8433842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  assert (ip >= di->start_ip && ip < di->end_ip);
8443842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
8453842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE)
8463842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
8473842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
8483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      table_len = di->u.rti.table_len * sizeof (unw_word_t);
8493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      debug_frame_base = 0;
8503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
8513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else
8523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
8533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#ifndef UNW_REMOTE_ONLY
8543842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
8553842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
85646e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma      /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
85746e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma         space.  Both the index and the unwind tables live in local memory, but
85846e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma         the address space to check for properties like the address size and
85946e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma         endianness is the target one.  */
86046e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma      as = unw_local_addr_space;
8613842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      table = fdesc->index;
8623842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      table_len = fdesc->index_size * sizeof (struct table_entry);
8633842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      debug_frame_base = (uintptr_t) fdesc->debug_frame;
8643842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#endif
8653842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
866eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
867eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  a = unw_get_accessors (as);
868eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
869eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#ifndef UNW_REMOTE_ONLY
870eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  if (as == unw_local_addr_space)
871eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
872eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      segbase = di->u.rti.segbase;
8733842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      e = lookup (table, table_len, ip - segbase);
874eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
875eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  else
876eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#endif
877eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
878eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#ifndef UNW_LOCAL_ONLY
879eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      segbase = di->u.rti.segbase;
8803842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
881eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm				ip - segbase, &ent, arg)) < 0)
882eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	return ret;
883eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      if (ret)
884eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	e = &ent;
885eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      else
886eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	e = NULL;	/* no info found */
887eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm#endif
888eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
889eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  if (!e)
890eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    {
891250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura      Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
892250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura	     (long) ip, (long) di->start_ip, (long) di->end_ip);
893eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      /* IP is inside this table's range, but there is no explicit
894eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm	 unwind info.  */
895eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm      return -UNW_ENOINFO;
896eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm    }
897e9045e3cca8cbffbb449bf544bea7263b4701b47homeip.net!davidm  Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
8983842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	 (long) ip, (long) (e->start_ip_offset));
8993842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (debug_frame_base)
9003842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    fde_addr = e->fde_offset + debug_frame_base;
9013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  else
9023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    fde_addr = e->fde_offset + segbase;
903250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura  Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
904250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura	    "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
905250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura	    (long) debug_frame_base, (long) fde_addr);
9061f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
9073842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					       need_unwind_info,
9083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz					       debug_frame_base, arg)) < 0)
9091f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm    return ret;
9101f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
9113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  /* .debug_frame uses an absolute encoding that does not know about any
9123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz     shared library relocation.  */
9133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  if (di->format == UNW_INFO_FORMAT_TABLE)
9143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    {
9153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      pi->start_ip += segbase;
9163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      pi->end_ip += segbase;
91746e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma      pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
9183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    }
9193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
9201f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  if (ip < pi->start_ip || ip >= pi->end_ip)
921d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris    {
922d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris      /* ANDROID support update. */
923d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris      if (need_unwind_info && pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
924d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris        {
925d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris          /* Free the memory used if the call fails. Otherwise, when there
926d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris           * is a mix of dwarf and other unwind data, the memory allocated
927d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris           * will be leaked.
928d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris           */
929d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris          mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
930d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris          pi->unwind_info = NULL;
931d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris        }
932d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris      /* End of ANDROID support update. */
933d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris      return -UNW_ENOINFO;
934d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris    }
9351f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm
9361f5ac0f5bd569a99e29b2de36f5600107503399emostang.com!davidm  return 0;
937eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
938eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm
939eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmHIDDEN void
940eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidmdwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
941eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm{
942eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm  return;	/* always a nop */
943eb51b4294aa18ab13c9496378abb25162688235bhp.com!davidm}
944