1824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm/* libunwind - a platform-independent unwind library
2379fb069d2d8291be25b2e54c1251371522179c8hp.com!davidm   Copyright (C) 2003-2005 Hewlett-Packard Co
3e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang   Copyright (C) 2007 David Mosberger-Tang
4e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang	Contributed by David Mosberger-Tang <dmosberger@gmail.com>
5824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
6824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmThis file is part of libunwind.
7824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
8824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmPermission is hereby granted, free of charge, to any person obtaining
9824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidma copy of this software and associated documentation files (the
10824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm"Software"), to deal in the Software without restriction, including
11824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
12824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
13824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmpermit persons to whom the Software is furnished to do so, subject to
14824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmthe following conditions:
15824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
16824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmThe above copyright notice and this permission notice shall be
17824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmincluded in all copies or substantial portions of the Software.
18824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
19824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
2796c1bca2b08f147011814b1b7be6863151ef0be9Tommi Rantala#include "libunwind_i.h"
2896c1bca2b08f147011814b1b7be6863151ef0be9Tommi Rantala
29824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm#include <stdio.h>
301787a2fd284a786b409af74047a12de02c644cd1Arun Sharma#include <sys/param.h>
31824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
323d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#ifdef HAVE_LZMA
333d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#include <lzma.h>
343d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#endif /* HAVE_LZMA */
353d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
3671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milatastatic Elf_W (Shdr)*
3771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milataelf_w (section_table) (struct elf_image *ei)
3871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata{
3971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Ehdr) *ehdr = ei->image;
4071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Off) soff;
4171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
4271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  soff = ehdr->e_shoff;
4371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
4471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    {
4571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      Debug (1, "section table outside of image? (%lu > %lu)\n",
4671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize),
4771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) ei->size);
4871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      return NULL;
4971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    }
5071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
5171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  return (Elf_W (Shdr) *) ((char *) ei->image + soff);
5271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata}
5371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
5471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milatastatic char*
5571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milataelf_w (string_table) (struct elf_image *ei, int section)
5671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata{
5771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Ehdr) *ehdr = ei->image;
5871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Off) soff, str_soff;
5971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Shdr) *str_shdr;
6071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
6171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  /* this offset is assumed to be OK */
6271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  soff = ehdr->e_shoff;
6371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
6471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  str_soff = soff + (section * ehdr->e_shentsize);
6571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  if (str_soff + ehdr->e_shentsize > ei->size)
6671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    {
6771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      Debug (1, "string shdr table outside of image? (%lu > %lu)\n",
6871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) (str_soff + ehdr->e_shentsize),
6971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) ei->size);
7071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      return NULL;
7171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    }
7271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff);
7371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
7471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  if (str_shdr->sh_offset + str_shdr->sh_size > ei->size)
7571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    {
7671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      Debug (1, "string table outside of image? (%lu > %lu)\n",
7771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) (str_shdr->sh_offset + str_shdr->sh_size),
7871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	     (unsigned long) ei->size);
7971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      return NULL;
8071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    }
8171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
8271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Debug (16, "strtab=0x%lx\n", (long) str_shdr->sh_offset);
83d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris  /* End of ANDROID update. */
84d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris  return (char*) ((uintptr_t) ei->image + str_shdr->sh_offset);
85d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris  /* End of ANDROID update. */
8671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata}
8771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
88824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmstatic int
89e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tangelf_w (lookup_symbol) (unw_addr_space_t as,
90e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang		       unw_word_t ip, struct elf_image *ei,
914fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm		       Elf_W (Addr) load_offset,
923d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		       char *buf, size_t buf_len, Elf_W (Addr) *min_dist)
93824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm{
94dee53d780094be559381f8584a0a95222ecf5bb5hp.com!davidm  size_t syment_size;
954fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm  Elf_W (Ehdr) *ehdr = ei->image;
964fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm  Elf_W (Sym) *sym, *symtab, *symtab_end;
9771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Shdr) *shdr;
983d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  Elf_W (Addr) val;
99e11a6a4fdf1891802987519974f3a01d665126e9Martin Milata  int i, ret = -UNW_ENOINFO;
100824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm  char *strtab;
101824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
1024fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm  if (!elf_w (valid_object) (ei))
1037bfbbb6126987bf6eedffd03fab4aa4cc537f1e9mostang.com!davidm    return -UNW_ENOINFO;
104824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
10571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  shdr = elf_w (section_table) (ei);
10671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  if (!shdr)
10771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    return -UNW_ENOINFO;
108824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
109824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm  for (i = 0; i < ehdr->e_shnum; ++i)
110824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm    {
111824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm      switch (shdr->sh_type)
112824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	{
113824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	case SHT_SYMTAB:
114824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	case SHT_DYNSYM:
1154fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm	  symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset);
1164fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm	  symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size);
117824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	  syment_size = shdr->sh_entsize;
118824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
11971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	  strtab = elf_w (string_table) (ei, shdr->sh_link);
12071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	  if (!strtab)
12171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	    break;
122824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
12371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	  Debug (16, "symtab=0x%lx[%d]\n",
12471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata		 (long) shdr->sh_offset, shdr->sh_type);
125824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
126824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	  for (sym = symtab;
127824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	       sym < symtab_end;
1284fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm	       sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
129824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	    {
1304fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm	      if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
131824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		  && sym->st_shndx != SHN_UNDEF)
132824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		{
133e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang		  if (tdep_get_func_addr (as, sym->st_value, &val) < 0)
134e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang		    continue;
135824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		  if (sym->st_shndx != SHN_ABS)
136824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		    val += load_offset;
137c67d345c33f1d0b6e4adce3e03f8a1f332722669hp.com!davidm		  Debug (16, "0x%016lx info=0x%02x %s\n",
13871650257d7c7e805e25482b431651a4dc9b18727hp.com!davidm			 (long) val, sym->st_info, strtab + sym->st_name);
139824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
140d24fdf6c51c7ab875662b9ca13372d57cd9f36e1Christopher Ferris                  /* ANDROID support update */
141d24fdf6c51c7ab875662b9ca13372d57cd9f36e1Christopher Ferris                  if ((Elf_W (Addr)) (ip - val) < *min_dist
142d24fdf6c51c7ab875662b9ca13372d57cd9f36e1Christopher Ferris                      && (Elf_W (Addr)) (ip - val) < sym->st_size)
143d24fdf6c51c7ab875662b9ca13372d57cd9f36e1Christopher Ferris                  /* End of ANDROID update */
144824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		    {
1453d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		      *min_dist = (Elf_W (Addr)) (ip - val);
146824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		      strncpy (buf, strtab + sym->st_name, buf_len);
147824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		      buf[buf_len - 1] = '\0';
148e11a6a4fdf1891802987519974f3a01d665126e9Martin Milata		      ret = (strlen (strtab + sym->st_name) >= buf_len
149e11a6a4fdf1891802987519974f3a01d665126e9Martin Milata			     ? -UNW_ENOMEM : 0);
150824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		    }
151824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm		}
152824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	    }
153824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	  break;
154824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
155824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	default:
156824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	  break;
157824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm	}
1584fafd8cbf7464f50b30e2983e332ddebef8b5acchp.com!davidm      shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
159824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm    }
1607bfbbb6126987bf6eedffd03fab4aa4cc537f1e9mostang.com!davidm  return ret;
161824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm}
162824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
16371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milatastatic Elf_W (Addr)
16471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milataelf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase,
16571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata			 unsigned long mapoff)
16671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata{
16771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Addr) offset = 0;
16871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Ehdr) *ehdr;
16971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Phdr) *phdr;
17071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  int i;
17171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
17271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  ehdr = ei->image;
17371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  phdr = (Elf_W (Phdr) *) ((char *) ei->image + ehdr->e_phoff);
17471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
17571c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  for (i = 0; i < ehdr->e_phnum; ++i)
17671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata    if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff)
17771c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      {
17871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	offset = segbase - phdr[i].p_vaddr;
17971c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata	break;
18071c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata      }
18171c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
18271c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  return offset;
18371c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata}
18471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata
1853d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#if HAVE_LZMA
1863d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milatastatic size_t
1873d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milataxz_uncompressed_size (uint8_t *compressed, size_t length)
1883d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata{
1893d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uint64_t memlimit = UINT64_MAX;
1903d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  size_t ret = 0, pos = 0;
1913d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  lzma_stream_flags options;
1923d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  lzma_index *index;
1933d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
1943d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (length < LZMA_STREAM_HEADER_SIZE)
1953d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
1963d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
1973d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uint8_t *footer = compressed + length - LZMA_STREAM_HEADER_SIZE;
1983d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (lzma_stream_footer_decode (&options, footer) != LZMA_OK)
1993d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2003d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2013d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (length < LZMA_STREAM_HEADER_SIZE + options.backward_size)
2023d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2033d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2043d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uint8_t *indexdata = footer - options.backward_size;
2053d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata,
2063d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata				&pos, options.backward_size) != LZMA_OK)
2073d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2083d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2093d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (lzma_index_size (index) == options.backward_size)
2103d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    {
2113d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      ret = lzma_index_uncompressed_size (index);
2123d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    }
2133d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2143d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  lzma_index_end (index, NULL);
2153d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  return ret;
2163d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata}
2173d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2183d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milatastatic int
2193d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milataelf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
2203d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata{
2213d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  Elf_W (Ehdr) *ehdr = ei->image;
2223d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  Elf_W (Shdr) *shdr;
2233d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  char *strtab;
2243d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  int i;
2253d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uint8_t *compressed = NULL;
2263d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uint64_t memlimit = UINT64_MAX; /* no memory limit */
2273d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  size_t compressed_len, uncompressed_len;
2283d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2293d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (!elf_w (valid_object) (ei))
2303d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2313d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2323d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  shdr = elf_w (section_table) (ei);
2333d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (!shdr)
2343d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2353d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2363d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  strtab = elf_w (string_table) (ei, ehdr->e_shstrndx);
2373d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (!strtab)
2383d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2393d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2403d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  for (i = 0; i < ehdr->e_shnum; ++i)
2413d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    {
2423d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      if (strcmp (strtab + shdr->sh_name, ".gnu_debugdata") == 0)
2433d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	{
2443d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  if (shdr->sh_offset + shdr->sh_size > ei->size)
2453d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	    {
2463d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	      Debug (1, ".gnu_debugdata outside image? (0x%lu > 0x%lu)\n",
2473d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		     (unsigned long) shdr->sh_offset + shdr->sh_size,
2483d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		     (unsigned long) ei->size);
2493d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	      return 0;
2503d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	    }
2513d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2523d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  Debug (16, "found .gnu_debugdata at 0x%lx\n",
2533d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		 (unsigned long) shdr->sh_offset);
2543d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  compressed = ((uint8_t *) ei->image) + shdr->sh_offset;
2553d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  compressed_len = shdr->sh_size;
2563d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  break;
2573d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	}
2583d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2593d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize);
2603d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    }
2613d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2623d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  /* not found */
2633d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (!compressed)
2643d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2653d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2663d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  uncompressed_len = xz_uncompressed_size (compressed, compressed_len);
2673d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (uncompressed_len == 0)
2683d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    {
2693d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      Debug (1, "invalid .gnu_debugdata contents\n");
2703d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      return 0;
2713d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    }
2723d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2733d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  mdi->size = uncompressed_len;
2743d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE,
2753d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata		     MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2763d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2773d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (mdi->image == MAP_FAILED)
2783d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return 0;
2793d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2803d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  size_t in_pos = 0, out_pos = 0;
2813d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  lzma_ret lret;
2823d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  lret = lzma_stream_buffer_decode (&memlimit, 0, NULL,
2833d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata				    compressed, &in_pos, compressed_len,
2843d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata				    mdi->image, &out_pos, mdi->size);
2853d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (lret != LZMA_OK)
2863d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    {
2873d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      Debug (1, "LZMA decompression failed: %d\n", lret);
2883d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      munmap (mdi->image, mdi->size);
2893d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      return 0;
2903d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    }
2913d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
2923d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  return 1;
2933d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata}
2943d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#else
2953d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milatastatic int
2963d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milataelf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
2973d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata{
2983d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  return 0;
2993d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata}
3003d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata#endif /* !HAVE_LZMA */
3013d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
302824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm/* Find the ELF image that contains IP and return the "closest"
303824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm   procedure name, if there is one.  With some caching, this could be
304824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm   sped up greatly, but until an application materializes that's
305824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm   sensitive to the performance of this routine, why bother...  */
306824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
3075d8b2e341554b1a1e96b66eb337251525017e006hp.com!davidmHIDDEN int
308d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharmaelf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei,
309d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma		       unsigned long segbase,
310d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma		       unsigned long mapoff,
311d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma		       unw_word_t ip,
312e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang		       char *buf, size_t buf_len, unw_word_t *offp)
313824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm{
31471c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  Elf_W (Addr) load_offset;
3153d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  Elf_W (Addr) min_dist = ~(Elf_W (Addr))0;
31671c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  int ret;
317824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
31871c1fffc357276dbcf7327a2829d8ec1eedf7e6fMartin Milata  load_offset = elf_w (get_load_offset) (ei, segbase, mapoff);
3193d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  ret = elf_w (lookup_symbol) (as, ip, ei, load_offset, buf, buf_len, &min_dist);
3203d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
3213d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  /* If the ELF image has MiniDebugInfo embedded in it, look up the symbol in
3223d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata     there as well and replace the previously found if it is closer. */
3233d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  struct elf_image mdi;
3243d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (elf_w (extract_minidebuginfo) (ei, &mdi))
3253d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    {
3263d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      int ret_mdi;
327824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
3283d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      load_offset = elf_w (get_load_offset) (&mdi, segbase, mapoff);
3293d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf,
3303d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata				       buf_len, &min_dist);
331824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
3323d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      /* Closer symbol was found (possibly truncated). */
3333d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM)
3343d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	{
3353d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	  ret = ret_mdi;
3363d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata	}
3373d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata
3383d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata      munmap (mdi.image, mdi.size);
3393d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    }
340d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma
3413d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (min_dist >= ei->size)
3423d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    return -UNW_ENOINFO;		/* not found */
3433d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata  if (offp)
3443d5e6c1dddc67288a4aeaf8bbcdc76dd220f5898Martin Milata    *offp = min_dist;
345d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma  return ret;
346d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma}
347d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma
34816b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris/* ANDROID support update. */
349d276b7a9614987495a7dfb056e6558f452ebe802Arun SharmaHIDDEN int
350d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharmaelf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
351d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma		       char *buf, size_t buf_len, unw_word_t *offp)
352d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma{
353f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  unsigned long segbase, mapoff;
354f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct elf_image ei;
355d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma  int ret;
356d276b7a9614987495a7dfb056e6558f452ebe802Arun Sharma
357f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  ret = tdep_get_elf_image(as, &ei, pid, ip, &segbase, &mapoff, NULL);
358f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (ret < 0)
359f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    return ret;
360824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
361f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return elf_w (get_proc_name_in_image) (as, &ei, segbase, mapoff, ip, buf, buf_len, offp);
362824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm}
36316b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris/* ANDROID support update. */
364