Blame libdwfl/linux-core-attach.c

Packit Service 97d2fb
/* Get Dwarf Frame state for target core file.
Packit Service 97d2fb
   Copyright (C) 2013, 2014 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include "libdwflP.h"
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include "system.h"
Packit Service 97d2fb
Packit Service 97d2fb
#include "../libdw/memory-access.h"
Packit Service 97d2fb
Packit Service 97d2fb
struct core_arg
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf *core;
Packit Service 97d2fb
  Elf_Data *note_data;
Packit Service 97d2fb
  size_t thread_note_offset;
Packit Service 97d2fb
  Ebl *ebl;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
struct thread_arg
Packit Service 97d2fb
{
Packit Service 97d2fb
  struct core_arg *core_arg;
Packit Service 97d2fb
  size_t note_offset;
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
static bool
Packit Service 97d2fb
core_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
Packit Service 97d2fb
		  void *dwfl_arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwfl_Process *process = dwfl->process;
Packit Service 97d2fb
  struct core_arg *core_arg = dwfl_arg;
Packit Service 97d2fb
  Elf *core = core_arg->core;
Packit Service 97d2fb
  assert (core != NULL);
Packit Service 97d2fb
  static size_t phnum;
Packit Service 97d2fb
  if (elf_getphdrnum (core, &phnum) < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdwfl_seterrno (DWFL_E_LIBELF);
Packit Service 97d2fb
      return false;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  for (size_t cnt = 0; cnt < phnum; ++cnt)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
Packit Service 97d2fb
      if (phdr == NULL || phdr->p_type != PT_LOAD)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      /* Bias is zero here, a core file itself has no bias.  */
Packit Service 97d2fb
      GElf_Addr start = __libdwfl_segment_start (dwfl, phdr->p_vaddr);
Packit Service 97d2fb
      GElf_Addr end = __libdwfl_segment_end (dwfl,
Packit Service 97d2fb
					     phdr->p_vaddr + phdr->p_memsz);
Packit Service 97d2fb
      unsigned bytes = ebl_get_elfclass (process->ebl) == ELFCLASS64 ? 8 : 4;
Packit Service 97d2fb
      if (addr < start || addr + bytes > end)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      Elf_Data *data;
Packit Service 97d2fb
      data = elf_getdata_rawchunk (core, phdr->p_offset + addr - start,
Packit Service 97d2fb
				   bytes, ELF_T_ADDR);
Packit Service 97d2fb
      if (data == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  __libdwfl_seterrno (DWFL_E_LIBELF);
Packit Service 97d2fb
	  return false;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      assert (data->d_size == bytes);
Packit Service 97d2fb
      if (bytes == 8)
Packit Service 97d2fb
	*result = read_8ubyte_unaligned_noncvt (data->d_buf);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	*result = read_4ubyte_unaligned_noncvt (data->d_buf);
Packit Service 97d2fb
      return true;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE);
Packit Service 97d2fb
  return false;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static pid_t
Packit Service 97d2fb
core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
Packit Service 97d2fb
		  void **thread_argp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  struct core_arg *core_arg = dwfl_arg;
Packit Service 97d2fb
  Elf *core = core_arg->core;
Packit Service 97d2fb
  GElf_Nhdr nhdr;
Packit Service 97d2fb
  size_t name_offset;
Packit Service 97d2fb
  size_t desc_offset;
Packit Service 97d2fb
  Elf_Data *note_data = core_arg->note_data;
Packit Service 97d2fb
  size_t offset;
Packit Service 97d2fb
Packit Service 97d2fb
  struct thread_arg *thread_arg;
