1cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath/* Get information from auxiliary vector at the given index.
21ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard   Copyright (C) 2007, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
7cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
21cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath   WITHOUT ANY WARRANTY; without even the implied warranty of
22cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath   General Public License for more details.
24cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
28cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
29cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#ifdef HAVE_CONFIG_H
30cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath# include <config.h>
31cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#endif
32cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
33cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#include <assert.h>
34cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#include <gelf.h>
35cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#include <string.h>
36cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
37cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath#include "libelfP.h"
38cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
39cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
40cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrathGElf_auxv_t *
411ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardgelf_getauxv (Elf_Data *data, int ndx, GElf_auxv_t *dst)
42cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath{
43cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
44cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  GElf_auxv_t *result = NULL;
45cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  Elf *elf;
46cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
47cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  if (data_scn == NULL)
48cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    return NULL;
49cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
50cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  if (unlikely (data_scn->d.d_type != ELF_T_AUXV))
51cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    {
52cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      __libelf_seterrno (ELF_E_INVALID_HANDLE);
53cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      return NULL;
54cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    }
55cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
56cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  elf = data_scn->s->elf;
57cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
58b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath  rwlock_rdlock (elf->lock);
59cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
60cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  /* This is the one place where we have to take advantage of the fact
61cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
62cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath     The interface is broken so that it requires this hack.  */
63cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  if (elf->class == ELFCLASS32)
64cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    {
65cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      Elf32_auxv_t *src;
66cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
67cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* Here it gets a bit more complicated.  The format of the vector
68cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	 entries has to be converted.  The user better have provided a
69cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	 buffer where we can store the information.  While copying the data
70cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	 we convert the format.  */
71cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      if (unlikely ((ndx + 1) * sizeof (Elf32_auxv_t) > data_scn->d.d_size))
72cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	{
73cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	  __libelf_seterrno (ELF_E_INVALID_INDEX);
74cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	  goto out;
75cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	}
76cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
77cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      src = &((Elf32_auxv_t *) data_scn->d.d_buf)[ndx];
78cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
79cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* This might look like a simple copy operation but it's
80cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	 not.  There are zero- and sign-extensions going on.  */
81cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      dst->a_type = src->a_type;
82cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      dst->a_un.a_val = src->a_un.a_val;
83cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    }
84cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  else
85cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    {
86cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* If this is a 64 bit object it's easy.  */
87cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      assert (sizeof (GElf_auxv_t) == sizeof (Elf64_auxv_t));
88cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
89cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* The data is already in the correct form.  Just make sure the
90cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	 index is OK.  */
91cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      if (unlikely ((ndx + 1) * sizeof (GElf_auxv_t) > data_scn->d.d_size))
92cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	{
93cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	  __libelf_seterrno (ELF_E_INVALID_INDEX);
94cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	  goto out;
95cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath	}
96cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
97d0509d49a080796d3257a8cd962039cd9b7f53f6Mark Wielaard      memcpy (dst, data_scn->d.d_buf + ndx * sizeof (GElf_auxv_t),
98d0509d49a080796d3257a8cd962039cd9b7f53f6Mark Wielaard	      sizeof (GElf_auxv_t));
99cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath    }
100cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
101cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  result = dst;
102cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
103cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath out:
104b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath  rwlock_unlock (elf->lock);
105cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
106cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath  return result;
107cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath}
108