Ejemplo n.º 1
0
static Pe *
read_unmmapped_file(int fildes, size_t maxsize, Pe_Cmd cmd, Pe *parent)
{
	union {
		struct {
			struct mz_hdr mz;
			struct pe_hdr pe;
		};
		unsigned char raw[1];
	} mem;

	ssize_t nread = pread_retry (fildes, &mem.mz, sizeof(mem.mz), 0);
	if (nread == -1)
		return NULL;

	/* this handles MZ-only binaries wrong, but who cares, really? */
	off_t peaddr = le32_to_cpu(mem.mz.peaddr);
	ssize_t prev_nread = nread;
	nread += pread_retry (fildes, &mem.pe, sizeof(mem.pe), peaddr);
	if (nread == prev_nread)
		return NULL;
	mem.mz.peaddr = cpu_to_le32(offsetof(typeof(mem), pe));

	Pe_Kind kind = determine_kind(&mem, nread);

	switch (kind) {
		case PE_K_PE_OBJ:
			return file_read_pe_obj(fildes, NULL, mem.raw, maxsize,
						cmd, parent);
		case PE_K_PE_EXE:
			return file_read_pe_exe(fildes, NULL, mem.raw, maxsize,
						cmd, parent);
		default:
			break;
	}

	return allocate_pe(fildes, NULL, maxsize, cmd, parent, PE_K_NONE, 0);
}
Ejemplo n.º 2
0
static unsigned char
get_pid_class (pid_t pid)
{
  char *fname;
  if (asprintf (&fname, PROCEXEFMT, pid) < 0)
    return ELFCLASSNONE;

  int fd = open (fname, O_RDONLY);
  free (fname);
  if (fd < 0)
    return ELFCLASSNONE;

  unsigned char buf[EI_CLASS + 1];
  ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0);
  close (fd);
  if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0
      || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2
      || buf[EI_MAG3] != ELFMAG3
      || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32))
    return ELFCLASSNONE;

  return buf[EI_CLASS];
}
Ejemplo n.º 3
0
static int
grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
{
  char *fname;
  if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
    return ENOMEM;

  int fd = open (fname, O_RDONLY);
  free (fname);
  if (fd < 0)
    return errno == ENOENT ? 0 : errno;

  GElf_Addr sysinfo_ehdr64 = 0;
  GElf_Addr sysinfo_ehdr32 = 0;
  GElf_Addr segment_align64 = dwfl->segment_align;
  GElf_Addr segment_align32 = dwfl->segment_align;
  off_t offset = 0;
  ssize_t nread;
  union
  {
    Elf64_auxv_t a64[64];
    Elf32_auxv_t a32[128];
  } d;
  do
    {
      eu_static_assert (sizeof d.a64 == sizeof d.a32);
      nread = pread_retry (fd, d.a64, sizeof d.a64, offset);
      if (nread < 0)
	{
	  int ret = errno;
	  close (fd);
	  return ret;
	}
      for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++)
	{
	  const Elf32_auxv_t *a32 = d.a32 + a32i;
	  switch (a32->a_type)
	  {
	    case AT_SYSINFO_EHDR:
	      sysinfo_ehdr32 = a32->a_un.a_val;
	      break;
	    case AT_PAGESZ:
	      segment_align32 = a32->a_un.a_val;
	      break;
	  }
	}
      for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++)
	{
	  const Elf64_auxv_t *a64 = d.a64 + a64i;
	  switch (a64->a_type)
	  {
	    case AT_SYSINFO_EHDR:
	      sysinfo_ehdr64 = a64->a_un.a_val;
	      break;
	    case AT_PAGESZ:
	      segment_align64 = a64->a_un.a_val;
	      break;
	  }
	}
      offset += nread;
    }
  while (nread == sizeof d.a64);

  close (fd);

  bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align;
  bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align;

  unsigned char pid_class = ELFCLASSNONE;
  if (valid64 && valid32)
    pid_class = get_pid_class (pid);

  if (pid_class == ELFCLASS64 || (valid64 && ! valid32))
    {
      *sysinfo_ehdr = sysinfo_ehdr64;
      dwfl->segment_align = segment_align64;
      return 0;
    }
  if (pid_class == ELFCLASS32 || (! valid64 && valid32))
    {
      *sysinfo_ehdr = sysinfo_ehdr32;
      dwfl->segment_align = segment_align32;
      return 0;
    }
  return ENOEXEC;
}