1da0c48c4Sopenharmony_ci/* Get CFI from ELF file's exception-handling info. 2da0c48c4Sopenharmony_ci Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include <stdlib.h> 34da0c48c4Sopenharmony_ci#include <string.h> 35da0c48c4Sopenharmony_ci#include <assert.h> 36da0c48c4Sopenharmony_ci 37da0c48c4Sopenharmony_ci#include "libdwP.h" 38da0c48c4Sopenharmony_ci#include "cfi.h" 39da0c48c4Sopenharmony_ci#include "encoded-value.h" 40da0c48c4Sopenharmony_ci#include <dwarf.h> 41da0c48c4Sopenharmony_ci 42da0c48c4Sopenharmony_ci 43da0c48c4Sopenharmony_cistatic Dwarf_CFI * 44da0c48c4Sopenharmony_ciallocate_cfi (Elf *elf, const GElf_Ehdr *ehdr, GElf_Addr vaddr) 45da0c48c4Sopenharmony_ci{ 46da0c48c4Sopenharmony_ci Dwarf_CFI *cfi = calloc (1, sizeof *cfi); 47da0c48c4Sopenharmony_ci if (cfi == NULL) 48da0c48c4Sopenharmony_ci { 49da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); 50da0c48c4Sopenharmony_ci return NULL; 51da0c48c4Sopenharmony_ci } 52da0c48c4Sopenharmony_ci 53da0c48c4Sopenharmony_ci cfi->e_ident = (unsigned char *) elf_getident (elf, NULL); 54da0c48c4Sopenharmony_ci if (cfi->e_ident == NULL) 55da0c48c4Sopenharmony_ci { 56da0c48c4Sopenharmony_ci free (cfi); 57da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_GETEHDR_ERROR); 58da0c48c4Sopenharmony_ci return NULL; 59da0c48c4Sopenharmony_ci } 60da0c48c4Sopenharmony_ci 61da0c48c4Sopenharmony_ci cfi->e_machine = ehdr->e_machine; 62da0c48c4Sopenharmony_ci 63da0c48c4Sopenharmony_ci if ((BYTE_ORDER == LITTLE_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2MSB) 64da0c48c4Sopenharmony_ci || (BYTE_ORDER == BIG_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2LSB)) 65da0c48c4Sopenharmony_ci cfi->other_byte_order = true; 66da0c48c4Sopenharmony_ci 67da0c48c4Sopenharmony_ci cfi->frame_vaddr = vaddr; 68da0c48c4Sopenharmony_ci cfi->textrel = 0; /* XXX ? */ 69da0c48c4Sopenharmony_ci cfi->datarel = 0; /* XXX ? */ 70da0c48c4Sopenharmony_ci 71da0c48c4Sopenharmony_ci return cfi; 72da0c48c4Sopenharmony_ci} 73da0c48c4Sopenharmony_ci 74da0c48c4Sopenharmony_cistatic const uint8_t * 75da0c48c4Sopenharmony_ciparse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr, 76da0c48c4Sopenharmony_ci const GElf_Ehdr *ehdr, GElf_Addr *eh_frame_vaddr, 77da0c48c4Sopenharmony_ci size_t *table_entries, uint8_t *table_encoding) 78da0c48c4Sopenharmony_ci{ 79da0c48c4Sopenharmony_ci const uint8_t *h = hdr; 80da0c48c4Sopenharmony_ci 81da0c48c4Sopenharmony_ci if (hdr_size < 4 || *h++ != 1) /* version */ 82da0c48c4Sopenharmony_ci return (void *) -1l; 83da0c48c4Sopenharmony_ci 84da0c48c4Sopenharmony_ci uint8_t eh_frame_ptr_encoding = *h++; 85da0c48c4Sopenharmony_ci uint8_t fde_count_encoding = *h++; 86da0c48c4Sopenharmony_ci uint8_t fde_table_encoding = *h++; 87da0c48c4Sopenharmony_ci 88da0c48c4Sopenharmony_ci if (eh_frame_ptr_encoding == DW_EH_PE_omit) 89da0c48c4Sopenharmony_ci return (void *) -1l; 90da0c48c4Sopenharmony_ci 91da0c48c4Sopenharmony_ci /* Dummy used by read_encoded_value. */ 92da0c48c4Sopenharmony_ci Elf_Data_Scn dummy_cfi_hdr_data = 93da0c48c4Sopenharmony_ci { 94da0c48c4Sopenharmony_ci .d = { .d_buf = (void *) hdr, .d_size = hdr_size } 95da0c48c4Sopenharmony_ci }; 96da0c48c4Sopenharmony_ci Dwarf_CFI dummy_cfi = 97da0c48c4Sopenharmony_ci { 98da0c48c4Sopenharmony_ci .e_ident = ehdr->e_ident, 99da0c48c4Sopenharmony_ci .datarel = hdr_vaddr, 100da0c48c4Sopenharmony_ci .frame_vaddr = hdr_vaddr, 101da0c48c4Sopenharmony_ci .data = &dummy_cfi_hdr_data, 102da0c48c4Sopenharmony_ci }; 103da0c48c4Sopenharmony_ci 104da0c48c4Sopenharmony_ci if (unlikely (read_encoded_value (&dummy_cfi, eh_frame_ptr_encoding, &h, 105da0c48c4Sopenharmony_ci eh_frame_vaddr))) 106da0c48c4Sopenharmony_ci return (void *) -1l; 107da0c48c4Sopenharmony_ci 108da0c48c4Sopenharmony_ci if (fde_count_encoding != DW_EH_PE_omit) 109da0c48c4Sopenharmony_ci { 110da0c48c4Sopenharmony_ci Dwarf_Word fde_count; 111da0c48c4Sopenharmony_ci if (unlikely (read_encoded_value (&dummy_cfi, fde_count_encoding, &h, 112da0c48c4Sopenharmony_ci &fde_count))) 113da0c48c4Sopenharmony_ci return (void *) -1l; 114da0c48c4Sopenharmony_ci if (fde_count != 0 && (size_t) fde_count == fde_count 115da0c48c4Sopenharmony_ci && fde_table_encoding != DW_EH_PE_omit 116da0c48c4Sopenharmony_ci && (fde_table_encoding &~ DW_EH_PE_signed) != DW_EH_PE_uleb128) 117da0c48c4Sopenharmony_ci { 118da0c48c4Sopenharmony_ci *table_entries = fde_count; 119da0c48c4Sopenharmony_ci *table_encoding = fde_table_encoding; 120da0c48c4Sopenharmony_ci return h; 121da0c48c4Sopenharmony_ci } 122da0c48c4Sopenharmony_ci } 123da0c48c4Sopenharmony_ci 124da0c48c4Sopenharmony_ci return NULL; 125da0c48c4Sopenharmony_ci} 126da0c48c4Sopenharmony_ci 127da0c48c4Sopenharmony_cistatic Dwarf_CFI * 128da0c48c4Sopenharmony_cigetcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr) 129da0c48c4Sopenharmony_ci{ 130da0c48c4Sopenharmony_ci Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz, 131da0c48c4Sopenharmony_ci ELF_T_BYTE); 132da0c48c4Sopenharmony_ci if (data == NULL || data->d_buf == NULL) 133da0c48c4Sopenharmony_ci { 134da0c48c4Sopenharmony_ci invalid_hdr: 135da0c48c4Sopenharmony_ci /* XXX might be read error or corrupt phdr */ 136da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_CFI); 137da0c48c4Sopenharmony_ci return NULL; 138da0c48c4Sopenharmony_ci } 139da0c48c4Sopenharmony_ci 140da0c48c4Sopenharmony_ci size_t vsize, dmax; 141da0c48c4Sopenharmony_ci Dwarf_Addr eh_frame_ptr; 142da0c48c4Sopenharmony_ci size_t search_table_entries = 0; 143da0c48c4Sopenharmony_ci uint8_t search_table_encoding = 0; 144da0c48c4Sopenharmony_ci const uint8_t *search_table = parse_eh_frame_hdr (data->d_buf, phdr->p_filesz, 145da0c48c4Sopenharmony_ci phdr->p_vaddr, ehdr, 146da0c48c4Sopenharmony_ci &eh_frame_ptr, 147da0c48c4Sopenharmony_ci &search_table_entries, 148da0c48c4Sopenharmony_ci &search_table_encoding); 149da0c48c4Sopenharmony_ci 150da0c48c4Sopenharmony_ci /* Make sure there is enough room for the entries in the table, 151da0c48c4Sopenharmony_ci each entry consists of 2 encoded values. */ 152da0c48c4Sopenharmony_ci vsize = encoded_value_size (data, ehdr->e_ident, search_table_encoding, 153da0c48c4Sopenharmony_ci NULL); 154da0c48c4Sopenharmony_ci dmax = phdr->p_filesz - (search_table - (const uint8_t *) data->d_buf); 155da0c48c4Sopenharmony_ci if (unlikely (search_table == (void *) -1l 156da0c48c4Sopenharmony_ci || vsize == 0 157da0c48c4Sopenharmony_ci || search_table_entries > (dmax / vsize) / 2)) 158da0c48c4Sopenharmony_ci goto invalid_hdr; 159da0c48c4Sopenharmony_ci 160da0c48c4Sopenharmony_ci Dwarf_Off eh_frame_offset = eh_frame_ptr - phdr->p_vaddr + phdr->p_offset; 161da0c48c4Sopenharmony_ci Dwarf_Word eh_frame_size = 0; 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci /* XXX we have no way without section headers to know the size 164da0c48c4Sopenharmony_ci of the .eh_frame data. Calculate the largest it might possibly be. 165da0c48c4Sopenharmony_ci This won't be wasteful if the file is already mmap'd, but if it isn't 166da0c48c4Sopenharmony_ci it might be quite excessive. */ 167da0c48c4Sopenharmony_ci size_t filesize; 168da0c48c4Sopenharmony_ci if (elf_rawfile (elf, &filesize) != NULL) 169da0c48c4Sopenharmony_ci eh_frame_size = filesize - eh_frame_offset; 170da0c48c4Sopenharmony_ci 171da0c48c4Sopenharmony_ci data = elf_getdata_rawchunk (elf, eh_frame_offset, eh_frame_size, ELF_T_BYTE); 172da0c48c4Sopenharmony_ci if (data == NULL) 173da0c48c4Sopenharmony_ci { 174da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); /* XXX might be read error */ 175da0c48c4Sopenharmony_ci return NULL; 176da0c48c4Sopenharmony_ci } 177da0c48c4Sopenharmony_ci Dwarf_CFI *cfi = allocate_cfi (elf, ehdr, eh_frame_ptr); 178da0c48c4Sopenharmony_ci if (cfi != NULL) 179da0c48c4Sopenharmony_ci { 180da0c48c4Sopenharmony_ci cfi->data = (Elf_Data_Scn *) data; 181da0c48c4Sopenharmony_ci 182da0c48c4Sopenharmony_ci if (search_table != NULL) 183da0c48c4Sopenharmony_ci { 184da0c48c4Sopenharmony_ci cfi->search_table = search_table; 185da0c48c4Sopenharmony_ci cfi->search_table_len = phdr->p_filesz; 186da0c48c4Sopenharmony_ci cfi->search_table_vaddr = phdr->p_vaddr; 187da0c48c4Sopenharmony_ci cfi->search_table_encoding = search_table_encoding; 188da0c48c4Sopenharmony_ci cfi->search_table_entries = search_table_entries; 189da0c48c4Sopenharmony_ci } 190da0c48c4Sopenharmony_ci } 191da0c48c4Sopenharmony_ci return cfi; 192da0c48c4Sopenharmony_ci} 193da0c48c4Sopenharmony_ci 194da0c48c4Sopenharmony_ci/* Search the phdrs for PT_GNU_EH_FRAME. */ 195da0c48c4Sopenharmony_cistatic Dwarf_CFI * 196da0c48c4Sopenharmony_cigetcfi_phdr (Elf *elf, const GElf_Ehdr *ehdr) 197da0c48c4Sopenharmony_ci{ 198da0c48c4Sopenharmony_ci size_t phnum; 199da0c48c4Sopenharmony_ci if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) 200da0c48c4Sopenharmony_ci return NULL; 201da0c48c4Sopenharmony_ci 202da0c48c4Sopenharmony_ci for (size_t i = 0; i < phnum; ++i) 203da0c48c4Sopenharmony_ci { 204da0c48c4Sopenharmony_ci GElf_Phdr phdr_mem; 205da0c48c4Sopenharmony_ci GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); 206da0c48c4Sopenharmony_ci if (unlikely (phdr == NULL)) 207da0c48c4Sopenharmony_ci return NULL; 208da0c48c4Sopenharmony_ci if (phdr->p_type == PT_GNU_EH_FRAME) 209da0c48c4Sopenharmony_ci return getcfi_gnu_eh_frame (elf, ehdr, phdr); 210da0c48c4Sopenharmony_ci } 211da0c48c4Sopenharmony_ci 212da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NO_DWARF); 213da0c48c4Sopenharmony_ci return NULL; 214da0c48c4Sopenharmony_ci} 215da0c48c4Sopenharmony_ci 216da0c48c4Sopenharmony_cistatic Dwarf_CFI * 217da0c48c4Sopenharmony_cigetcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, 218da0c48c4Sopenharmony_ci Elf_Scn *scn, GElf_Shdr *shdr, 219da0c48c4Sopenharmony_ci Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr) 220da0c48c4Sopenharmony_ci{ 221da0c48c4Sopenharmony_ci Elf_Data *data = elf_rawdata (scn, NULL); 222da0c48c4Sopenharmony_ci if (data == NULL || data->d_buf == NULL) 223da0c48c4Sopenharmony_ci { 224da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 225da0c48c4Sopenharmony_ci return NULL; 226da0c48c4Sopenharmony_ci } 227da0c48c4Sopenharmony_ci Dwarf_CFI *cfi = allocate_cfi (elf, ehdr, shdr->sh_addr); 228da0c48c4Sopenharmony_ci if (cfi != NULL) 229da0c48c4Sopenharmony_ci { 230da0c48c4Sopenharmony_ci cfi->data = (Elf_Data_Scn *) data; 231da0c48c4Sopenharmony_ci if (hdr_scn != NULL) 232da0c48c4Sopenharmony_ci { 233da0c48c4Sopenharmony_ci Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL); 234da0c48c4Sopenharmony_ci if (hdr_data != NULL && hdr_data->d_buf != NULL) 235da0c48c4Sopenharmony_ci { 236da0c48c4Sopenharmony_ci size_t vsize, dmax; 237da0c48c4Sopenharmony_ci GElf_Addr eh_frame_vaddr; 238da0c48c4Sopenharmony_ci cfi->search_table_vaddr = hdr_vaddr; 239da0c48c4Sopenharmony_ci cfi->search_table 240da0c48c4Sopenharmony_ci = parse_eh_frame_hdr (hdr_data->d_buf, hdr_data->d_size, 241da0c48c4Sopenharmony_ci hdr_vaddr, ehdr, &eh_frame_vaddr, 242da0c48c4Sopenharmony_ci &cfi->search_table_entries, 243da0c48c4Sopenharmony_ci &cfi->search_table_encoding); 244da0c48c4Sopenharmony_ci cfi->search_table_len = hdr_data->d_size; 245da0c48c4Sopenharmony_ci 246da0c48c4Sopenharmony_ci /* Make sure there is enough room for the entries in the table, 247da0c48c4Sopenharmony_ci each entry consists of 2 encoded values. */ 248da0c48c4Sopenharmony_ci vsize = encoded_value_size (hdr_data, ehdr->e_ident, 249da0c48c4Sopenharmony_ci cfi->search_table_encoding, NULL); 250da0c48c4Sopenharmony_ci dmax = hdr_data->d_size - (cfi->search_table 251da0c48c4Sopenharmony_ci - (const uint8_t *) hdr_data->d_buf); 252da0c48c4Sopenharmony_ci if (unlikely (cfi->search_table == (void *) -1l 253da0c48c4Sopenharmony_ci || vsize == 0 254da0c48c4Sopenharmony_ci || cfi->search_table_entries > (dmax / vsize) / 2)) 255da0c48c4Sopenharmony_ci { 256da0c48c4Sopenharmony_ci free (cfi); 257da0c48c4Sopenharmony_ci /* XXX might be read error or corrupt phdr */ 258da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_CFI); 259da0c48c4Sopenharmony_ci return NULL; 260da0c48c4Sopenharmony_ci } 261da0c48c4Sopenharmony_ci 262da0c48c4Sopenharmony_ci /* Sanity check. */ 263da0c48c4Sopenharmony_ci if (unlikely (eh_frame_vaddr != shdr->sh_addr)) 264da0c48c4Sopenharmony_ci cfi->search_table = NULL; 265da0c48c4Sopenharmony_ci } 266da0c48c4Sopenharmony_ci } 267da0c48c4Sopenharmony_ci } 268da0c48c4Sopenharmony_ci return cfi; 269da0c48c4Sopenharmony_ci} 270da0c48c4Sopenharmony_ci 271da0c48c4Sopenharmony_ci/* Search for the sections named ".eh_frame" and ".eh_frame_hdr". */ 272da0c48c4Sopenharmony_cistatic Dwarf_CFI * 273da0c48c4Sopenharmony_cigetcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr) 274da0c48c4Sopenharmony_ci{ 275da0c48c4Sopenharmony_ci size_t shstrndx; 276da0c48c4Sopenharmony_ci if (elf_getshdrstrndx (elf, &shstrndx) != 0) 277da0c48c4Sopenharmony_ci { 278da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_GETEHDR_ERROR); 279da0c48c4Sopenharmony_ci return NULL; 280da0c48c4Sopenharmony_ci } 281da0c48c4Sopenharmony_ci 282da0c48c4Sopenharmony_ci if (shstrndx != 0) 283da0c48c4Sopenharmony_ci { 284da0c48c4Sopenharmony_ci Elf_Scn *hdr_scn = NULL; 285da0c48c4Sopenharmony_ci GElf_Addr hdr_vaddr = 0; 286da0c48c4Sopenharmony_ci Elf_Scn *scn = NULL; 287da0c48c4Sopenharmony_ci while ((scn = elf_nextscn (elf, scn)) != NULL) 288da0c48c4Sopenharmony_ci { 289da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 290da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 291da0c48c4Sopenharmony_ci if (shdr == NULL) 292da0c48c4Sopenharmony_ci continue; 293da0c48c4Sopenharmony_ci const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); 294da0c48c4Sopenharmony_ci if (name == NULL) 295da0c48c4Sopenharmony_ci continue; 296da0c48c4Sopenharmony_ci if (!strcmp (name, ".eh_frame_hdr")) 297da0c48c4Sopenharmony_ci { 298da0c48c4Sopenharmony_ci hdr_scn = scn; 299da0c48c4Sopenharmony_ci hdr_vaddr = shdr->sh_addr; 300da0c48c4Sopenharmony_ci } 301da0c48c4Sopenharmony_ci else if (!strcmp (name, ".eh_frame")) 302da0c48c4Sopenharmony_ci { 303da0c48c4Sopenharmony_ci if (shdr->sh_type != SHT_NOBITS) 304da0c48c4Sopenharmony_ci return getcfi_scn_eh_frame (elf, ehdr, scn, shdr, 305da0c48c4Sopenharmony_ci hdr_scn, hdr_vaddr); 306da0c48c4Sopenharmony_ci else 307da0c48c4Sopenharmony_ci return NULL; 308da0c48c4Sopenharmony_ci } 309da0c48c4Sopenharmony_ci } 310da0c48c4Sopenharmony_ci } 311da0c48c4Sopenharmony_ci 312da0c48c4Sopenharmony_ci return (void *) -1l; 313da0c48c4Sopenharmony_ci} 314da0c48c4Sopenharmony_ci 315da0c48c4Sopenharmony_ciDwarf_CFI * 316da0c48c4Sopenharmony_cidwarf_getcfi_elf (Elf *elf) 317da0c48c4Sopenharmony_ci{ 318da0c48c4Sopenharmony_ci if (elf_kind (elf) != ELF_K_ELF) 319da0c48c4Sopenharmony_ci { 320da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOELF); 321da0c48c4Sopenharmony_ci return NULL; 322da0c48c4Sopenharmony_ci } 323da0c48c4Sopenharmony_ci 324da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem; 325da0c48c4Sopenharmony_ci GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 326da0c48c4Sopenharmony_ci if (unlikely (ehdr == NULL)) 327da0c48c4Sopenharmony_ci { 328da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 329da0c48c4Sopenharmony_ci return NULL; 330da0c48c4Sopenharmony_ci } 331da0c48c4Sopenharmony_ci 332da0c48c4Sopenharmony_ci Dwarf_CFI *result = getcfi_shdr (elf, ehdr); 333da0c48c4Sopenharmony_ci if (result == (void *) -1l) 334da0c48c4Sopenharmony_ci result = getcfi_phdr (elf, ehdr); 335da0c48c4Sopenharmony_ci 336da0c48c4Sopenharmony_ci return result; 337da0c48c4Sopenharmony_ci} 338da0c48c4Sopenharmony_ciINTDEF (dwarf_getcfi_elf) 339