1da0c48c4Sopenharmony_ci/* Create descriptor from ELF descriptor for processing file. 2da0c48c4Sopenharmony_ci Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 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 <system.h> 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_ci#include <assert.h> 36da0c48c4Sopenharmony_ci#include <stdbool.h> 37da0c48c4Sopenharmony_ci#include <stddef.h> 38da0c48c4Sopenharmony_ci#include <stdlib.h> 39da0c48c4Sopenharmony_ci#include <stdio.h> 40da0c48c4Sopenharmony_ci#include <string.h> 41da0c48c4Sopenharmony_ci#include <sys/types.h> 42da0c48c4Sopenharmony_ci#include <sys/stat.h> 43da0c48c4Sopenharmony_ci#include <fcntl.h> 44da0c48c4Sopenharmony_ci 45da0c48c4Sopenharmony_ci#include "libelfP.h" 46da0c48c4Sopenharmony_ci#include "libdwP.h" 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_ci 49da0c48c4Sopenharmony_ci/* Section names. (Note .debug_str_offsets is the largest 19 chars.) */ 50da0c48c4Sopenharmony_cistatic const char dwarf_scnnames[IDX_last][19] = 51da0c48c4Sopenharmony_ci{ 52da0c48c4Sopenharmony_ci [IDX_debug_info] = ".debug_info", 53da0c48c4Sopenharmony_ci [IDX_debug_types] = ".debug_types", 54da0c48c4Sopenharmony_ci [IDX_debug_abbrev] = ".debug_abbrev", 55da0c48c4Sopenharmony_ci [IDX_debug_addr] = ".debug_addr", 56da0c48c4Sopenharmony_ci [IDX_debug_aranges] = ".debug_aranges", 57da0c48c4Sopenharmony_ci [IDX_debug_line] = ".debug_line", 58da0c48c4Sopenharmony_ci [IDX_debug_line_str] = ".debug_line_str", 59da0c48c4Sopenharmony_ci [IDX_debug_frame] = ".debug_frame", 60da0c48c4Sopenharmony_ci [IDX_debug_loc] = ".debug_loc", 61da0c48c4Sopenharmony_ci [IDX_debug_loclists] = ".debug_loclists", 62da0c48c4Sopenharmony_ci [IDX_debug_pubnames] = ".debug_pubnames", 63da0c48c4Sopenharmony_ci [IDX_debug_str] = ".debug_str", 64da0c48c4Sopenharmony_ci [IDX_debug_str_offsets] = ".debug_str_offsets", 65da0c48c4Sopenharmony_ci [IDX_debug_macinfo] = ".debug_macinfo", 66da0c48c4Sopenharmony_ci [IDX_debug_macro] = ".debug_macro", 67da0c48c4Sopenharmony_ci [IDX_debug_ranges] = ".debug_ranges", 68da0c48c4Sopenharmony_ci [IDX_debug_rnglists] = ".debug_rnglists", 69da0c48c4Sopenharmony_ci [IDX_gnu_debugaltlink] = ".gnu_debugaltlink" 70da0c48c4Sopenharmony_ci}; 71da0c48c4Sopenharmony_ci#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0])) 72da0c48c4Sopenharmony_ci 73da0c48c4Sopenharmony_cistatic enum dwarf_type 74da0c48c4Sopenharmony_ciscn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn) 75da0c48c4Sopenharmony_ci{ 76da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 77da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 78da0c48c4Sopenharmony_ci if (shdr == NULL) 79da0c48c4Sopenharmony_ci return TYPE_UNKNOWN; 80da0c48c4Sopenharmony_ci 81da0c48c4Sopenharmony_ci const char *scnname = elf_strptr (result->elf, shstrndx, 82da0c48c4Sopenharmony_ci shdr->sh_name); 83da0c48c4Sopenharmony_ci if (scnname != NULL) 84da0c48c4Sopenharmony_ci { 85da0c48c4Sopenharmony_ci if (startswith (scnname, ".gnu.debuglto_.debug")) 86da0c48c4Sopenharmony_ci return TYPE_GNU_LTO; 87da0c48c4Sopenharmony_ci else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_")) 88da0c48c4Sopenharmony_ci { 89da0c48c4Sopenharmony_ci size_t len = strlen (scnname); 90da0c48c4Sopenharmony_ci if (strcmp (scnname + len - 4, ".dwo") == 0) 91da0c48c4Sopenharmony_ci return TYPE_DWO; 92da0c48c4Sopenharmony_ci else 93da0c48c4Sopenharmony_ci return TYPE_PLAIN; 94da0c48c4Sopenharmony_ci } 95da0c48c4Sopenharmony_ci } 96da0c48c4Sopenharmony_ci return TYPE_UNKNOWN; 97da0c48c4Sopenharmony_ci} 98da0c48c4Sopenharmony_cistatic Dwarf * 99da0c48c4Sopenharmony_cicheck_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp) 100da0c48c4Sopenharmony_ci{ 101da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 102da0c48c4Sopenharmony_ci GElf_Shdr *shdr; 103da0c48c4Sopenharmony_ci 104da0c48c4Sopenharmony_ci /* Get the section header data. */ 105da0c48c4Sopenharmony_ci shdr = gelf_getshdr (scn, &shdr_mem); 106da0c48c4Sopenharmony_ci if (shdr == NULL) 107da0c48c4Sopenharmony_ci /* We may read /proc/PID/mem with only program headers mapped and section 108da0c48c4Sopenharmony_ci headers out of the mapped pages. */ 109da0c48c4Sopenharmony_ci goto err; 110da0c48c4Sopenharmony_ci 111da0c48c4Sopenharmony_ci /* Ignore any SHT_NOBITS sections. Debugging sections should not 112da0c48c4Sopenharmony_ci have been stripped, but in case of a corrupt file we won't try 113da0c48c4Sopenharmony_ci to look at the missing data. */ 114da0c48c4Sopenharmony_ci if (unlikely (shdr->sh_type == SHT_NOBITS)) 115da0c48c4Sopenharmony_ci return result; 116da0c48c4Sopenharmony_ci 117da0c48c4Sopenharmony_ci /* Make sure the section is part of a section group only iff we 118da0c48c4Sopenharmony_ci really need it. If we are looking for the global (= non-section 119da0c48c4Sopenharmony_ci group debug info) we have to ignore all the info in section 120da0c48c4Sopenharmony_ci groups. If we are looking into a section group we cannot look at 121da0c48c4Sopenharmony_ci a section which isn't part of the section group. */ 122da0c48c4Sopenharmony_ci if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0) 123da0c48c4Sopenharmony_ci /* Ignore the section. */ 124da0c48c4Sopenharmony_ci return result; 125da0c48c4Sopenharmony_ci 126da0c48c4Sopenharmony_ci 127da0c48c4Sopenharmony_ci /* We recognize the DWARF section by their names. This is not very 128da0c48c4Sopenharmony_ci safe and stable but the best we can do. */ 129da0c48c4Sopenharmony_ci const char *scnname = elf_strptr (result->elf, shstrndx, 130da0c48c4Sopenharmony_ci shdr->sh_name); 131da0c48c4Sopenharmony_ci if (scnname == NULL) 132da0c48c4Sopenharmony_ci { 133da0c48c4Sopenharmony_ci /* The section name must be valid. Otherwise is the ELF file 134da0c48c4Sopenharmony_ci invalid. */ 135da0c48c4Sopenharmony_ci err: 136da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 137da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 138da0c48c4Sopenharmony_ci free (result); 139da0c48c4Sopenharmony_ci return NULL; 140da0c48c4Sopenharmony_ci } 141da0c48c4Sopenharmony_ci 142da0c48c4Sopenharmony_ci /* Recognize the various sections. Most names start with .debug_. 143da0c48c4Sopenharmony_ci They might be compressed (and start with .z). Or end with .dwo 144da0c48c4Sopenharmony_ci for split dwarf sections. Or start with .gnu.debuglto_ for 145da0c48c4Sopenharmony_ci LTO debug sections. We should only use one consistent set at 146da0c48c4Sopenharmony_ci a time. We prefer PLAIN over DWO over LTO. */ 147da0c48c4Sopenharmony_ci size_t cnt; 148da0c48c4Sopenharmony_ci bool gnu_compressed = false; 149da0c48c4Sopenharmony_ci for (cnt = 0; cnt < ndwarf_scnnames; ++cnt) 150da0c48c4Sopenharmony_ci { 151da0c48c4Sopenharmony_ci size_t dbglen = strlen (dwarf_scnnames[cnt]); 152da0c48c4Sopenharmony_ci size_t scnlen = strlen (scnname); 153da0c48c4Sopenharmony_ci if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0 154da0c48c4Sopenharmony_ci && (dbglen == scnlen 155da0c48c4Sopenharmony_ci || (scnlen == dbglen + 4 156da0c48c4Sopenharmony_ci && strstr (scnname, ".dwo") == scnname + dbglen))) 157da0c48c4Sopenharmony_ci { 158da0c48c4Sopenharmony_ci if (dbglen == scnlen) 159da0c48c4Sopenharmony_ci { 160da0c48c4Sopenharmony_ci if (result->type == TYPE_PLAIN) 161da0c48c4Sopenharmony_ci break; 162da0c48c4Sopenharmony_ci } 163da0c48c4Sopenharmony_ci else if (result->type == TYPE_DWO) 164da0c48c4Sopenharmony_ci break; 165da0c48c4Sopenharmony_ci } 166da0c48c4Sopenharmony_ci else if (scnname[0] == '.' && scnname[1] == 'z' 167da0c48c4Sopenharmony_ci && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1], 168da0c48c4Sopenharmony_ci dbglen - 1) == 0 169da0c48c4Sopenharmony_ci && (scnlen == dbglen + 1 170da0c48c4Sopenharmony_ci || (scnlen == dbglen + 5 171da0c48c4Sopenharmony_ci && strstr (scnname, 172da0c48c4Sopenharmony_ci ".dwo") == scnname + dbglen + 1)))) 173da0c48c4Sopenharmony_ci { 174da0c48c4Sopenharmony_ci if (scnlen == dbglen + 1) 175da0c48c4Sopenharmony_ci { 176da0c48c4Sopenharmony_ci if (result->type == TYPE_PLAIN) 177da0c48c4Sopenharmony_ci { 178da0c48c4Sopenharmony_ci gnu_compressed = true; 179da0c48c4Sopenharmony_ci break; 180da0c48c4Sopenharmony_ci } 181da0c48c4Sopenharmony_ci } 182da0c48c4Sopenharmony_ci else if (result->type <= TYPE_DWO) 183da0c48c4Sopenharmony_ci { 184da0c48c4Sopenharmony_ci gnu_compressed = true; 185da0c48c4Sopenharmony_ci break; 186da0c48c4Sopenharmony_ci } 187da0c48c4Sopenharmony_ci } 188da0c48c4Sopenharmony_ci else if (scnlen > 14 /* .gnu.debuglto_ prefix. */ 189da0c48c4Sopenharmony_ci && startswith (scnname, ".gnu.debuglto_") 190da0c48c4Sopenharmony_ci && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0) 191da0c48c4Sopenharmony_ci { 192da0c48c4Sopenharmony_ci if (result->type == TYPE_GNU_LTO) 193da0c48c4Sopenharmony_ci break; 194da0c48c4Sopenharmony_ci } 195da0c48c4Sopenharmony_ci } 196da0c48c4Sopenharmony_ci 197da0c48c4Sopenharmony_ci if (cnt >= ndwarf_scnnames) 198da0c48c4Sopenharmony_ci /* Not a debug section; ignore it. */ 199da0c48c4Sopenharmony_ci return result; 200da0c48c4Sopenharmony_ci 201da0c48c4Sopenharmony_ci if (unlikely (result->sectiondata[cnt] != NULL)) 202da0c48c4Sopenharmony_ci /* A section appears twice. That's bad. We ignore the section. */ 203da0c48c4Sopenharmony_ci return result; 204da0c48c4Sopenharmony_ci 205da0c48c4Sopenharmony_ci /* We cannot know whether or not a GNU compressed section has already 206da0c48c4Sopenharmony_ci been uncompressed or not, so ignore any errors. */ 207da0c48c4Sopenharmony_ci if (gnu_compressed) 208da0c48c4Sopenharmony_ci elf_compress_gnu (scn, 0, 0); 209da0c48c4Sopenharmony_ci 210da0c48c4Sopenharmony_ci if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 211da0c48c4Sopenharmony_ci { 212da0c48c4Sopenharmony_ci if (elf_compress (scn, 0, 0) < 0) 213da0c48c4Sopenharmony_ci { 214da0c48c4Sopenharmony_ci /* It would be nice if we could fail with a specific error. 215da0c48c4Sopenharmony_ci But we don't know if this was an essential section or not. 216da0c48c4Sopenharmony_ci So just continue for now. See also valid_p(). */ 217da0c48c4Sopenharmony_ci return result; 218da0c48c4Sopenharmony_ci } 219da0c48c4Sopenharmony_ci } 220da0c48c4Sopenharmony_ci 221da0c48c4Sopenharmony_ci /* Get the section data. */ 222da0c48c4Sopenharmony_ci Elf_Data *data = elf_getdata (scn, NULL); 223da0c48c4Sopenharmony_ci if (data == NULL) 224da0c48c4Sopenharmony_ci goto err; 225da0c48c4Sopenharmony_ci 226da0c48c4Sopenharmony_ci if (data->d_buf == NULL || data->d_size == 0) 227da0c48c4Sopenharmony_ci /* No data actually available, ignore it. */ 228da0c48c4Sopenharmony_ci return result; 229da0c48c4Sopenharmony_ci 230da0c48c4Sopenharmony_ci /* We can now read the section data into results. */ 231da0c48c4Sopenharmony_ci result->sectiondata[cnt] = data; 232da0c48c4Sopenharmony_ci 233da0c48c4Sopenharmony_ci return result; 234da0c48c4Sopenharmony_ci} 235da0c48c4Sopenharmony_ci 236da0c48c4Sopenharmony_ci 237da0c48c4Sopenharmony_ci/* Helper function to set debugdir field. We want to cache the dir 238da0c48c4Sopenharmony_ci where we found this Dwarf ELF file to locate alt and dwo files. */ 239da0c48c4Sopenharmony_cichar * 240da0c48c4Sopenharmony_ci__libdw_debugdir (int fd) 241da0c48c4Sopenharmony_ci{ 242da0c48c4Sopenharmony_ci /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */ 243da0c48c4Sopenharmony_ci char devfdpath[25]; 244da0c48c4Sopenharmony_ci sprintf (devfdpath, "/proc/self/fd/%u", fd); 245da0c48c4Sopenharmony_ci char *fdpath = realpath (devfdpath, NULL); 246da0c48c4Sopenharmony_ci char *fddir; 247da0c48c4Sopenharmony_ci if (fdpath != NULL && fdpath[0] == '/' 248da0c48c4Sopenharmony_ci && (fddir = strrchr (fdpath, '/')) != NULL) 249da0c48c4Sopenharmony_ci { 250da0c48c4Sopenharmony_ci *++fddir = '\0'; 251da0c48c4Sopenharmony_ci return fdpath; 252da0c48c4Sopenharmony_ci } 253da0c48c4Sopenharmony_ci return NULL; 254da0c48c4Sopenharmony_ci} 255da0c48c4Sopenharmony_ci 256da0c48c4Sopenharmony_ci 257da0c48c4Sopenharmony_ci/* Check whether all the necessary DWARF information is available. */ 258da0c48c4Sopenharmony_cistatic Dwarf * 259da0c48c4Sopenharmony_civalid_p (Dwarf *result) 260da0c48c4Sopenharmony_ci{ 261da0c48c4Sopenharmony_ci /* We looked at all the sections. Now determine whether all the 262da0c48c4Sopenharmony_ci sections with debugging information we need are there. 263da0c48c4Sopenharmony_ci 264da0c48c4Sopenharmony_ci Require at least one section that can be read "standalone". */ 265da0c48c4Sopenharmony_ci if (likely (result != NULL) 266da0c48c4Sopenharmony_ci && unlikely (result->sectiondata[IDX_debug_info] == NULL 267da0c48c4Sopenharmony_ci && result->sectiondata[IDX_debug_line] == NULL 268da0c48c4Sopenharmony_ci && result->sectiondata[IDX_debug_frame] == NULL)) 269da0c48c4Sopenharmony_ci { 270da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 271da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NO_DWARF); 272da0c48c4Sopenharmony_ci free (result); 273da0c48c4Sopenharmony_ci result = NULL; 274da0c48c4Sopenharmony_ci } 275da0c48c4Sopenharmony_ci 276da0c48c4Sopenharmony_ci /* We are setting up some "fake" CUs, which need an address size. 277da0c48c4Sopenharmony_ci Check the ELF class to come up with something reasonable. */ 278da0c48c4Sopenharmony_ci int elf_addr_size = 8; 279da0c48c4Sopenharmony_ci if (result != NULL) 280da0c48c4Sopenharmony_ci { 281da0c48c4Sopenharmony_ci GElf_Ehdr ehdr; 282da0c48c4Sopenharmony_ci if (gelf_getehdr (result->elf, &ehdr) == NULL) 283da0c48c4Sopenharmony_ci { 284da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 285da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 286da0c48c4Sopenharmony_ci free (result); 287da0c48c4Sopenharmony_ci result = NULL; 288da0c48c4Sopenharmony_ci } 289da0c48c4Sopenharmony_ci else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 290da0c48c4Sopenharmony_ci elf_addr_size = 4; 291da0c48c4Sopenharmony_ci } 292da0c48c4Sopenharmony_ci 293da0c48c4Sopenharmony_ci /* For dwarf_location_attr () we need a "fake" CU to indicate 294da0c48c4Sopenharmony_ci where the "fake" attribute data comes from. This is a block 295da0c48c4Sopenharmony_ci inside the .debug_loc or .debug_loclists section. */ 296da0c48c4Sopenharmony_ci if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL) 297da0c48c4Sopenharmony_ci { 298da0c48c4Sopenharmony_ci result->fake_loc_cu = malloc (sizeof (Dwarf_CU)); 299da0c48c4Sopenharmony_ci if (unlikely (result->fake_loc_cu == NULL)) 300da0c48c4Sopenharmony_ci { 301da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 302da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); 303da0c48c4Sopenharmony_ci free (result); 304da0c48c4Sopenharmony_ci result = NULL; 305da0c48c4Sopenharmony_ci } 306da0c48c4Sopenharmony_ci else 307da0c48c4Sopenharmony_ci { 308da0c48c4Sopenharmony_ci result->fake_loc_cu->sec_idx = IDX_debug_loc; 309da0c48c4Sopenharmony_ci result->fake_loc_cu->dbg = result; 310da0c48c4Sopenharmony_ci result->fake_loc_cu->startp 311da0c48c4Sopenharmony_ci = result->sectiondata[IDX_debug_loc]->d_buf; 312da0c48c4Sopenharmony_ci result->fake_loc_cu->endp 313da0c48c4Sopenharmony_ci = (result->sectiondata[IDX_debug_loc]->d_buf 314da0c48c4Sopenharmony_ci + result->sectiondata[IDX_debug_loc]->d_size); 315da0c48c4Sopenharmony_ci result->fake_loc_cu->locs = NULL; 316da0c48c4Sopenharmony_ci result->fake_loc_cu->address_size = elf_addr_size; 317da0c48c4Sopenharmony_ci result->fake_loc_cu->offset_size = 4; 318da0c48c4Sopenharmony_ci result->fake_loc_cu->version = 4; 319da0c48c4Sopenharmony_ci result->fake_loc_cu->split = NULL; 320da0c48c4Sopenharmony_ci } 321da0c48c4Sopenharmony_ci } 322da0c48c4Sopenharmony_ci 323da0c48c4Sopenharmony_ci if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL) 324da0c48c4Sopenharmony_ci { 325da0c48c4Sopenharmony_ci result->fake_loclists_cu = malloc (sizeof (Dwarf_CU)); 326da0c48c4Sopenharmony_ci if (unlikely (result->fake_loclists_cu == NULL)) 327da0c48c4Sopenharmony_ci { 328da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 329da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); 330da0c48c4Sopenharmony_ci free (result->fake_loc_cu); 331da0c48c4Sopenharmony_ci free (result); 332da0c48c4Sopenharmony_ci result = NULL; 333da0c48c4Sopenharmony_ci } 334da0c48c4Sopenharmony_ci else 335da0c48c4Sopenharmony_ci { 336da0c48c4Sopenharmony_ci result->fake_loclists_cu->sec_idx = IDX_debug_loclists; 337da0c48c4Sopenharmony_ci result->fake_loclists_cu->dbg = result; 338da0c48c4Sopenharmony_ci result->fake_loclists_cu->startp 339da0c48c4Sopenharmony_ci = result->sectiondata[IDX_debug_loclists]->d_buf; 340da0c48c4Sopenharmony_ci result->fake_loclists_cu->endp 341da0c48c4Sopenharmony_ci = (result->sectiondata[IDX_debug_loclists]->d_buf 342da0c48c4Sopenharmony_ci + result->sectiondata[IDX_debug_loclists]->d_size); 343da0c48c4Sopenharmony_ci result->fake_loclists_cu->locs = NULL; 344da0c48c4Sopenharmony_ci result->fake_loclists_cu->address_size = elf_addr_size; 345da0c48c4Sopenharmony_ci result->fake_loclists_cu->offset_size = 4; 346da0c48c4Sopenharmony_ci result->fake_loclists_cu->version = 5; 347da0c48c4Sopenharmony_ci result->fake_loclists_cu->split = NULL; 348da0c48c4Sopenharmony_ci } 349da0c48c4Sopenharmony_ci } 350da0c48c4Sopenharmony_ci 351da0c48c4Sopenharmony_ci /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index 352da0c48c4Sopenharmony_ci the dwarf_location_attr () will need a "fake" address CU to 353da0c48c4Sopenharmony_ci indicate where the attribute data comes from. This is a just 354da0c48c4Sopenharmony_ci inside the .debug_addr section, if it exists. */ 355da0c48c4Sopenharmony_ci if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL) 356da0c48c4Sopenharmony_ci { 357da0c48c4Sopenharmony_ci result->fake_addr_cu = malloc (sizeof (Dwarf_CU)); 358da0c48c4Sopenharmony_ci if (unlikely (result->fake_addr_cu == NULL)) 359da0c48c4Sopenharmony_ci { 360da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 361da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); 362da0c48c4Sopenharmony_ci free (result->fake_loc_cu); 363da0c48c4Sopenharmony_ci free (result->fake_loclists_cu); 364da0c48c4Sopenharmony_ci free (result); 365da0c48c4Sopenharmony_ci result = NULL; 366da0c48c4Sopenharmony_ci } 367da0c48c4Sopenharmony_ci else 368da0c48c4Sopenharmony_ci { 369da0c48c4Sopenharmony_ci result->fake_addr_cu->sec_idx = IDX_debug_addr; 370da0c48c4Sopenharmony_ci result->fake_addr_cu->dbg = result; 371da0c48c4Sopenharmony_ci result->fake_addr_cu->startp 372da0c48c4Sopenharmony_ci = result->sectiondata[IDX_debug_addr]->d_buf; 373da0c48c4Sopenharmony_ci result->fake_addr_cu->endp 374da0c48c4Sopenharmony_ci = (result->sectiondata[IDX_debug_addr]->d_buf 375da0c48c4Sopenharmony_ci + result->sectiondata[IDX_debug_addr]->d_size); 376da0c48c4Sopenharmony_ci result->fake_addr_cu->locs = NULL; 377da0c48c4Sopenharmony_ci result->fake_addr_cu->address_size = elf_addr_size; 378da0c48c4Sopenharmony_ci result->fake_addr_cu->offset_size = 4; 379da0c48c4Sopenharmony_ci result->fake_addr_cu->version = 5; 380da0c48c4Sopenharmony_ci result->fake_addr_cu->split = NULL; 381da0c48c4Sopenharmony_ci } 382da0c48c4Sopenharmony_ci } 383da0c48c4Sopenharmony_ci 384da0c48c4Sopenharmony_ci if (result != NULL) 385da0c48c4Sopenharmony_ci result->debugdir = __libdw_debugdir (result->elf->fildes); 386da0c48c4Sopenharmony_ci 387da0c48c4Sopenharmony_ci return result; 388da0c48c4Sopenharmony_ci} 389da0c48c4Sopenharmony_ci 390da0c48c4Sopenharmony_ci 391da0c48c4Sopenharmony_cistatic Dwarf * 392da0c48c4Sopenharmony_ciglobal_read (Dwarf *result, Elf *elf, size_t shstrndx) 393da0c48c4Sopenharmony_ci{ 394da0c48c4Sopenharmony_ci Elf_Scn *scn = NULL; 395da0c48c4Sopenharmony_ci 396da0c48c4Sopenharmony_ci /* First check the type (PLAIN, DWO, LTO) we are looking for. We 397da0c48c4Sopenharmony_ci prefer PLAIN if available over DWO, over LTO. */ 398da0c48c4Sopenharmony_ci while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN) 399da0c48c4Sopenharmony_ci { 400da0c48c4Sopenharmony_ci enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn); 401da0c48c4Sopenharmony_ci if (type > result->type) 402da0c48c4Sopenharmony_ci result->type = type; 403da0c48c4Sopenharmony_ci } 404da0c48c4Sopenharmony_ci 405da0c48c4Sopenharmony_ci scn = NULL; 406da0c48c4Sopenharmony_ci while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL) 407da0c48c4Sopenharmony_ci result = check_section (result, shstrndx, scn, false); 408da0c48c4Sopenharmony_ci 409da0c48c4Sopenharmony_ci return valid_p (result); 410da0c48c4Sopenharmony_ci} 411da0c48c4Sopenharmony_ci 412da0c48c4Sopenharmony_ci 413da0c48c4Sopenharmony_cistatic Dwarf * 414da0c48c4Sopenharmony_ciscngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp) 415da0c48c4Sopenharmony_ci{ 416da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 417da0c48c4Sopenharmony_ci GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem); 418da0c48c4Sopenharmony_ci if (shdr == NULL) 419da0c48c4Sopenharmony_ci { 420da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 421da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 422da0c48c4Sopenharmony_ci free (result); 423da0c48c4Sopenharmony_ci return NULL; 424da0c48c4Sopenharmony_ci } 425da0c48c4Sopenharmony_ci 426da0c48c4Sopenharmony_ci if ((shdr->sh_flags & SHF_COMPRESSED) != 0 427da0c48c4Sopenharmony_ci && elf_compress (scngrp, 0, 0) < 0) 428da0c48c4Sopenharmony_ci { 429da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 430da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_COMPRESSED_ERROR); 431da0c48c4Sopenharmony_ci free (result); 432da0c48c4Sopenharmony_ci return NULL; 433da0c48c4Sopenharmony_ci } 434da0c48c4Sopenharmony_ci 435da0c48c4Sopenharmony_ci /* SCNGRP is the section descriptor for a section group which might 436da0c48c4Sopenharmony_ci contain debug sections. */ 437da0c48c4Sopenharmony_ci Elf_Data *data = elf_getdata (scngrp, NULL); 438da0c48c4Sopenharmony_ci if (data == NULL) 439da0c48c4Sopenharmony_ci { 440da0c48c4Sopenharmony_ci /* We cannot read the section content. Fail! */ 441da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 442da0c48c4Sopenharmony_ci free (result); 443da0c48c4Sopenharmony_ci return NULL; 444da0c48c4Sopenharmony_ci } 445da0c48c4Sopenharmony_ci 446da0c48c4Sopenharmony_ci /* The content of the section is a number of 32-bit words which 447da0c48c4Sopenharmony_ci represent section indices. The first word is a flag word. */ 448da0c48c4Sopenharmony_ci Elf32_Word *scnidx = (Elf32_Word *) data->d_buf; 449da0c48c4Sopenharmony_ci size_t cnt; 450da0c48c4Sopenharmony_ci 451da0c48c4Sopenharmony_ci /* First check the type (PLAIN, DWO, LTO) we are looking for. We 452da0c48c4Sopenharmony_ci prefer PLAIN if available over DWO, over LTO. */ 453da0c48c4Sopenharmony_ci for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt) 454da0c48c4Sopenharmony_ci { 455da0c48c4Sopenharmony_ci Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); 456da0c48c4Sopenharmony_ci if (scn == NULL) 457da0c48c4Sopenharmony_ci { 458da0c48c4Sopenharmony_ci /* A section group refers to a non-existing section. Should 459da0c48c4Sopenharmony_ci never happen. */ 460da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 461da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 462da0c48c4Sopenharmony_ci free (result); 463da0c48c4Sopenharmony_ci return NULL; 464da0c48c4Sopenharmony_ci } 465da0c48c4Sopenharmony_ci 466da0c48c4Sopenharmony_ci enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn); 467da0c48c4Sopenharmony_ci if (type > result->type) 468da0c48c4Sopenharmony_ci result->type = type; 469da0c48c4Sopenharmony_ci } 470da0c48c4Sopenharmony_ci 471da0c48c4Sopenharmony_ci for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt) 472da0c48c4Sopenharmony_ci { 473da0c48c4Sopenharmony_ci Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); 474da0c48c4Sopenharmony_ci assert (scn != NULL); // checked above 475da0c48c4Sopenharmony_ci result = check_section (result, shstrndx, scn, true); 476da0c48c4Sopenharmony_ci if (result == NULL) 477da0c48c4Sopenharmony_ci break; 478da0c48c4Sopenharmony_ci } 479da0c48c4Sopenharmony_ci 480da0c48c4Sopenharmony_ci return valid_p (result); 481da0c48c4Sopenharmony_ci} 482da0c48c4Sopenharmony_ci 483da0c48c4Sopenharmony_ci 484da0c48c4Sopenharmony_ciDwarf * 485da0c48c4Sopenharmony_cidwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp) 486da0c48c4Sopenharmony_ci{ 487da0c48c4Sopenharmony_ci GElf_Ehdr *ehdr; 488da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem; 489da0c48c4Sopenharmony_ci 490da0c48c4Sopenharmony_ci /* Get the ELF header of the file. We need various pieces of 491da0c48c4Sopenharmony_ci information from it. */ 492da0c48c4Sopenharmony_ci ehdr = gelf_getehdr (elf, &ehdr_mem); 493da0c48c4Sopenharmony_ci if (ehdr == NULL) 494da0c48c4Sopenharmony_ci { 495da0c48c4Sopenharmony_ci if (elf_kind (elf) != ELF_K_ELF) 496da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOELF); 497da0c48c4Sopenharmony_ci else 498da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_GETEHDR_ERROR); 499da0c48c4Sopenharmony_ci 500da0c48c4Sopenharmony_ci return NULL; 501da0c48c4Sopenharmony_ci } 502da0c48c4Sopenharmony_ci 503da0c48c4Sopenharmony_ci 504da0c48c4Sopenharmony_ci /* Default memory allocation size. */ 505da0c48c4Sopenharmony_ci size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *); 506da0c48c4Sopenharmony_ci assert (sizeof (struct Dwarf) < mem_default_size); 507da0c48c4Sopenharmony_ci 508da0c48c4Sopenharmony_ci /* Allocate the data structure. */ 509da0c48c4Sopenharmony_ci Dwarf *result = calloc (1, sizeof (Dwarf)); 510da0c48c4Sopenharmony_ci if (unlikely (result == NULL) 511da0c48c4Sopenharmony_ci || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0)) 512da0c48c4Sopenharmony_ci { 513da0c48c4Sopenharmony_ci free (result); 514da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); 515da0c48c4Sopenharmony_ci return NULL; 516da0c48c4Sopenharmony_ci } 517da0c48c4Sopenharmony_ci 518da0c48c4Sopenharmony_ci /* Fill in some values. */ 519da0c48c4Sopenharmony_ci if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB) 520da0c48c4Sopenharmony_ci || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)) 521da0c48c4Sopenharmony_ci result->other_byte_order = true; 522da0c48c4Sopenharmony_ci 523da0c48c4Sopenharmony_ci result->elf = elf; 524da0c48c4Sopenharmony_ci result->alt_fd = -1; 525da0c48c4Sopenharmony_ci 526da0c48c4Sopenharmony_ci /* Initialize the memory handling. Initial blocks are allocated on first 527da0c48c4Sopenharmony_ci actual allocation. */ 528da0c48c4Sopenharmony_ci result->mem_default_size = mem_default_size; 529da0c48c4Sopenharmony_ci result->oom_handler = __libdw_oom; 530da0c48c4Sopenharmony_ci if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0) 531da0c48c4Sopenharmony_ci { 532da0c48c4Sopenharmony_ci free (result); 533da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NOMEM); /* no memory. */ 534da0c48c4Sopenharmony_ci return NULL; 535da0c48c4Sopenharmony_ci } 536da0c48c4Sopenharmony_ci result->mem_stacks = 0; 537da0c48c4Sopenharmony_ci result->mem_tails = NULL; 538da0c48c4Sopenharmony_ci 539da0c48c4Sopenharmony_ci if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR) 540da0c48c4Sopenharmony_ci { 541da0c48c4Sopenharmony_ci /* All sections are recognized by name, so pass the section header 542da0c48c4Sopenharmony_ci string index along to easily get the section names. */ 543da0c48c4Sopenharmony_ci size_t shstrndx; 544da0c48c4Sopenharmony_ci if (elf_getshdrstrndx (elf, &shstrndx) != 0) 545da0c48c4Sopenharmony_ci { 546da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 547da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_ELF); 548da0c48c4Sopenharmony_ci free (result); 549da0c48c4Sopenharmony_ci return NULL; 550da0c48c4Sopenharmony_ci } 551da0c48c4Sopenharmony_ci 552da0c48c4Sopenharmony_ci /* If the caller provides a section group we get the DWARF 553da0c48c4Sopenharmony_ci sections only from this section group. Otherwise we search 554da0c48c4Sopenharmony_ci for the first section with the required name. Further 555da0c48c4Sopenharmony_ci sections with the name are ignored. The DWARF specification 556da0c48c4Sopenharmony_ci does not really say this is allowed. */ 557da0c48c4Sopenharmony_ci if (scngrp == NULL) 558da0c48c4Sopenharmony_ci return global_read (result, elf, shstrndx); 559da0c48c4Sopenharmony_ci else 560da0c48c4Sopenharmony_ci return scngrp_read (result, elf, shstrndx, scngrp); 561da0c48c4Sopenharmony_ci } 562da0c48c4Sopenharmony_ci else if (cmd == DWARF_C_WRITE) 563da0c48c4Sopenharmony_ci { 564da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 565da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_UNIMPL); 566da0c48c4Sopenharmony_ci free (result); 567da0c48c4Sopenharmony_ci return NULL; 568da0c48c4Sopenharmony_ci } 569da0c48c4Sopenharmony_ci 570da0c48c4Sopenharmony_ci Dwarf_Sig8_Hash_free (&result->sig8_hash); 571da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_CMD); 572da0c48c4Sopenharmony_ci free (result); 573da0c48c4Sopenharmony_ci return NULL; 574da0c48c4Sopenharmony_ci} 575da0c48c4Sopenharmony_ciINTDEF(dwarf_begin_elf) 576