Packit Service 97d2fb
  if (*thread_argp == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      core_arg->thread_note_offset = 0;
Packit Service 97d2fb
      thread_arg = malloc (sizeof (*thread_arg));
Packit Service 97d2fb
      if (thread_arg == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  __libdwfl_seterrno (DWFL_E_NOMEM);
Packit Service 97d2fb
	  return -1;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      thread_arg->core_arg = core_arg;
Packit Service 97d2fb
      *thread_argp = thread_arg;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    thread_arg = (struct thread_arg *) *thread_argp;
Packit Service 97d2fb
Packit Service 97d2fb
  while (offset = core_arg->thread_note_offset, offset < note_data->d_size
Packit Service 97d2fb
	 && (core_arg->thread_note_offset = gelf_getnote (note_data, offset,
Packit Service 97d2fb
							  &nhdr, &name_offset,
Packit Service 97d2fb
							  &desc_offset)) > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Do not check NAME for now, help broken Linux kernels.  */
Packit Service 97d2fb
      const char *name = (nhdr.n_namesz == 0
Packit Service 97d2fb
			  ? "" : note_data->d_buf + name_offset);
Packit Service 97d2fb
      const char *desc = note_data->d_buf + desc_offset;
Packit Service 97d2fb
      GElf_Word regs_offset;
Packit Service 97d2fb
      size_t nregloc;
Packit Service 97d2fb
      const Ebl_Register_Location *reglocs;
Packit Service 97d2fb
      size_t nitems;
Packit Service 97d2fb
      const Ebl_Core_Item *items;
Packit Service 97d2fb
      if (! ebl_core_note (core_arg->ebl, &nhdr, name, desc,
Packit Service 97d2fb
			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* This note may be just not recognized, skip it.  */
Packit Service 97d2fb
	  continue;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      if (nhdr.n_type != NT_PRSTATUS)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      const Ebl_Core_Item *item;
Packit Service 97d2fb
      for (item = items; item < items + nitems; item++)
Packit Service 97d2fb
	if (strcmp (item->name, "pid") == 0)
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
      if (item == items + nitems)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
Packit Service 97d2fb
      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		? be32toh (val32) : le32toh (val32));
Packit Service 97d2fb
      pid_t tid = (int32_t) val32;
Packit Service 97d2fb
      eu_static_assert (sizeof val32 <= sizeof tid);
Packit Service 97d2fb
      thread_arg->note_offset = offset;
Packit Service 97d2fb
      return tid;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  free (thread_arg);
Packit Service 97d2fb
  return 0;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static bool
Packit Service 97d2fb
core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  struct thread_arg *thread_arg = thread_arg_voidp;
Packit Service 97d2fb
  struct core_arg *core_arg = thread_arg->core_arg;
Packit Service 97d2fb
  Elf *core = core_arg->core;
Packit Service 97d2fb
  size_t offset = thread_arg->note_offset;
Packit Service 97d2fb
  GElf_Nhdr nhdr;
Packit Service 97d2fb
  size_t name_offset;
Packit Service 97d2fb
  size_t desc_offset;
Packit Service 97d2fb
  Elf_Data *note_data = core_arg->note_data;
Packit Service 97d2fb
  size_t nregs = ebl_frame_nregs (core_arg->ebl);
Packit Service 97d2fb
  assert (nregs > 0);
Packit Service 97d2fb
  assert (offset < note_data->d_size);
Packit Service 97d2fb
  size_t getnote_err = gelf_getnote (note_data, offset, &nhdr, &name_offset,
Packit Service 97d2fb
				     &desc_offset);
Packit Service 97d2fb
  /* __libdwfl_attach_state_for_core already verified the note is there.  */
Packit Service 97d2fb
  if (getnote_err == 0)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
  /* Do not check NAME for now, help broken Linux kernels.  */
Packit Service 97d2fb
  const char *name = (nhdr.n_namesz == 0
Packit Service 97d2fb
		      ? "" : note_data->d_buf + name_offset);
Packit Service 97d2fb
  const char *desc = note_data->d_buf + desc_offset;
Packit Service 97d2fb
  GElf_Word regs_offset;
Packit Service 97d2fb
  size_t nregloc;
Packit Service 97d2fb
  const Ebl_Register_Location *reglocs;
Packit Service 97d2fb
  size_t nitems;
Packit Service 97d2fb
  const Ebl_Core_Item *items;
Packit Service 97d2fb
  int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, desc,
Packit Service 97d2fb
				     &regs_offset, &nregloc, &reglocs,
Packit Service 97d2fb
				     &nitems, &items);
Packit Service 97d2fb
  /* __libdwfl_attach_state_for_core already verified the note is there.  */
Packit Service 97d2fb
  if (core_note_err == 0 || nhdr.n_type != NT_PRSTATUS)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
  const Ebl_Core_Item *item;
Packit Service 97d2fb
  for (item = items; item < items + nitems; item++)
Packit Service 97d2fb
    if (strcmp (item->name, "pid") == 0)
Packit Service 97d2fb
      break;
Packit Service 97d2fb
  assert (item < items + nitems);
Packit Service 97d2fb
  pid_t tid;
Packit Service 97d2fb
  {
Packit Service 97d2fb
    uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
Packit Service 97d2fb
    val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
	     ? be32toh (val32) : le32toh (val32));
Packit Service 97d2fb
    tid = (int32_t) val32;
Packit Service 97d2fb
    eu_static_assert (sizeof val32 <= sizeof tid);
Packit Service 97d2fb
  }
Packit Service 97d2fb
  /* core_next_thread already found this TID there.  */
Packit Service 97d2fb
  assert (tid == INTUSE(dwfl_thread_tid) (thread));
Packit Service 97d2fb
  for (item = items; item < items + nitems; item++)
Packit Service 97d2fb
    if (item->pc_register)
Packit Service 97d2fb
      break;
Packit Service 97d2fb
  if (item < items + nitems)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Word pc;
Packit Service 97d2fb
      switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64)
Packit Service 97d2fb
      {
Packit Service 97d2fb
	case 32:;
Packit Service 97d2fb
	  uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
Packit Service 97d2fb
	  val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		   ? be32toh (val32) : le32toh (val32));
Packit Service 97d2fb
	  /* Do a host width conversion.  */
Packit Service 97d2fb
	  pc = val32;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	case 64:;
Packit Service 97d2fb
	  uint64_t val64 = read_8ubyte_unaligned_noncvt (desc + item->offset);
Packit Service 97d2fb
	  val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		   ? be64toh (val64) : le64toh (val64));
