Home | History | Annotate | Download | only in dwarf
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
      3 	Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4 
      5 This file is part of libunwind.
      6 
      7 Permission is hereby granted, free of charge, to any person obtaining
      8 a copy of this software and associated documentation files (the
      9 "Software"), to deal in the Software without restriction, including
     10 without limitation the rights to use, copy, modify, merge, publish,
     11 distribute, sublicense, and/or sell copies of the Software, and to
     12 permit persons to whom the Software is furnished to do so, subject to
     13 the following conditions:
     14 
     15 The above copyright notice and this permission notice shall be
     16 included in all copies or substantial portions of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     25 
     26 /* Locate an FDE via the ELF data-structures defined by LSB v1.3
     27    (http://www.linuxbase.org/spec/).  */
     28 
     29 #include <stddef.h>
     30 #include <stdio.h>
     31 #include <limits.h>
     32 
     33 #include "dwarf_i.h"
     34 #include "dwarf-eh.h"
     35 #include "libunwind_i.h"
     36 
     37 struct table_entry
     38   {
     39     int32_t start_ip_offset;
     40     int32_t fde_offset;
     41   };
     42 
     43 #ifndef UNW_REMOTE_ONLY
     44 
     45 #ifdef __linux
     46 #include "os-linux.h"
     47 #endif
     48 
     49 static int
     50 linear_search (unw_addr_space_t as, unw_word_t ip,
     51 	       unw_word_t eh_frame_start, unw_word_t eh_frame_end,
     52 	       unw_word_t fde_count,
     53 	       unw_proc_info_t *pi, int need_unwind_info, void *arg)
     54 {
     55   unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
     56   unw_word_t i = 0, fde_addr, addr = eh_frame_start;
     57   int ret;
     58 
     59   while (i++ < fde_count && addr < eh_frame_end)
     60     {
     61       fde_addr = addr;
     62       if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg))
     63 	  < 0)
     64 	return ret;
     65 
     66       if (ip >= pi->start_ip && ip < pi->end_ip)
     67 	{
     68 	  if (!need_unwind_info)
     69 	    return 1;
     70 	  addr = fde_addr;
     71 	  if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
     72 						       need_unwind_info, 0,
     73 						       arg))
     74 	      < 0)
     75 	    return ret;
     76 	  return 1;
     77 	}
     78     }
     79   return -UNW_ENOINFO;
     80 }
     81 #endif /* !UNW_REMOTE_ONLY */
     82 
     83 #ifdef CONFIG_DEBUG_FRAME
     84 /* Load .debug_frame section from FILE.  Allocates and returns space
     85    in *BUF, and sets *BUFSIZE to its size.  IS_LOCAL is 1 if using the
     86    local process, in which case we can search the system debug file
     87    directory; 0 for other address spaces, in which case we do not; or
     88    -1 for recursive calls following .gnu_debuglink.  Returns 0 on
     89    success, 1 on error.  Succeeds even if the file contains no
     90    .debug_frame.  */
     91 /* XXX: Could use mmap; but elf_map_image keeps tons mapped in.  */
     92 
     93 static int
     94 load_debug_frame (const char *file, char **buf, size_t *bufsize,
     95                   int is_local, Elf_W(Addr)* segbase_bias)
     96 {
     97   FILE *f;
     98   Elf_W (Ehdr) ehdr;
     99   Elf_W (Half) shstrndx;
    100   Elf_W (Shdr) *sec_hdrs = NULL;
    101   char *stringtab = NULL;
    102   unsigned int i;
    103   size_t linksize = 0;
    104   char *linkbuf = NULL;
    105 
    106   *buf = NULL;
    107   *bufsize = 0;
    108 
    109   f = fopen (file, "r");
    110 
    111   if (!f)
    112     return 1;
    113 
    114   if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)
    115     goto file_error;
    116 
    117   /* Verify this is actually an elf file. */
    118   if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0)
    119     goto file_error;
    120 
    121   shstrndx = ehdr.e_shstrndx;
    122 
    123   Debug (4, "opened file '%s'. Section header at offset %d\n",
    124          file, (int) ehdr.e_shoff);
    125 
    126   fseek (f, ehdr.e_shoff, SEEK_SET);
    127   sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
    128   if (sec_hdrs == NULL || fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum
    129       || shstrndx >= ehdr.e_shnum)
    130     goto file_error;
    131 
    132   Debug (4, "loading string table of size %ld\n",
    133 	   (long) sec_hdrs[shstrndx].sh_size);
    134   size_t sec_size = sec_hdrs[shstrndx].sh_size;
    135   stringtab = malloc (sec_size);
    136   fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
    137   if (stringtab == NULL || fread (stringtab, 1, sec_size, f) != sec_size)
    138     goto file_error;
    139 
    140   for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
    141     {
    142       size_t sec_position = sec_hdrs[i].sh_name;
    143       if (sec_position >= sec_size)
    144         continue;
    145       char *secname = &stringtab[sec_position];
    146 
    147       if (sec_position + sizeof(".debug_frame") <= sec_size
    148           && strcmp (secname, ".debug_frame") == 0)
    149         {
    150 	  *bufsize = sec_hdrs[i].sh_size;
    151 	  *buf = malloc (*bufsize);
    152 	  fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
    153 	  if (*buf == NULL || fread (*buf, 1, *bufsize, f) != *bufsize)
    154 	    goto file_error;
    155 
    156 	  Debug (4, "read %zd bytes of .debug_frame from offset %ld\n",
    157 		 *bufsize, (long) sec_hdrs[i].sh_offset);
    158 	}
    159       else if (sec_position + sizeof(".gnu_debuglink") <= sec_size
    160           && strcmp (secname, ".gnu_debuglink") == 0)
    161 	{
    162 	  linksize = sec_hdrs[i].sh_size;
    163 	  linkbuf = malloc (linksize);
    164 	  fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
    165 	  if (linkbuf == NULL || fread (linkbuf, 1, linksize, f) != linksize)
    166 	    goto file_error;
    167 
    168 	  Debug (4, "read %zd bytes of .gnu_debuglink from offset %ld\n",
    169 		 linksize, (long) sec_hdrs[i].sh_offset);
    170 	}
    171     /* ANDROID support update. */
    172       // Do not process the compressed section for local unwinds.
    173       // Uncompressing this section can consume a large amount of memory
    174       // and cause the unwind to take longer, which can cause problems
    175       // when an ANR occurs in the system. Compressed sections are
    176       // only used to contain java stack trace information. Since ART is
    177       // one of the only ways that a local trace is done, and it already
    178       // dumps the java stack, this information is redundant.
    179       else if (local_map_list == NULL
    180           && sec_position + sizeof(".gnu_debugdata") <= sec_size
    181           && strcmp (secname, ".gnu_debugdata") == 0)
    182         {
    183           size_t xz_size = sec_hdrs[i].sh_size;
    184           uint8_t* xz_data = malloc (xz_size);
    185           struct elf_image mdi;
    186           if (xz_data == NULL)
    187             goto file_error;
    188           fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
    189           if (fread (xz_data, 1, xz_size, f) != xz_size) {
    190             free(xz_data);
    191             goto file_error;
    192           }
    193           Debug (4, "read %zd bytes of .gnu_debugdata from offset %ld\n",
    194                  xz_size, (long) sec_hdrs[i].sh_offset);
    195           if (elf_w (xz_decompress) (xz_data, xz_size,
    196                                      (uint8_t**)&mdi.u.mapped.image, &mdi.u.mapped.size)) {
    197             uint8_t* found_section;
    198             Elf_W(Addr) old_text_vaddr, new_text_vaddr;
    199             mdi.valid = elf_w (valid_object_mapped) (&mdi);
    200             mdi.mapped = true;
    201             Debug (4, "decompressed .gnu_debugdata\n");
    202             if (elf_w (find_section_mapped) (&mdi, ".debug_frame", &found_section, bufsize, NULL)) {
    203               Debug (4, "found .debug_frame in .gnu_debugdata\n");
    204               *buf = malloc (*bufsize);
    205               if (*buf == NULL) {
    206                 free(xz_data);
    207                 free(mdi.u.mapped.image);
    208                 goto file_error;
    209               }
    210               memcpy(*buf, found_section, *bufsize);
    211               // The ELF file might have been relocated since .gnu_debugdata was created.
    212               if (elf_w (find_section_mapped) (&mdi, ".text", NULL, NULL, &old_text_vaddr)) {
    213                 int j;
    214                 for (j = 1; j < ehdr.e_shnum; j++) {
    215                   if (sec_hdrs[j].sh_name + sizeof(".text") <= sec_size
    216                       && strcmp(&stringtab[sec_hdrs[j].sh_name], ".text") == 0) {
    217                     new_text_vaddr = sec_hdrs[j].sh_addr;
    218                     *segbase_bias = new_text_vaddr - old_text_vaddr;
    219                     Debug (4, "ELF file was relocated by 0x%llx bytes since it was created.\n",
    220                            (unsigned long long)*segbase_bias);
    221                     break;
    222                   }
    223                 }
    224               }
    225             } else {
    226               Debug (1, "can not find .debug_frame inside .gnu_debugdata\n");
    227             }
    228             free(mdi.u.mapped.image);
    229           } else {
    230             Debug (1, "failed to decompress .gnu_debugdata\n");
    231           }
    232           free(xz_data);
    233         }
    234   /* End of ANDROID update. */
    235     }
    236 
    237   free (stringtab);
    238   free (sec_hdrs);
    239 
    240   fclose (f);
    241 
    242   /* Ignore separate debug files which contain a .gnu_debuglink section. */
    243   if (linkbuf && is_local == -1)
    244     {
    245       free (linkbuf);
    246       return 1;
    247     }
    248 
    249   if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
    250     {
    251       char *newname, *basedir, *p;
    252       static const char *debugdir = "/usr/lib/debug";
    253       int ret;
    254 
    255       /* XXX: Don't bother with the checksum; just search for the file.  */
    256       basedir = malloc (strlen (file) + 1);
    257       newname = malloc (strlen (linkbuf) + strlen (debugdir)
    258 			+ strlen (file) + 9);
    259       if (basedir == NULL || newname == NULL)
    260         goto file_error;
    261 
    262       p = strrchr (file, '/');
    263       if (p != NULL)
    264 	{
    265 	  memcpy (basedir, file, p - file);
    266 	  basedir[p - file] = '\0';
    267 	}
    268       else
    269 	basedir[0] = 0;
    270 
    271       strcpy (newname, basedir);
    272       strcat (newname, "/");
    273       strcat (newname, linkbuf);
    274       ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias);
    275 
    276       if (ret == 1)
    277 	{
    278 	  strcpy (newname, basedir);
    279 	  strcat (newname, "/.debug/");
    280 	  strcat (newname, linkbuf);
    281 	  ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias);
    282 	}
    283 
    284       if (ret == 1 && is_local == 1)
    285 	{
    286 	  strcpy (newname, debugdir);
    287 	  strcat (newname, basedir);
    288 	  strcat (newname, "/");
    289 	  strcat (newname, linkbuf);
    290 	  ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias);
    291 	}
    292 
    293       free (basedir);
    294       free (newname);
    295     }
    296   free (linkbuf);
    297 
    298   return 0;
    299 
    300 /* An error reading image file. Release resources and return error code */
    301 file_error:
    302   free(stringtab);
    303   free(sec_hdrs);
    304   free(linkbuf);
    305   free(*buf);
    306   fclose(f);
    307 
    308   return 1;
    309 }
    310 
    311 /* Locate the binary which originated the contents of address ADDR. Return
    312    the name of the binary in *name (space is allocated by the caller)
    313    Returns 0 if a binary is successfully found, or 1 if an error occurs.  */
    314 
    315 /* ANDROID support update. */
    316 /* Removed the find_binary_for_address function. */
    317 /* End of ANDROID update. */
    318 
    319 /* Locate and/or try to load a debug_frame section for address ADDR.  Return
    320    pointer to debug frame descriptor, or zero if not found.  */
    321 
    322 static struct unw_debug_frame_list *
    323 locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
    324 		   unw_word_t start, unw_word_t end)
    325 {
    326   struct unw_debug_frame_list *w, *fdesc = 0;
    327   int err;
    328   char *buf;
    329   size_t bufsize;
    330   /* ANDROID support update. */
    331   char *name = NULL;
    332   Elf_W(Addr) segbase_bias = 0;
    333   /* End of ANDROID update. */
    334 
    335   /* First, see if we loaded this frame already.  */
    336 
    337   for (w = as->debug_frames; w; w = w->next)
    338     {
    339       Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
    340       if (addr >= w->start && addr < w->end)
    341 	return w;
    342     }
    343 
    344   /* ANDROID support update. */
    345   /* If the object name we receive is blank, there's still a chance of locating
    346      the file by looking at the maps cache. */
    347 
    348   if (strcmp (dlname, "") == 0)
    349     {
    350 #ifdef UNW_LOCAL_ONLY
    351       name = map_local_get_image_name (addr);
    352 #else
    353       struct map_info *map = map_find_from_addr (as->map_list, addr);
    354       if (map)
    355         name = strdup (map->path);
    356 #endif
    357       if (!name)
    358   /* End of ANDROID update. */
    359         {
    360 	  Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
    361 		 (uint64_t) addr);
    362           return 0;
    363 	}
    364     }
    365   else
    366     name = (char*) dlname;
    367 
    368   err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space, &segbase_bias);
    369 
    370   if (!err)
    371     {
    372       fdesc = malloc (sizeof (struct unw_debug_frame_list));
    373 
    374       fdesc->start = start;
    375       fdesc->end = end;
    376       fdesc->debug_frame = buf;
    377       fdesc->debug_frame_size = bufsize;
    378       fdesc->segbase_bias = segbase_bias;
    379       fdesc->index = NULL;
    380       fdesc->next = as->debug_frames;
    381 
    382       as->debug_frames = fdesc;
    383     }
    384 
    385   /* ANDROID support update. */
    386   if (name != dlname)
    387     free(name);
    388   /* End of ANDROID update. */
    389 
    390   return fdesc;
    391 }
    392 
    393 struct debug_frame_tab
    394   {
    395     struct table_entry *tab;
    396     uint32_t length;
    397     uint32_t size;
    398   };
    399 
    400 static void
    401 debug_frame_tab_append (struct debug_frame_tab *tab,
    402 			unw_word_t fde_offset, unw_word_t start_ip)
    403 {
    404   unsigned int length = tab->length;
    405 
    406   if (length == tab->size)
    407     {
    408       tab->size *= 2;
    409       tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
    410     }
    411 
    412   tab->tab[length].fde_offset = fde_offset;
    413   tab->tab[length].start_ip_offset = start_ip;
    414 
    415   tab->length = length + 1;
    416 }
    417 
    418 static void
    419 debug_frame_tab_shrink (struct debug_frame_tab *tab)
    420 {
    421   if (tab->size > tab->length)
    422     {
    423       tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
    424       tab->size = tab->length;
    425     }
    426 }
    427 
    428 static int
    429 debug_frame_tab_compare (const void *a, const void *b)
    430 {
    431   const struct table_entry *fa = a, *fb = b;
    432 
    433   if (fa->start_ip_offset > fb->start_ip_offset)
    434     return 1;
    435   else if (fa->start_ip_offset < fb->start_ip_offset)
    436     return -1;
    437   else
    438     return 0;
    439 }
    440 
    441 PROTECTED int
    442 dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
    443 			unw_word_t segbase, const char* obj_name,
    444 			unw_word_t start, unw_word_t end)
    445 {
    446   unw_dyn_info_t *di;
    447   struct unw_debug_frame_list *fdesc = 0;
    448   unw_accessors_t *a;
    449   unw_word_t addr;
    450 
    451   Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
    452   di = di_debug;
    453 
    454   fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
    455 
    456   if (!fdesc)
    457     {
    458       Debug (15, "couldn't load .debug_frame\n");
    459       return found;
    460     }
    461   else
    462     {
    463       char *buf;
    464       size_t bufsize;
    465       unw_word_t item_start, item_end = 0;
    466       uint32_t u32val = 0;
    467       uint64_t cie_id = 0;
    468       struct debug_frame_tab tab;
    469 
    470       Debug (15, "loaded .debug_frame\n");
    471 
    472       buf = fdesc->debug_frame;
    473       bufsize = fdesc->debug_frame_size;
    474 
    475       if (bufsize == 0)
    476        {
    477          Debug (15, "zero-length .debug_frame\n");
    478          return found;
    479        }
    480 
    481       /* Now create a binary-search table, if it does not already exist.  */
    482       if (!fdesc->index)
    483        {
    484          addr = (unw_word_t) (uintptr_t) buf;
    485 
    486          a = unw_get_accessors (unw_local_addr_space);
    487 
    488          /* Find all FDE entries in debug_frame, and make into a sorted
    489             index.  */
    490 
    491          tab.length = 0;
    492          tab.size = 16;
    493          tab.tab = calloc (tab.size, sizeof (struct table_entry));
    494 
    495          while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
    496            {
    497              uint64_t id_for_cie;
    498              item_start = addr;
    499 
    500              dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
    501 
    502              if (u32val == 0)
    503                break;
    504              else if (u32val != 0xffffffff)
    505                {
    506                  uint32_t cie_id32 = 0;
    507                  item_end = addr + u32val;
    508                  dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
    509                                 NULL);
    510                  cie_id = cie_id32;
    511                  id_for_cie = 0xffffffff;
    512                }
    513              else
    514                {
    515                  uint64_t u64val = 0;
    516                  /* Extended length.  */
    517                  dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
    518                  item_end = addr + u64val;
    519 
    520                  dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
    521                  id_for_cie = 0xffffffffffffffffull;
    522                }
    523 
    524              /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
    525 
    526              if (cie_id == id_for_cie)
    527                ;
    528              /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
    529              else
    530                {
    531                  unw_word_t fde_addr = item_start;
    532                  unw_proc_info_t this_pi;
    533                  int err;
    534 
    535                  /*Debug (1, "Found FDE at %.8x\n", item_start);*/
    536 
    537                  err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
    538                                                          a, &fde_addr,
    539                                                          &this_pi, 0,
    540                                                          (uintptr_t) buf,
    541                                                          NULL);
    542                  if (err == 0)
    543                    {
    544                      Debug (15, "start_ip = %lx, end_ip = %lx\n",
    545                             (long) this_pi.start_ip, (long) this_pi.end_ip);
    546                      debug_frame_tab_append (&tab,
    547                                              item_start - (unw_word_t) (uintptr_t) buf,
    548                                              this_pi.start_ip);
    549                    }
    550                  /*else
    551                    Debug (1, "FDE parse failed\n");*/
    552                }
    553 
    554              addr = item_end;
    555            }
    556 
    557          debug_frame_tab_shrink (&tab);
    558          qsort (tab.tab, tab.length, sizeof (struct table_entry),
    559                 debug_frame_tab_compare);
    560          /* for (i = 0; i < tab.length; i++)
    561             {
    562             fprintf (stderr, "ip %x, fde offset %x\n",
    563             (int) tab.tab[i].start_ip_offset,
    564             (int) tab.tab[i].fde_offset);
    565             }*/
    566          fdesc->index = tab.tab;
    567          fdesc->index_size = tab.length;
    568        }
    569 
    570       di->format = UNW_INFO_FORMAT_TABLE;
    571       di->start_ip = fdesc->start;
    572       di->end_ip = fdesc->end;
    573       di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
    574       di->u.ti.table_data = (unw_word_t *) fdesc;
    575       di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
    576       di->u.ti.segbase = segbase + fdesc->segbase_bias;
    577 
    578       found = 1;
    579       Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
    580             "gp=0x%lx, table_data=0x%lx\n",
    581             (char *) (uintptr_t) di->u.ti.name_ptr,
    582             (long) di->u.ti.segbase, (long) di->u.ti.table_len,
    583             (long) di->gp, (long) di->u.ti.table_data);
    584     }
    585   return found;
    586 }
    587 
    588 #endif /* CONFIG_DEBUG_FRAME */
    589 
    590 #ifndef UNW_REMOTE_ONLY
    591 
    592 /* ptr is a pointer to a dwarf_callback_data structure and, on entry,
    593    member ip contains the instruction-pointer we're looking
    594    for.  */
    595 HIDDEN int
    596 dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
    597 {
    598   struct dwarf_callback_data *cb_data = ptr;
    599   unw_dyn_info_t *di = &cb_data->di;
    600   const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
    601   unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
    602   Elf_W(Addr) load_base, max_load_addr = 0;
    603   int ret, need_unwind_info = cb_data->need_unwind_info;
    604   unw_proc_info_t *pi = cb_data->pi;
    605   struct dwarf_eh_frame_hdr *hdr;
    606   unw_accessors_t *a;
    607   long n;
    608   int found = 0;
    609 #ifdef CONFIG_DEBUG_FRAME
    610   unw_word_t start, end;
    611 #endif /* CONFIG_DEBUG_FRAME*/
    612 
    613   ip = cb_data->ip;
    614 
    615   /* Make sure struct dl_phdr_info is at least as big as we need.  */
    616   if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
    617 	     + sizeof (info->dlpi_phnum))
    618     return -1;
    619 
    620   Debug (15, "checking %s, base=0x%lx)\n",
    621 	 info->dlpi_name, (long) info->dlpi_addr);
    622 
    623   phdr = info->dlpi_phdr;
    624   load_base = info->dlpi_addr;
    625   p_text = NULL;
    626   p_eh_hdr = NULL;
    627   p_dynamic = NULL;
    628 
    629   /* See if PC falls into one of the loaded segments.  Find the
    630      eh-header segment at the same time.  */
    631   for (n = info->dlpi_phnum; --n >= 0; phdr++)
    632     {
    633       if (phdr->p_type == PT_LOAD)
    634 	{
    635 	  Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
    636 
    637 	  if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
    638 	    p_text = phdr;
    639 
    640 	  if (vaddr + phdr->p_filesz > max_load_addr)
    641 	    max_load_addr = vaddr + phdr->p_filesz;
    642 	}
    643       else if (phdr->p_type == PT_GNU_EH_FRAME)
    644 	p_eh_hdr = phdr;
    645       else if (phdr->p_type == PT_DYNAMIC)
    646 	p_dynamic = phdr;
    647     }
    648 
    649   if (!p_text)
    650     return 0;
    651 
    652   if (p_eh_hdr)
    653     {
    654       if (p_dynamic)
    655 	{
    656 	  /* For dynamicly linked executables and shared libraries,
    657 	     DT_PLTGOT is the value that data-relative addresses are
    658 	     relative to for that object.  We call this the "gp".  */
    659 	  Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
    660 	  for (; dyn->d_tag != DT_NULL; ++dyn)
    661 	    if (dyn->d_tag == DT_PLTGOT)
    662 	      {
    663 		/* Assume that _DYNAMIC is writable and GLIBC has
    664 		   relocated it (true for x86 at least).  */
    665 		di->gp = dyn->d_un.d_ptr;
    666 		break;
    667 	      }
    668 	}
    669       else
    670 	/* Otherwise this is a static executable with no _DYNAMIC.  Assume
    671 	   that data-relative addresses are relative to 0, i.e.,
    672 	   absolute.  */
    673 	di->gp = 0;
    674       pi->gp = di->gp;
    675 
    676       hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
    677       if (hdr->version != DW_EH_VERSION)
    678 	{
    679 	  Debug (1, "table `%s' has unexpected version %d\n",
    680 		 info->dlpi_name, hdr->version);
    681 	  return 0;
    682 	}
    683 
    684       a = unw_get_accessors (unw_local_addr_space);
    685       addr = (unw_word_t) (uintptr_t) (hdr + 1);
    686 
    687       /* (Optionally) read eh_frame_ptr: */
    688       if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
    689 					     &addr, hdr->eh_frame_ptr_enc, pi,
    690 					     &eh_frame_start, NULL)) < 0)
    691 	return ret;
    692 
    693       /* (Optionally) read fde_count: */
    694       if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
    695 					     &addr, hdr->fde_count_enc, pi,
    696 					     &fde_count, NULL)) < 0)
    697 	return ret;
    698 
    699       if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
    700 	{
    701 	  /* If there is no search table or it has an unsupported
    702 	     encoding, fall back on linear search.  */
    703 	  if (hdr->table_enc == DW_EH_PE_omit)
    704             /* ANDROID support update. */
    705 	    {
    706             /* End of ANDROID update. */
    707 	      Debug (4, "table `%s' lacks search table; doing linear search\n",
    708 		     info->dlpi_name);
    709             /* ANDROID support update. */
    710 	    }
    711             /* End of ANDROID update. */
    712 	  else
    713             /* ANDROID support update. */
    714 	    {
    715             /* End of ANDROID update. */
    716 	      Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
    717 		     info->dlpi_name, hdr->table_enc);
    718             /* ANDROID support update. */
    719 	    }
    720             /* End of ANDROID update. */
    721 
    722 	  eh_frame_end = max_load_addr;	/* XXX can we do better? */
    723 
    724 	  if (hdr->fde_count_enc == DW_EH_PE_omit)
    725 	    fde_count = ~0UL;
    726 	  if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
    727 	    abort ();
    728 
    729 	  /* XXX we know how to build a local binary search table for
    730 	     .debug_frame, so we could do that here too.  */
    731 	  cb_data->single_fde = 1;
    732 	  found = linear_search (unw_local_addr_space, ip,
    733 				 eh_frame_start, eh_frame_end, fde_count,
    734 				 pi, need_unwind_info, NULL);
    735 	  if (found != 1)
    736 	    found = 0;
    737 	}
    738       else
    739 	{
    740 	  di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
    741 	  di->start_ip = p_text->p_vaddr + load_base;
    742 	  di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
    743 	  di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
    744 	  di->u.rti.table_data = addr;
    745 	  assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
    746 	  di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
    747 				 / sizeof (unw_word_t));
    748 	  /* For the binary-search table in the eh_frame_hdr, data-relative
    749 	     means relative to the start of that section... */
    750 	  di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
    751 
    752 	  found = 1;
    753 	  Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
    754 		 "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
    755 		 (long) di->u.rti.segbase, (long) di->u.rti.table_len,
    756 		 (long) di->gp, (long) di->u.rti.table_data);
    757 	}
    758     }
    759 
    760 #ifdef CONFIG_DEBUG_FRAME
    761   /* Find the start/end of the described region by parsing the phdr_info
    762      structure.  */
    763   start = (unw_word_t) -1;
    764   end = 0;
    765 
    766   for (n = 0; n < info->dlpi_phnum; n++)
    767     {
    768       if (info->dlpi_phdr[n].p_type == PT_LOAD)
    769         {
    770 	  unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
    771           unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
    772 
    773 	  if (seg_start < start)
    774 	    start = seg_start;
    775 
    776 	  if (seg_end > end)
    777 	    end = seg_end;
    778 	}
    779     }
    780 
    781   found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
    782 				  info->dlpi_addr, info->dlpi_name, start,
    783 				  end);
    784 #endif  /* CONFIG_DEBUG_FRAME */
    785 
    786   return found;
    787 }
    788 
    789 HIDDEN int
    790 dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
    791 		      unw_proc_info_t *pi, int need_unwind_info, void *arg)
    792 {
    793   struct dwarf_callback_data cb_data;
    794   intrmask_t saved_mask;
    795   int ret;
    796 
    797   Debug (14, "looking for IP=0x%lx\n", (long) ip);
    798 
    799   memset (&cb_data, 0, sizeof (cb_data));
    800   cb_data.ip = ip;
    801   cb_data.pi = pi;
    802   cb_data.need_unwind_info = need_unwind_info;
    803   cb_data.di.format = -1;
    804   cb_data.di_debug.format = -1;
    805 
    806   SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
    807   ret = dl_iterate_phdr (dwarf_callback, &cb_data);
    808   SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
    809 
    810   if (ret <= 0)
    811     {
    812       Debug (14, "IP=0x%lx not found\n", (long) ip);
    813       return -UNW_ENOINFO;
    814     }
    815 
    816   if (cb_data.single_fde)
    817     /* already got the result in *pi */
    818     return 0;
    819 
    820   /* search the table: */
    821   if (cb_data.di.format != -1)
    822     ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
    823 				      pi, need_unwind_info, arg);
    824   else
    825     ret = -UNW_ENOINFO;
    826 
    827   if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
    828     ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
    829 				     need_unwind_info, arg);
    830   return ret;
    831 }
    832 
    833 static inline const struct table_entry *
    834 lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
    835 {
    836   unsigned long table_len = table_size / sizeof (struct table_entry);
    837   const struct table_entry *e = NULL;
    838   unsigned long lo, hi, mid;
    839 
    840   /* do a binary search for right entry: */
    841   for (lo = 0, hi = table_len; lo < hi;)
    842     {
    843       mid = (lo + hi) / 2;
    844       e = table + mid;
    845       Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
    846       if (rel_ip < e->start_ip_offset)
    847 	hi = mid;
    848       else
    849 	lo = mid + 1;
    850     }
    851   if (hi <= 0)
    852 	return NULL;
    853   e = table + hi - 1;
    854   return e;
    855 }
    856 
    857 #endif /* !UNW_REMOTE_ONLY */
    858 
    859 #ifndef UNW_LOCAL_ONLY
    860 
    861 /* Lookup an unwind-table entry in remote memory.  Returns 1 if an
    862    entry is found, 0 if no entry is found, negative if an error
    863    occurred reading remote memory.  */
    864 static int
    865 remote_lookup (unw_addr_space_t as,
    866 	       unw_word_t table, size_t table_size, int32_t rel_ip,
    867 	       struct table_entry *e, void *arg)
    868 {
    869   unsigned long table_len = table_size / sizeof (struct table_entry);
    870   unw_accessors_t *a = unw_get_accessors (as);
    871   unsigned long lo, hi, mid;
    872   unw_word_t e_addr = 0;
    873   int32_t start;
    874   int ret;
    875 
    876   /* do a binary search for right entry: */
    877   for (lo = 0, hi = table_len; lo < hi;)
    878     {
    879       mid = (lo + hi) / 2;
    880       e_addr = table + mid * sizeof (struct table_entry);
    881       if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
    882 	return ret;
    883 
    884       if (rel_ip < start)
    885 	hi = mid;
    886       else
    887 	lo = mid + 1;
    888     }
    889   if (hi <= 0)
    890     return 0;
    891   e_addr = table + (hi - 1) * sizeof (struct table_entry);
    892   if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
    893    || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0)
    894     return ret;
    895   return 1;
    896 }
    897 
    898 #endif /* !UNW_LOCAL_ONLY */
    899 
    900 PROTECTED int
    901 dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
    902 			   unw_dyn_info_t *di, unw_proc_info_t *pi,
    903 			   int need_unwind_info, void *arg)
    904 {
    905   const struct table_entry *e = NULL, *table;
    906   unw_word_t segbase = 0, fde_addr;
    907   unw_accessors_t *a;
    908 #ifndef UNW_LOCAL_ONLY
    909   struct table_entry ent;
    910 #endif
    911   int ret;
    912   unw_word_t debug_frame_base;
    913   size_t table_len;
    914 
    915 #ifdef UNW_REMOTE_ONLY
    916   assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE);
    917 #else
    918   assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE
    919 	  || di->format == UNW_INFO_FORMAT_TABLE);
    920 #endif
    921   assert (ip >= di->start_ip && ip < di->end_ip);
    922 
    923   if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE)
    924     {
    925       table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
    926       table_len = di->u.rti.table_len * sizeof (unw_word_t);
    927       debug_frame_base = 0;
    928     }
    929   else
    930     {
    931 #ifndef UNW_REMOTE_ONLY
    932       struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
    933 
    934       /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
    935          space.  Both the index and the unwind tables live in local memory, but
    936          the address space to check for properties like the address size and
    937          endianness is the target one.  */
    938       as = unw_local_addr_space;
    939       table = fdesc->index;
    940       table_len = fdesc->index_size * sizeof (struct table_entry);
    941       debug_frame_base = (uintptr_t) fdesc->debug_frame;
    942 #endif
    943     }
    944 
    945   a = unw_get_accessors (as);
    946 
    947 #ifndef UNW_REMOTE_ONLY
    948   if (as == unw_local_addr_space)
    949     {
    950       segbase = di->u.rti.segbase;
    951       e = lookup (table, table_len, ip - segbase);
    952     }
    953   else
    954 #endif
    955     {
    956 #ifndef UNW_LOCAL_ONLY
    957       segbase = di->u.rti.segbase;
    958       if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
    959 				ip - segbase, &ent, arg)) < 0)
    960 	return ret;
    961       if (ret)
    962 	e = &ent;
    963       else
    964 	e = NULL;	/* no info found */
    965 #endif
    966     }
    967   if (!e)
    968     {
    969       Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
    970 	     (long) ip, (long) di->start_ip, (long) di->end_ip);
    971       /* IP is inside this table's range, but there is no explicit
    972 	 unwind info.  */
    973       return -UNW_ENOINFO;
    974     }
    975   Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
    976 	 (long) ip, (long) (e->start_ip_offset));
    977   if (debug_frame_base)
    978     fde_addr = e->fde_offset + debug_frame_base;
    979   else
    980     fde_addr = e->fde_offset + segbase;
    981   Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
    982 	    "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
    983 	    (long) debug_frame_base, (long) fde_addr);
    984   if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
    985 					       need_unwind_info,
    986 					       debug_frame_base, arg)) < 0)
    987     return ret;
    988 
    989   /* .debug_frame uses an absolute encoding that does not know about any
    990      shared library relocation.  */
    991   if (di->format == UNW_INFO_FORMAT_TABLE)
    992     {
    993       pi->start_ip += segbase;
    994       pi->end_ip += segbase;
    995       pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
    996     }
    997 
    998   if (ip < pi->start_ip || ip >= pi->end_ip)
    999     {
   1000       /* ANDROID support update. */
   1001       if (need_unwind_info && pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
   1002         {
   1003           /* Free the memory used if the call fails. Otherwise, when there
   1004            * is a mix of dwarf and other unwind data, the memory allocated
   1005            * will be leaked.
   1006            */
   1007           mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
   1008           pi->unwind_info = NULL;
   1009         }
   1010       /* End of ANDROID support update. */
   1011       return -UNW_ENOINFO;
   1012     }
   1013 
   1014   return 0;
   1015 }
   1016 
   1017 HIDDEN void
   1018 dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
   1019 {
   1020   return;	/* always a nop */
   1021 }
   1022