Git init
[external/libelf.git] / lib / x.elfext.c
1 /*
2  * x.elfext.c -- handle ELF format extensions
3  * Copyright (C) 2002 - 2006 Michael Riepe
4  * 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * 
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <private.h>
21
22 #ifndef lint
23 static const char rcsid[] = "@(#) $Id: x.elfext.c,v 1.5 2009/07/07 17:57:43 michael Exp $";
24 #endif /* lint */
25
26 int
27 elf_getphdrnum(Elf *elf, size_t *resultp) {
28     if (!elf) {
29         return -1;
30     }
31     elf_assert(elf->e_magic == ELF_MAGIC);
32     if (elf->e_kind != ELF_K_ELF) {
33         seterr(ERROR_NOTELF);
34         return -1;
35     }
36     if (!elf->e_ehdr && !_elf_cook(elf)) {
37         return -1;
38     }
39     if (resultp) {
40         *resultp = elf->e_phnum;
41     }
42     return 0;
43 }
44
45 int
46 elf_getshdrnum(Elf *elf, size_t *resultp) {
47     size_t num = 0;
48     Elf_Scn *scn;
49
50     if (!elf) {
51         return -1;
52     }
53     elf_assert(elf->e_magic == ELF_MAGIC);
54     if (elf->e_kind != ELF_K_ELF) {
55         seterr(ERROR_NOTELF);
56         return -1;
57     }
58     if (!elf->e_ehdr && !_elf_cook(elf)) {
59         return -1;
60     }
61     if ((scn = elf->e_scn_n)) {
62         num = scn->s_index + 1;
63     }
64     if (resultp) {
65         *resultp = num;
66     }
67     return 0;
68 }
69
70 int
71 elf_getshdrstrndx(Elf *elf, size_t *resultp) {
72     size_t num = 0;
73     size_t dummy;
74     Elf_Scn *scn;
75
76     if (!elf) {
77         return -1;
78     }
79     elf_assert(elf->e_magic == ELF_MAGIC);
80     if (resultp == NULL) {
81         resultp = &dummy;       /* handle NULL pointer gracefully */
82     }
83     if (elf->e_kind != ELF_K_ELF) {
84         seterr(ERROR_NOTELF);
85         return -1;
86     }
87     if (!elf->e_ehdr && !_elf_cook(elf)) {
88         return -1;
89     }
90     if (elf->e_class == ELFCLASS32) {
91         num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx;
92     }
93 #if __LIBELF64
94     else if (elf->e_class == ELFCLASS64) {
95         num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx;
96     }
97 #endif /* __LIBELF64 */
98     else {
99         if (valid_class(elf->e_class)) {
100             seterr(ERROR_UNIMPLEMENTED);
101         }
102         else {
103             seterr(ERROR_UNKNOWN_CLASS);
104         }
105         return -1;
106     }
107     if (num != SHN_XINDEX) {
108         *resultp = num;
109         return 0;
110     }
111     /*
112      * look at first section header
113      */
114     if (!(scn = elf->e_scn_1)) {
115         seterr(ERROR_NOSUCHSCN);
116         return -1;
117     }
118     elf_assert(scn->s_magic == SCN_MAGIC);
119 #if __LIBELF64
120     if (elf->e_class == ELFCLASS64) {
121         *resultp = scn->s_shdr64.sh_link;
122         return 0;
123     }
124 #endif /* __LIBELF64 */
125     *resultp = scn->s_shdr32.sh_link;
126     return 0;
127 }
128
129 int
130 elf_getphnum(Elf *elf, size_t *resultp) {
131     return elf_getphdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
132 }
133
134 int
135 elf_getshnum(Elf *elf, size_t *resultp) {
136     return elf_getshdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
137 }
138
139 int
140 elf_getshstrndx(Elf *elf, size_t *resultp) {
141     return elf_getshdrstrndx(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
142 }
143
144 int
145 elfx_update_shstrndx(Elf *elf, size_t value) {
146     size_t extvalue = 0;
147     Elf_Scn *scn;
148
149     if (!elf) {
150         return LIBELF_FAILURE;
151     }
152     elf_assert(elf->e_magic == ELF_MAGIC);
153     if (value >= SHN_LORESERVE) {
154         extvalue = value;
155         value = SHN_XINDEX;
156     }
157     if (elf->e_kind != ELF_K_ELF) {
158         seterr(ERROR_NOTELF);
159         return LIBELF_FAILURE;
160     }
161     if (!elf->e_ehdr && !_elf_cook(elf)) {
162         return LIBELF_FAILURE;
163     }
164     if (!(scn = _elf_first_scn(elf))) {
165         return LIBELF_FAILURE;
166     }
167     elf_assert(scn->s_magic == SCN_MAGIC);
168     if (elf->e_class == ELFCLASS32) {
169         ((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx = value;
170         scn->s_shdr32.sh_link = extvalue;
171     }
172 #if __LIBELF64
173     else if (elf->e_class == ELFCLASS64) {
174         ((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx = value;
175         scn->s_shdr64.sh_link = extvalue;
176     }
177 #endif /* __LIBELF64 */
178     else {
179         if (valid_class(elf->e_class)) {
180             seterr(ERROR_UNIMPLEMENTED);
181         }
182         else {
183             seterr(ERROR_UNKNOWN_CLASS);
184         }
185         return LIBELF_FAILURE;
186     }
187     elf->e_ehdr_flags |= ELF_F_DIRTY;
188     scn->s_shdr_flags |= ELF_F_DIRTY;
189     return LIBELF_SUCCESS;
190 }