125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Get CFI from ELF file's exception-handling info. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2009-2010, 2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwP.h" 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "cfi.h" 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "encoded-value.h" 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_CFI * 4425b3c049e70834cf33790a28643ab058b507b35cBen Chengallocate_cfi (Elf *elf, GElf_Addr vaddr) 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI *cfi = calloc (1, sizeof *cfi); 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cfi == NULL) 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NOMEM); 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->e_ident = (unsigned char *) elf_getident (elf, NULL); 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cfi->e_ident == NULL) 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (cfi); 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_GETEHDR_ERROR); 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((BYTE_ORDER == LITTLE_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2MSB) 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (BYTE_ORDER == BIG_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2LSB)) 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->other_byte_order = true; 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->frame_vaddr = vaddr; 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->textrel = 0; /* XXX ? */ 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->datarel = 0; /* XXX ? */ 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return cfi; 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const uint8_t * 7325b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr, 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Ehdr *ehdr, GElf_Addr *eh_frame_vaddr, 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *table_entries, uint8_t *table_encoding) 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *h = hdr; 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*h++ != 1) /* version */ 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint8_t eh_frame_ptr_encoding = *h++; 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint8_t fde_count_encoding = *h++; 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint8_t fde_table_encoding = *h++; 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eh_frame_ptr_encoding == DW_EH_PE_omit) 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Dummy used by read_encoded_value. */ 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data_Scn dummy_cfi_hdr_data = 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d = { .d_buf = (void *) hdr, .d_size = hdr_size } 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI dummy_cfi = 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng .e_ident = ehdr->e_ident, 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .datarel = hdr_vaddr, 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .frame_vaddr = hdr_vaddr, 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .data = &dummy_cfi_hdr_data, 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_encoded_value (&dummy_cfi, eh_frame_ptr_encoding, &h, 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eh_frame_vaddr))) 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde_count_encoding != DW_EH_PE_omit) 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word fde_count; 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_encoded_value (&dummy_cfi, fde_count_encoding, &h, 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &fde_count))) 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde_count != 0 && (size_t) fde_count == fde_count 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && fde_table_encoding != DW_EH_PE_omit 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (fde_table_encoding &~ DW_EH_PE_signed) != DW_EH_PE_uleb128) 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *table_entries = fde_count; 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *table_encoding = fde_table_encoding; 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return h; 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_CFI * 12625b3c049e70834cf33790a28643ab058b507b35cBen Chenggetcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr) 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (phdr->p_filesz < 4)) 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto invalid; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz, 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_T_BYTE); 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng invalid_hdr: 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng invalid: 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* XXX might be read error or corrupt phdr */ 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_CFI); 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr eh_frame_ptr; 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t search_table_entries = 0; 14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes uint8_t search_table_encoding = 0; 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *search_table = parse_eh_frame_hdr (data->d_buf, phdr->p_filesz, 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr->p_vaddr, ehdr, 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &eh_frame_ptr, 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng &search_table_entries, 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng &search_table_encoding); 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (search_table == (void *) -1l) 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto invalid_hdr; 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Off eh_frame_offset = eh_frame_ptr - phdr->p_vaddr + phdr->p_offset; 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word eh_frame_size = 0; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* XXX we have no way without section headers to know the size 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng of the .eh_frame data. Calculate the largest it might possibly be. 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng This won't be wasteful if the file is already mmap'd, but if it isn't 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng it might be quite excessive. */ 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t filesize; 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_rawfile (elf, &filesize) != NULL) 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eh_frame_size = filesize - eh_frame_offset; 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng data = elf_getdata_rawchunk (elf, eh_frame_offset, eh_frame_size, ELF_T_BYTE); 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_ELF); /* XXX might be read error */ 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI *cfi = allocate_cfi (elf, eh_frame_ptr); 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cfi != NULL) 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->data = (Elf_Data_Scn *) data; 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (search_table != NULL) 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table = search_table; 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table_vaddr = phdr->p_vaddr; 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table_encoding = search_table_encoding; 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table_entries = search_table_entries; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return cfi; 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Search the phdrs for PT_GNU_EH_FRAME. */ 18725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_CFI * 18825b3c049e70834cf33790a28643ab058b507b35cBen Chenggetcfi_phdr (Elf *elf, const GElf_Ehdr *ehdr) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phnum; 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < phnum; ++i) 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (phdr == NULL)) 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type == PT_GNU_EH_FRAME) 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return getcfi_gnu_eh_frame (elf, ehdr, phdr); 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NO_DWARF); 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_CFI * 20925b3c049e70834cf33790a28643ab058b507b35cBen Chenggetcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn, GElf_Shdr *shdr, 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr) 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_rawdata (scn, NULL); 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_ELF); 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI *cfi = allocate_cfi (elf, shdr->sh_addr); 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cfi != NULL) 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->data = (Elf_Data_Scn *) data; 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hdr_scn != NULL) 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL); 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (hdr_data != NULL) 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr eh_frame_vaddr; 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table_vaddr = hdr_vaddr; 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng = parse_eh_frame_hdr (hdr_data->d_buf, hdr_data->d_size, 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng hdr_vaddr, ehdr, &eh_frame_vaddr, 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &cfi->search_table_entries, 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng &cfi->search_table_encoding); 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cfi->search_table == (void *) -1l) 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (cfi); 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* XXX might be read error or corrupt phdr */ 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_CFI); 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Sanity check. */ 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (eh_frame_vaddr != shdr->sh_addr)) 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng cfi->search_table = NULL; 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return cfi; 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Search for the sections named ".eh_frame" and ".eh_frame_hdr". */ 25325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_CFI * 25425b3c049e70834cf33790a28643ab058b507b35cBen Chenggetcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr) 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t shstrndx; 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_getshdrstrndx (elf, &shstrndx) != 0) 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_GETEHDR_ERROR); 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shstrndx != 0) 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *hdr_scn = NULL; 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr hdr_vaddr = 0; 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (shdr == NULL) 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name == NULL) 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!strcmp (name, ".eh_frame_hdr")) 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng hdr_scn = scn; 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng hdr_vaddr = shdr->sh_addr; 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (!strcmp (name, ".eh_frame")) 28303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (shdr->sh_type == SHT_PROGBITS) 28503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return getcfi_scn_eh_frame (elf, ehdr, scn, shdr, 28603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes hdr_scn, hdr_vaddr); 28703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 28803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 28903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29625b3c049e70834cf33790a28643ab058b507b35cBen ChengDwarf_CFI * 29725b3c049e70834cf33790a28643ab058b507b35cBen Chengdwarf_getcfi_elf (elf) 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf; 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf_kind (elf) != ELF_K_ELF) 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NOELF); 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr ehdr_mem; 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ehdr == NULL)) 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_ELF); 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI *result = getcfi_shdr (elf, ehdr); 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result == (void *) -1l) 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = getcfi_phdr (elf, ehdr); 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 32025b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwarf_getcfi_elf) 321