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
elf_getphdrnum(Elf * elf,size_t * resultp)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
elf_getshdrnum(Elf * elf,size_t * resultp)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
elf_getshdrstrndx(Elf * elf,size_t * resultp)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
elf_getphnum(Elf * elf,size_t * resultp)130 elf_getphnum(Elf *elf, size_t *resultp) {
131     return elf_getphdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
132 }
133 
134 int
elf_getshnum(Elf * elf,size_t * resultp)135 elf_getshnum(Elf *elf, size_t *resultp) {
136     return elf_getshdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
137 }
138 
139 int
elf_getshstrndx(Elf * elf,size_t * resultp)140 elf_getshstrndx(Elf *elf, size_t *resultp) {
141     return elf_getshdrstrndx(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS;
142 }
143 
144 int
elfx_update_shstrndx(Elf * elf,size_t value)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 }
191