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