1da0c48c4Sopenharmony_ci/* Get Dwarf Frame state for target core file. 2da0c48c4Sopenharmony_ci Copyright (C) 2013, 2014 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 "libdwflP.h" 34da0c48c4Sopenharmony_ci#include <fcntl.h> 35da0c48c4Sopenharmony_ci#include "system.h" 36da0c48c4Sopenharmony_ci 37da0c48c4Sopenharmony_ci#include "../libdw/memory-access.h" 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_cistruct core_arg 40da0c48c4Sopenharmony_ci{ 41da0c48c4Sopenharmony_ci Elf *core; 42da0c48c4Sopenharmony_ci Elf_Data *note_data; 43da0c48c4Sopenharmony_ci size_t thread_note_offset; 44da0c48c4Sopenharmony_ci Ebl *ebl; 45da0c48c4Sopenharmony_ci}; 46da0c48c4Sopenharmony_ci 47da0c48c4Sopenharmony_cistruct thread_arg 48da0c48c4Sopenharmony_ci{ 49da0c48c4Sopenharmony_ci struct core_arg *core_arg; 50da0c48c4Sopenharmony_ci size_t note_offset; 51da0c48c4Sopenharmony_ci}; 52da0c48c4Sopenharmony_ci 53da0c48c4Sopenharmony_cistatic bool 54da0c48c4Sopenharmony_cicore_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, 55da0c48c4Sopenharmony_ci void *dwfl_arg) 56da0c48c4Sopenharmony_ci{ 57da0c48c4Sopenharmony_ci Dwfl_Process *process = dwfl->process; 58da0c48c4Sopenharmony_ci struct core_arg *core_arg = dwfl_arg; 59da0c48c4Sopenharmony_ci Elf *core = core_arg->core; 60da0c48c4Sopenharmony_ci assert (core != NULL); 61da0c48c4Sopenharmony_ci static size_t phnum; 62da0c48c4Sopenharmony_ci if (elf_getphdrnum (core, &phnum) < 0) 63da0c48c4Sopenharmony_ci { 64da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_LIBELF); 65da0c48c4Sopenharmony_ci return false; 66da0c48c4Sopenharmony_ci } 67da0c48c4Sopenharmony_ci for (size_t cnt = 0; cnt < phnum; ++cnt) 68da0c48c4Sopenharmony_ci { 69da0c48c4Sopenharmony_ci GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem); 70da0c48c4Sopenharmony_ci if (phdr == NULL || phdr->p_type != PT_LOAD) 71da0c48c4Sopenharmony_ci continue; 72da0c48c4Sopenharmony_ci /* Bias is zero here, a core file itself has no bias. */ 73da0c48c4Sopenharmony_ci GElf_Addr start = __libdwfl_segment_start (dwfl, phdr->p_vaddr); 74da0c48c4Sopenharmony_ci GElf_Addr end = __libdwfl_segment_end (dwfl, 75da0c48c4Sopenharmony_ci phdr->p_vaddr + phdr->p_memsz); 76da0c48c4Sopenharmony_ci unsigned bytes = ebl_get_elfclass (process->ebl) == ELFCLASS64 ? 8 : 4; 77da0c48c4Sopenharmony_ci if (addr < start || addr + bytes > end) 78da0c48c4Sopenharmony_ci continue; 79da0c48c4Sopenharmony_ci Elf_Data *data; 80da0c48c4Sopenharmony_ci data = elf_getdata_rawchunk (core, phdr->p_offset + addr - start, 81da0c48c4Sopenharmony_ci bytes, ELF_T_ADDR); 82da0c48c4Sopenharmony_ci if (data == NULL) 83da0c48c4Sopenharmony_ci { 84da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_LIBELF); 85da0c48c4Sopenharmony_ci return false; 86da0c48c4Sopenharmony_ci } 87da0c48c4Sopenharmony_ci assert (data->d_size == bytes); 88da0c48c4Sopenharmony_ci if (bytes == 8) 89da0c48c4Sopenharmony_ci *result = read_8ubyte_unaligned_noncvt (data->d_buf); 90da0c48c4Sopenharmony_ci else 91da0c48c4Sopenharmony_ci *result = read_4ubyte_unaligned_noncvt (data->d_buf); 92da0c48c4Sopenharmony_ci return true; 93da0c48c4Sopenharmony_ci } 94da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE); 95da0c48c4Sopenharmony_ci return false; 96da0c48c4Sopenharmony_ci} 97da0c48c4Sopenharmony_ci 98da0c48c4Sopenharmony_cistatic pid_t 99da0c48c4Sopenharmony_cicore_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg, 100da0c48c4Sopenharmony_ci void **thread_argp) 101da0c48c4Sopenharmony_ci{ 102da0c48c4Sopenharmony_ci struct core_arg *core_arg = dwfl_arg; 103da0c48c4Sopenharmony_ci Elf *core = core_arg->core; 104da0c48c4Sopenharmony_ci GElf_Nhdr nhdr; 105da0c48c4Sopenharmony_ci size_t name_offset; 106da0c48c4Sopenharmony_ci size_t desc_offset; 107da0c48c4Sopenharmony_ci Elf_Data *note_data = core_arg->note_data; 108da0c48c4Sopenharmony_ci size_t offset; 109da0c48c4Sopenharmony_ci 110da0c48c4Sopenharmony_ci struct thread_arg *thread_arg; 111da0c48c4Sopenharmony_ci if (*thread_argp == NULL) 112da0c48c4Sopenharmony_ci { 113da0c48c4Sopenharmony_ci core_arg->thread_note_offset = 0; 114da0c48c4Sopenharmony_ci thread_arg = malloc (sizeof (*thread_arg)); 115da0c48c4Sopenharmony_ci if (thread_arg == NULL) 116da0c48c4Sopenharmony_ci { 117da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_NOMEM); 118da0c48c4Sopenharmony_ci return -1; 119da0c48c4Sopenharmony_ci } 120da0c48c4Sopenharmony_ci thread_arg->core_arg = core_arg; 121da0c48c4Sopenharmony_ci *thread_argp = thread_arg; 122da0c48c4Sopenharmony_ci } 123da0c48c4Sopenharmony_ci else 124da0c48c4Sopenharmony_ci thread_arg = (struct thread_arg *) *thread_argp; 125da0c48c4Sopenharmony_ci 126da0c48c4Sopenharmony_ci while (offset = core_arg->thread_note_offset, offset < note_data->d_size 127da0c48c4Sopenharmony_ci && (core_arg->thread_note_offset = gelf_getnote (note_data, offset, 128da0c48c4Sopenharmony_ci &nhdr, &name_offset, 129da0c48c4Sopenharmony_ci &desc_offset)) > 0) 130da0c48c4Sopenharmony_ci { 131da0c48c4Sopenharmony_ci /* Do not check NAME for now, help broken Linux kernels. */ 132da0c48c4Sopenharmony_ci const char *name = (nhdr.n_namesz == 0 133da0c48c4Sopenharmony_ci ? "" : note_data->d_buf + name_offset); 134da0c48c4Sopenharmony_ci const char *desc = note_data->d_buf + desc_offset; 135da0c48c4Sopenharmony_ci GElf_Word regs_offset; 136da0c48c4Sopenharmony_ci size_t nregloc; 137da0c48c4Sopenharmony_ci const Ebl_Register_Location *reglocs; 138da0c48c4Sopenharmony_ci size_t nitems; 139da0c48c4Sopenharmony_ci const Ebl_Core_Item *items; 140da0c48c4Sopenharmony_ci if (! ebl_core_note (core_arg->ebl, &nhdr, name, desc, 141da0c48c4Sopenharmony_ci ®s_offset, &nregloc, ®locs, &nitems, &items)) 142da0c48c4Sopenharmony_ci { 143da0c48c4Sopenharmony_ci /* This note may be just not recognized, skip it. */ 144da0c48c4Sopenharmony_ci continue; 145da0c48c4Sopenharmony_ci } 146da0c48c4Sopenharmony_ci if (nhdr.n_type != NT_PRSTATUS) 147da0c48c4Sopenharmony_ci continue; 148da0c48c4Sopenharmony_ci const Ebl_Core_Item *item; 149da0c48c4Sopenharmony_ci for (item = items; item < items + nitems; item++) 150da0c48c4Sopenharmony_ci if (strcmp (item->name, "pid") == 0) 151da0c48c4Sopenharmony_ci break; 152da0c48c4Sopenharmony_ci if (item == items + nitems) 153da0c48c4Sopenharmony_ci continue; 154da0c48c4Sopenharmony_ci uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); 155da0c48c4Sopenharmony_ci val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 156da0c48c4Sopenharmony_ci ? be32toh (val32) : le32toh (val32)); 157da0c48c4Sopenharmony_ci pid_t tid = (int32_t) val32; 158da0c48c4Sopenharmony_ci eu_static_assert (sizeof val32 <= sizeof tid); 159da0c48c4Sopenharmony_ci thread_arg->note_offset = offset; 160da0c48c4Sopenharmony_ci return tid; 161da0c48c4Sopenharmony_ci } 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci free (thread_arg); 164da0c48c4Sopenharmony_ci return 0; 165da0c48c4Sopenharmony_ci} 166da0c48c4Sopenharmony_ci 167da0c48c4Sopenharmony_cistatic bool 168da0c48c4Sopenharmony_cicore_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp) 169da0c48c4Sopenharmony_ci{ 170da0c48c4Sopenharmony_ci struct thread_arg *thread_arg = thread_arg_voidp; 171da0c48c4Sopenharmony_ci struct core_arg *core_arg = thread_arg->core_arg; 172da0c48c4Sopenharmony_ci Elf *core = core_arg->core; 173da0c48c4Sopenharmony_ci size_t offset = thread_arg->note_offset; 174da0c48c4Sopenharmony_ci GElf_Nhdr nhdr; 175da0c48c4Sopenharmony_ci size_t name_offset; 176da0c48c4Sopenharmony_ci size_t desc_offset; 177da0c48c4Sopenharmony_ci Elf_Data *note_data = core_arg->note_data; 178da0c48c4Sopenharmony_ci size_t nregs = ebl_frame_nregs (core_arg->ebl); 179da0c48c4Sopenharmony_ci assert (nregs > 0); 180da0c48c4Sopenharmony_ci assert (offset < note_data->d_size); 181da0c48c4Sopenharmony_ci size_t getnote_err = gelf_getnote (note_data, offset, &nhdr, &name_offset, 182da0c48c4Sopenharmony_ci &desc_offset); 183da0c48c4Sopenharmony_ci /* __libdwfl_attach_state_for_core already verified the note is there. */ 184da0c48c4Sopenharmony_ci if (getnote_err == 0) 185da0c48c4Sopenharmony_ci return false; 186da0c48c4Sopenharmony_ci /* Do not check NAME for now, help broken Linux kernels. */ 187da0c48c4Sopenharmony_ci const char *name = (nhdr.n_namesz == 0 188da0c48c4Sopenharmony_ci ? "" : note_data->d_buf + name_offset); 189da0c48c4Sopenharmony_ci const char *desc = note_data->d_buf + desc_offset; 190da0c48c4Sopenharmony_ci GElf_Word regs_offset; 191da0c48c4Sopenharmony_ci size_t nregloc; 192da0c48c4Sopenharmony_ci const Ebl_Register_Location *reglocs; 193da0c48c4Sopenharmony_ci size_t nitems; 194da0c48c4Sopenharmony_ci const Ebl_Core_Item *items; 195da0c48c4Sopenharmony_ci int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, desc, 196da0c48c4Sopenharmony_ci ®s_offset, &nregloc, ®locs, 197da0c48c4Sopenharmony_ci &nitems, &items); 198da0c48c4Sopenharmony_ci /* __libdwfl_attach_state_for_core already verified the note is there. */ 199da0c48c4Sopenharmony_ci if (core_note_err == 0 || nhdr.n_type != NT_PRSTATUS) 200da0c48c4Sopenharmony_ci return false; 201da0c48c4Sopenharmony_ci const Ebl_Core_Item *item; 202da0c48c4Sopenharmony_ci for (item = items; item < items + nitems; item++) 203da0c48c4Sopenharmony_ci if (strcmp (item->name, "pid") == 0) 204da0c48c4Sopenharmony_ci break; 205da0c48c4Sopenharmony_ci assert (item < items + nitems); 206da0c48c4Sopenharmony_ci pid_t tid; 207da0c48c4Sopenharmony_ci { 208da0c48c4Sopenharmony_ci uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); 209da0c48c4Sopenharmony_ci val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 210da0c48c4Sopenharmony_ci ? be32toh (val32) : le32toh (val32)); 211da0c48c4Sopenharmony_ci tid = (int32_t) val32; 212da0c48c4Sopenharmony_ci eu_static_assert (sizeof val32 <= sizeof tid); 213da0c48c4Sopenharmony_ci } 214da0c48c4Sopenharmony_ci /* core_next_thread already found this TID there. */ 215da0c48c4Sopenharmony_ci assert (tid == INTUSE(dwfl_thread_tid) (thread)); 216da0c48c4Sopenharmony_ci for (item = items; item < items + nitems; item++) 217da0c48c4Sopenharmony_ci if (item->pc_register) 218da0c48c4Sopenharmony_ci break; 219da0c48c4Sopenharmony_ci if (item < items + nitems) 220da0c48c4Sopenharmony_ci { 221da0c48c4Sopenharmony_ci Dwarf_Word pc; 222da0c48c4Sopenharmony_ci switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64) 223da0c48c4Sopenharmony_ci { 224da0c48c4Sopenharmony_ci case 32:; 225da0c48c4Sopenharmony_ci uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); 226da0c48c4Sopenharmony_ci val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 227da0c48c4Sopenharmony_ci ? be32toh (val32) : le32toh (val32)); 228da0c48c4Sopenharmony_ci /* Do a host width conversion. */ 229da0c48c4Sopenharmony_ci pc = val32; 230da0c48c4Sopenharmony_ci break; 231da0c48c4Sopenharmony_ci case 64:; 232da0c48c4Sopenharmony_ci uint64_t val64 = read_8ubyte_unaligned_noncvt (desc + item->offset); 233da0c48c4Sopenharmony_ci val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 234da0c48c4Sopenharmony_ci ? be64toh (val64) : le64toh (val64)); 235da0c48c4Sopenharmony_ci pc = val64; 236da0c48c4Sopenharmony_ci break; 237da0c48c4Sopenharmony_ci default: 238da0c48c4Sopenharmony_ci abort (); 239da0c48c4Sopenharmony_ci } 240da0c48c4Sopenharmony_ci INTUSE(dwfl_thread_state_register_pc) (thread, pc); 241da0c48c4Sopenharmony_ci } 242da0c48c4Sopenharmony_ci desc += regs_offset; 243da0c48c4Sopenharmony_ci for (size_t regloci = 0; regloci < nregloc; regloci++) 244da0c48c4Sopenharmony_ci { 245da0c48c4Sopenharmony_ci const Ebl_Register_Location *regloc = reglocs + regloci; 246da0c48c4Sopenharmony_ci // Iterate even regs out of NREGS range so that we can find pc_register. 247da0c48c4Sopenharmony_ci if (regloc->bits != 32 && regloc->bits != 64) 248da0c48c4Sopenharmony_ci continue; 249da0c48c4Sopenharmony_ci const char *reg_desc = desc + regloc->offset; 250da0c48c4Sopenharmony_ci for (unsigned regno = regloc->regno; 251da0c48c4Sopenharmony_ci regno < regloc->regno + (regloc->count ?: 1U); 252da0c48c4Sopenharmony_ci regno++) 253da0c48c4Sopenharmony_ci { 254da0c48c4Sopenharmony_ci /* PPC provides DWARF register 65 irrelevant for 255da0c48c4Sopenharmony_ci CFI which clashes with register 108 (LR) we need. 256da0c48c4Sopenharmony_ci LR (108) is provided earlier (in NT_PRSTATUS) than the # 65. 257da0c48c4Sopenharmony_ci FIXME: It depends now on their order in core notes. 258da0c48c4Sopenharmony_ci FIXME: It uses private function. */ 259da0c48c4Sopenharmony_ci if (regno < nregs 260da0c48c4Sopenharmony_ci && __libdwfl_frame_reg_get (thread->unwound, regno, NULL) == 0) 261da0c48c4Sopenharmony_ci continue; 262da0c48c4Sopenharmony_ci Dwarf_Word val; 263da0c48c4Sopenharmony_ci switch (regloc->bits) 264da0c48c4Sopenharmony_ci { 265da0c48c4Sopenharmony_ci case 32:; 266da0c48c4Sopenharmony_ci uint32_t val32 = read_4ubyte_unaligned_noncvt (reg_desc); 267da0c48c4Sopenharmony_ci reg_desc += sizeof val32; 268da0c48c4Sopenharmony_ci val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 269da0c48c4Sopenharmony_ci ? be32toh (val32) : le32toh (val32)); 270da0c48c4Sopenharmony_ci /* Do a host width conversion. */ 271da0c48c4Sopenharmony_ci val = val32; 272da0c48c4Sopenharmony_ci break; 273da0c48c4Sopenharmony_ci case 64:; 274da0c48c4Sopenharmony_ci uint64_t val64 = read_8ubyte_unaligned_noncvt (reg_desc); 275da0c48c4Sopenharmony_ci reg_desc += sizeof val64; 276da0c48c4Sopenharmony_ci val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 277da0c48c4Sopenharmony_ci ? be64toh (val64) : le64toh (val64)); 278da0c48c4Sopenharmony_ci assert (sizeof (*thread->unwound->regs) == sizeof val64); 279da0c48c4Sopenharmony_ci val = val64; 280da0c48c4Sopenharmony_ci break; 281da0c48c4Sopenharmony_ci default: 282da0c48c4Sopenharmony_ci abort (); 283da0c48c4Sopenharmony_ci } 284da0c48c4Sopenharmony_ci /* Registers not valid for CFI are just ignored. */ 285da0c48c4Sopenharmony_ci if (regno < nregs) 286da0c48c4Sopenharmony_ci INTUSE(dwfl_thread_state_registers) (thread, regno, 1, &val); 287da0c48c4Sopenharmony_ci if (regloc->pc_register) 288da0c48c4Sopenharmony_ci INTUSE(dwfl_thread_state_register_pc) (thread, val); 289da0c48c4Sopenharmony_ci reg_desc += regloc->pad; 290da0c48c4Sopenharmony_ci } 291da0c48c4Sopenharmony_ci } 292da0c48c4Sopenharmony_ci return true; 293da0c48c4Sopenharmony_ci} 294da0c48c4Sopenharmony_ci 295da0c48c4Sopenharmony_cistatic void 296da0c48c4Sopenharmony_cicore_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg) 297da0c48c4Sopenharmony_ci{ 298da0c48c4Sopenharmony_ci struct core_arg *core_arg = dwfl_arg; 299da0c48c4Sopenharmony_ci ebl_closebackend (core_arg->ebl); 300da0c48c4Sopenharmony_ci free (core_arg); 301da0c48c4Sopenharmony_ci} 302da0c48c4Sopenharmony_ci 303da0c48c4Sopenharmony_cistatic const Dwfl_Thread_Callbacks core_thread_callbacks = 304da0c48c4Sopenharmony_ci{ 305da0c48c4Sopenharmony_ci core_next_thread, 306da0c48c4Sopenharmony_ci NULL, /* get_thread */ 307da0c48c4Sopenharmony_ci core_memory_read, 308da0c48c4Sopenharmony_ci core_set_initial_registers, 309da0c48c4Sopenharmony_ci core_detach, 310da0c48c4Sopenharmony_ci NULL, /* core_thread_detach */ 311da0c48c4Sopenharmony_ci}; 312da0c48c4Sopenharmony_ci 313da0c48c4Sopenharmony_ciint 314da0c48c4Sopenharmony_cidwfl_core_file_attach (Dwfl *dwfl, Elf *core) 315da0c48c4Sopenharmony_ci{ 316da0c48c4Sopenharmony_ci Dwfl_Error err = DWFL_E_NOERROR; 317da0c48c4Sopenharmony_ci Ebl *ebl = ebl_openbackend (core); 318da0c48c4Sopenharmony_ci if (ebl == NULL) 319da0c48c4Sopenharmony_ci { 320da0c48c4Sopenharmony_ci err = DWFL_E_LIBEBL; 321da0c48c4Sopenharmony_ci fail_err: 322da0c48c4Sopenharmony_ci if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR) 323da0c48c4Sopenharmony_ci dwfl->attacherr = __libdwfl_canon_error (err); 324da0c48c4Sopenharmony_ci __libdwfl_seterrno (err); 325da0c48c4Sopenharmony_ci return -1; 326da0c48c4Sopenharmony_ci } 327da0c48c4Sopenharmony_ci size_t nregs = ebl_frame_nregs (ebl); 328da0c48c4Sopenharmony_ci if (nregs == 0) 329da0c48c4Sopenharmony_ci { 330da0c48c4Sopenharmony_ci err = DWFL_E_NO_UNWIND; 331da0c48c4Sopenharmony_ci fail: 332da0c48c4Sopenharmony_ci ebl_closebackend (ebl); 333da0c48c4Sopenharmony_ci goto fail_err; 334da0c48c4Sopenharmony_ci } 335da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem); 336da0c48c4Sopenharmony_ci if (ehdr == NULL) 337da0c48c4Sopenharmony_ci { 338da0c48c4Sopenharmony_ci err = DWFL_E_LIBELF; 339da0c48c4Sopenharmony_ci goto fail; 340da0c48c4Sopenharmony_ci } 341da0c48c4Sopenharmony_ci if (ehdr->e_type != ET_CORE) 342da0c48c4Sopenharmony_ci { 343da0c48c4Sopenharmony_ci err = DWFL_E_NO_CORE_FILE; 344da0c48c4Sopenharmony_ci goto fail; 345da0c48c4Sopenharmony_ci } 346da0c48c4Sopenharmony_ci size_t phnum; 347da0c48c4Sopenharmony_ci if (elf_getphdrnum (core, &phnum) < 0) 348da0c48c4Sopenharmony_ci { 349da0c48c4Sopenharmony_ci err = DWFL_E_LIBELF; 350da0c48c4Sopenharmony_ci goto fail; 351da0c48c4Sopenharmony_ci } 352da0c48c4Sopenharmony_ci pid_t pid = -1; 353da0c48c4Sopenharmony_ci Elf_Data *note_data = NULL; 354da0c48c4Sopenharmony_ci for (size_t cnt = 0; cnt < phnum; ++cnt) 355da0c48c4Sopenharmony_ci { 356da0c48c4Sopenharmony_ci GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem); 357da0c48c4Sopenharmony_ci if (phdr != NULL && phdr->p_type == PT_NOTE) 358da0c48c4Sopenharmony_ci { 359da0c48c4Sopenharmony_ci note_data = elf_getdata_rawchunk (core, phdr->p_offset, 360da0c48c4Sopenharmony_ci phdr->p_filesz, (phdr->p_align == 8 361da0c48c4Sopenharmony_ci ? ELF_T_NHDR8 362da0c48c4Sopenharmony_ci : ELF_T_NHDR)); 363da0c48c4Sopenharmony_ci break; 364da0c48c4Sopenharmony_ci } 365da0c48c4Sopenharmony_ci } 366da0c48c4Sopenharmony_ci if (note_data == NULL) 367da0c48c4Sopenharmony_ci { 368da0c48c4Sopenharmony_ci err = DWFL_E_LIBELF; 369da0c48c4Sopenharmony_ci goto fail; 370da0c48c4Sopenharmony_ci } 371da0c48c4Sopenharmony_ci size_t offset = 0; 372da0c48c4Sopenharmony_ci GElf_Nhdr nhdr; 373da0c48c4Sopenharmony_ci size_t name_offset; 374da0c48c4Sopenharmony_ci size_t desc_offset; 375da0c48c4Sopenharmony_ci while (offset < note_data->d_size 376da0c48c4Sopenharmony_ci && (offset = gelf_getnote (note_data, offset, 377da0c48c4Sopenharmony_ci &nhdr, &name_offset, &desc_offset)) > 0) 378da0c48c4Sopenharmony_ci { 379da0c48c4Sopenharmony_ci /* Do not check NAME for now, help broken Linux kernels. */ 380da0c48c4Sopenharmony_ci const char *name = (nhdr.n_namesz == 0 381da0c48c4Sopenharmony_ci ? "" : note_data->d_buf + name_offset); 382da0c48c4Sopenharmony_ci const char *desc = note_data->d_buf + desc_offset; 383da0c48c4Sopenharmony_ci GElf_Word regs_offset; 384da0c48c4Sopenharmony_ci size_t nregloc; 385da0c48c4Sopenharmony_ci const Ebl_Register_Location *reglocs; 386da0c48c4Sopenharmony_ci size_t nitems; 387da0c48c4Sopenharmony_ci const Ebl_Core_Item *items; 388da0c48c4Sopenharmony_ci if (! ebl_core_note (ebl, &nhdr, name, desc, 389da0c48c4Sopenharmony_ci ®s_offset, &nregloc, ®locs, &nitems, &items)) 390da0c48c4Sopenharmony_ci { 391da0c48c4Sopenharmony_ci /* This note may be just not recognized, skip it. */ 392da0c48c4Sopenharmony_ci continue; 393da0c48c4Sopenharmony_ci } 394da0c48c4Sopenharmony_ci if (nhdr.n_type != NT_PRPSINFO) 395da0c48c4Sopenharmony_ci continue; 396da0c48c4Sopenharmony_ci const Ebl_Core_Item *item; 397da0c48c4Sopenharmony_ci for (item = items; item < items + nitems; item++) 398da0c48c4Sopenharmony_ci if (strcmp (item->name, "pid") == 0) 399da0c48c4Sopenharmony_ci break; 400da0c48c4Sopenharmony_ci if (item == items + nitems) 401da0c48c4Sopenharmony_ci continue; 402da0c48c4Sopenharmony_ci uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); 403da0c48c4Sopenharmony_ci val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB 404da0c48c4Sopenharmony_ci ? be32toh (val32) : le32toh (val32)); 405da0c48c4Sopenharmony_ci pid = (int32_t) val32; 406da0c48c4Sopenharmony_ci eu_static_assert (sizeof val32 <= sizeof pid); 407da0c48c4Sopenharmony_ci break; 408da0c48c4Sopenharmony_ci } 409da0c48c4Sopenharmony_ci if (pid == -1) 410da0c48c4Sopenharmony_ci { 411da0c48c4Sopenharmony_ci /* No valid NT_PRPSINFO recognized in this CORE. */ 412da0c48c4Sopenharmony_ci err = DWFL_E_BADELF; 413da0c48c4Sopenharmony_ci goto fail; 414da0c48c4Sopenharmony_ci } 415da0c48c4Sopenharmony_ci struct core_arg *core_arg = malloc (sizeof *core_arg); 416da0c48c4Sopenharmony_ci if (core_arg == NULL) 417da0c48c4Sopenharmony_ci { 418da0c48c4Sopenharmony_ci err = DWFL_E_NOMEM; 419da0c48c4Sopenharmony_ci goto fail; 420da0c48c4Sopenharmony_ci } 421da0c48c4Sopenharmony_ci core_arg->core = core; 422da0c48c4Sopenharmony_ci core_arg->note_data = note_data; 423da0c48c4Sopenharmony_ci core_arg->thread_note_offset = 0; 424da0c48c4Sopenharmony_ci core_arg->ebl = ebl; 425da0c48c4Sopenharmony_ci if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks, 426da0c48c4Sopenharmony_ci core_arg)) 427da0c48c4Sopenharmony_ci { 428da0c48c4Sopenharmony_ci free (core_arg); 429da0c48c4Sopenharmony_ci ebl_closebackend (ebl); 430da0c48c4Sopenharmony_ci return -1; 431da0c48c4Sopenharmony_ci } 432da0c48c4Sopenharmony_ci return pid; 433da0c48c4Sopenharmony_ci} 434da0c48c4Sopenharmony_ciINTDEF (dwfl_core_file_attach) 435