Packit Service 97d2fb
	  pc = val64;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	default:
Packit Service 97d2fb
	  abort ();
Packit Service 97d2fb
      }
Packit Service 97d2fb
      INTUSE(dwfl_thread_state_register_pc) (thread, pc);
Packit Service 97d2fb
    }
Packit Service 97d2fb
  desc += regs_offset;
Packit Service 97d2fb
  for (size_t regloci = 0; regloci < nregloc; regloci++)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      const Ebl_Register_Location *regloc = reglocs + regloci;
Packit Service 97d2fb
      // Iterate even regs out of NREGS range so that we can find pc_register.
Packit Service 97d2fb
      if (regloc->bits != 32 && regloc->bits != 64)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      const char *reg_desc = desc + regloc->offset;
Packit Service 97d2fb
      for (unsigned regno = regloc->regno;
Packit Service 97d2fb
	   regno < regloc->regno + (regloc->count ?: 1U);
Packit Service 97d2fb
	   regno++)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* PPC provides DWARF register 65 irrelevant for
Packit Service 97d2fb
	     CFI which clashes with register 108 (LR) we need.
Packit Service 97d2fb
	     LR (108) is provided earlier (in NT_PRSTATUS) than the # 65.
Packit Service 97d2fb
	     FIXME: It depends now on their order in core notes.
Packit Service 97d2fb
	     FIXME: It uses private function.  */
Packit Service 97d2fb
	  if (regno < nregs
Packit Service 97d2fb
	      && __libdwfl_frame_reg_get (thread->unwound, regno, NULL))
Packit Service 97d2fb
	    continue;
Packit Service 97d2fb
	  Dwarf_Word val;
Packit Service 97d2fb
	  switch (regloc->bits)
Packit Service 97d2fb
	  {
Packit Service 97d2fb
	    case 32:;
Packit Service 97d2fb
	      uint32_t val32 = read_4ubyte_unaligned_noncvt (reg_desc);
Packit Service 97d2fb
	      reg_desc += sizeof val32;
Packit Service 97d2fb
	      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		       ? be32toh (val32) : le32toh (val32));
Packit Service 97d2fb
	      /* Do a host width conversion.  */
Packit Service 97d2fb
	      val = val32;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 64:;
Packit Service 97d2fb
	      uint64_t val64 = read_8ubyte_unaligned_noncvt (reg_desc);
Packit Service 97d2fb
	      reg_desc += sizeof val64;
Packit Service 97d2fb
	      val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		       ? be64toh (val64) : le64toh (val64));
Packit Service 97d2fb
	      assert (sizeof (*thread->unwound->regs) == sizeof val64);
Packit Service 97d2fb
	      val = val64;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    default:
Packit Service 97d2fb
	      abort ();
Packit Service 97d2fb
	  }
Packit Service 97d2fb
	  /* Registers not valid for CFI are just ignored.  */
Packit Service 97d2fb
	  if (regno < nregs)
