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