Packit Service 97d2fb
	    INTUSE(dwfl_thread_state_registers) (thread, regno, 1, &val;;
Packit Service 97d2fb
	  if (regloc->pc_register)
Packit Service 97d2fb
	    INTUSE(dwfl_thread_state_register_pc) (thread, val);
Packit Service 97d2fb
	  reg_desc += regloc->pad;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return true;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static void
Packit Service 97d2fb
core_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
Packit Service 97d2fb
{
Packit Service 97d2fb
  struct core_arg *core_arg = dwfl_arg;
Packit Service 97d2fb
  ebl_closebackend (core_arg->ebl);
Packit Service 97d2fb
  free (core_arg);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
static const Dwfl_Thread_Callbacks core_thread_callbacks =
Packit Service 97d2fb
{
Packit Service 97d2fb
  core_next_thread,
Packit Service 97d2fb
  NULL, /* get_thread */
Packit Service 97d2fb
  core_memory_read,
Packit Service 97d2fb
  core_set_initial_registers,
Packit Service 97d2fb
  core_detach,
Packit Service 97d2fb
  NULL, /* core_thread_detach */
Packit Service 97d2fb
};
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Dwfl_Error err = DWFL_E_NOERROR;
Packit Service 97d2fb
  Ebl *ebl = ebl_openbackend (core);
Packit Service 97d2fb
  if (ebl == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_LIBEBL;
Packit Service 97d2fb
    fail_err:
Packit Service 97d2fb
      if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
Packit Service 97d2fb
	dwfl->attacherr = __libdwfl_canon_error (err);
Packit Service 97d2fb
      __libdwfl_seterrno (err);
Packit Service 97d2fb
      return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  size_t nregs = ebl_frame_nregs (ebl);
Packit Service 97d2fb
  if (nregs == 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_NO_UNWIND;
Packit Service 97d2fb
    fail:
Packit Service 97d2fb
      ebl_closebackend (ebl);
Packit Service 97d2fb
      goto fail_err;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
Packit Service 97d2fb
  if (ehdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_LIBELF;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  if (ehdr->e_type != ET_CORE)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_NO_CORE_FILE;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  size_t phnum;
Packit Service 97d2fb
  if (elf_getphdrnum (core, &phnum) < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_LIBELF;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  pid_t pid = -1;
Packit Service 97d2fb
  Elf_Data *note_data = NULL;
Packit Service 97d2fb
  for (size_t cnt = 0; cnt < phnum; ++cnt)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
Packit Service 97d2fb
      if (phdr != NULL && phdr->p_type == PT_NOTE)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  note_data = elf_getdata_rawchunk (core, phdr->p_offset,
Packit Service 97d2fb
					    phdr->p_filesz, (phdr->p_align == 8
Packit Service 97d2fb
							     ? ELF_T_NHDR8
Packit Service 97d2fb
							     : ELF_T_NHDR));
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
  if (note_data == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_LIBELF;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  size_t offset = 0;
Packit Service 97d2fb
  GElf_Nhdr nhdr;
Packit Service 97d2fb
  size_t name_offset;
Packit Service 97d2fb
  size_t desc_offset;
Packit Service 97d2fb
  while (offset < note_data->d_size
Packit Service 97d2fb
	 && (offset = gelf_getnote (note_data, offset,
Packit Service 97d2fb
				    &nhdr, &name_offset, &desc_offset)) > 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* Do not check NAME for now, help broken Linux kernels.  */
Packit Service 97d2fb
      const char *name = (nhdr.n_namesz == 0
Packit Service 97d2fb
			  ? "" : note_data->d_buf + name_offset);
Packit Service 97d2fb
      const char *desc = note_data->d_buf + desc_offset;
Packit Service 97d2fb
      GElf_Word regs_offset;
Packit Service 97d2fb
      size_t nregloc;
Packit Service 97d2fb
      const Ebl_Register_Location *reglocs;
Packit Service 97d2fb
      size_t nitems;
Packit Service 97d2fb
      const Ebl_Core_Item *items;
Packit Service 97d2fb
      if (! ebl_core_note (ebl, &nhdr, name, desc,
Packit Service 97d2fb
			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* This note may be just not recognized, skip it.  */
Packit Service 97d2fb
	  continue;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      if (nhdr.n_type != NT_PRPSINFO)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      const Ebl_Core_Item *item;
Packit Service 97d2fb
      for (item = items; item < items + nitems; item++)
Packit Service 97d2fb
	if (strcmp (item->name, "pid") == 0)
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
      if (item == items + nitems)
Packit Service 97d2fb
	continue;
Packit Service 97d2fb
      uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
Packit Service 97d2fb
      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
Packit Service 97d2fb
		? be32toh (val32) : le32toh (val32));
Packit Service 97d2fb
      pid = (int32_t) val32;
Packit Service 97d2fb
      eu_static_assert (sizeof val32 <= sizeof pid);
Packit Service 97d2fb
      break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  if (pid == -1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* No valid NT_PRPSINFO recognized in this CORE.  */
Packit Service 97d2fb
      err = DWFL_E_BADELF;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  struct core_arg *core_arg = malloc (sizeof *core_arg);
Packit Service 97d2fb
  if (core_arg == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      err = DWFL_E_NOMEM;
Packit Service 97d2fb
      goto fail;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  core_arg->core = core;
Packit Service 97d2fb
  core_arg->note_data = note_data;
Packit Service 97d2fb
  core_arg->thread_note_offset = 0;
Packit Service 97d2fb
  core_arg->ebl = ebl;
Packit Service 97d2fb
  if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks,
Packit Service 97d2fb
				   core_arg))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (core_arg);
Packit Service 97d2fb
      ebl_closebackend (ebl);
Packit Service 97d2fb
      return -1;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return pid;
Packit Service 97d2fb
}
Packit Service 97d2fb
INTDEF (dwfl_core_file_attach)