dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / libelf / common / clscook.c
bloba34bf62c6e11fa6ec7d0ad823ee2ed419234cfa4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 * This stuff used to live in cook.c, but was moved out to
32 * facilitate dual (Elf32 and Elf64) compilation. See block
33 * comment in cook.c for more info.
36 #include <string.h>
37 #include <ar.h>
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <sys/sysmacros.h>
41 #include "decl.h"
42 #include "member.h"
43 #include "msg.h"
46 * This module is compiled twice, the second time having
47 * -D_ELF64 defined. The following set of macros, along
48 * with machelf.h, represent the differences between the
49 * two compilations. Be careful *not* to add any class-
50 * dependent code (anything that has elf32 or elf64 in the
51 * name) to this code without hiding it behind a switch-
52 * able macro like these.
54 #if defined(_ELF64)
55 #define Snode Snode64
56 #define ELFCLASS ELFCLASS64
57 #define ElfField Elf64
58 #define _elf_snode_init _elf64_snode_init
59 #define _elf_prepscan _elf64_prepscan
60 #define _elf_cookscn _elf64_cookscn
61 #define _elf_mtype _elf64_mtype
62 #define _elf_msize _elf64_msize
63 #define elf_fsize elf64_fsize
64 #define _elf_snode _elf64_snode
65 #define _elf_ehdr _elf64_ehdr
66 #define elf_xlatetom elf64_xlatetom
67 #define _elf_phdr _elf64_phdr
68 #define _elf_shdr _elf64_shdr
69 #define _elf_prepscn _elf64_prepscn
71 #else /* Elf32 */
72 #define Snode Snode32
73 #define ELFCLASS ELFCLASS32
74 #define ElfField Elf32
75 #define _elf_snode_init _elf32_snode_init
76 #define _elf_prepscan _elf32_prepscan
77 #define _elf_cookscn _elf32_cookscn
78 #define _elf_mtype _elf32_mtype
79 #define _elf_msize _elf32_msize
80 #define elf_fsize elf32_fsize
81 #define _elf_snode _elf32_snode
82 #define _elf_ehdr _elf32_ehdr
83 #define elf_xlatetom elf32_xlatetom
84 #define _elf_phdr _elf32_phdr
85 #define _elf_shdr _elf32_shdr
86 #define _elf_prepscn _elf32_prepscn
88 #endif /* _ELF64 */
91 static Okay
92 _elf_prepscn(Elf *elf, size_t cnt)
94 Elf_Scn * s;
95 Elf_Scn * end;
97 if (cnt == 0)
98 return (OK_YES);
100 if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) {
101 _elf_seterr(EMEM_SCN, errno);
102 return (OK_NO);
104 elf->ed_scntabsz = cnt;
105 end = s + cnt;
106 elf->ed_hdscn = s;
107 do {
108 *s = _elf_snode_init.sb_scn;
109 s->s_elf = elf;
110 s->s_next = s + 1;
111 s->s_index = s - elf->ed_hdscn;
112 s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index;
113 ELFMUTEXINIT(&s->s_mutex);
116 * Section has not yet been cooked!
118 * We don't cook a section until it's data is actually
119 * referenced.
121 s->s_myflags = 0;
122 } while (++s < end);
124 elf->ed_tlscn = --s;
125 s->s_next = 0;
128 * Section index SHN_UNDEF (0) does not and cannot
129 * have a data buffer. Fix it here. Also mark the
130 * initial section as being allocated for the block
133 s = elf->ed_hdscn;
134 s->s_myflags = SF_ALLOC;
135 s->s_hdnode = 0;
136 s->s_tlnode = 0;
137 return (OK_YES);
141 Okay
142 _elf_cookscn(Elf_Scn * s)
144 Elf * elf;
145 Shdr * sh;
146 register Dnode * d = &s->s_dnode;
147 size_t fsz, msz;
148 unsigned work;
150 s->s_hdnode = s->s_tlnode = d;
151 s->s_err = 0;
152 s->s_shflags = 0;
153 s->s_uflags = 0;
157 * Prepare d_data for inspection, but don't actually
158 * translate data until needed. Leave the READY
159 * flag off. NOBITS sections see zero size.
161 elf = s->s_elf;
162 sh = s->s_shdr;
164 d->db_scn = s;
165 d->db_off = sh->sh_offset;
166 d->db_data.d_align = sh->sh_addralign;
167 d->db_data.d_version = elf->ed_version;
168 ELFACCESSDATA(work, _elf_work)
169 d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work);
170 d->db_data.d_buf = 0;
171 d->db_data.d_off = 0;
172 fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version);
173 msz = _elf_msize(d->db_data.d_type, elf->ed_version);
174 d->db_data.d_size = MAX(sh->sh_size, (sh->sh_size / fsz) * msz);
175 d->db_shsz = sh->sh_size;
176 d->db_raw = 0;
177 d->db_buf = 0;
178 d->db_uflags = 0;
179 d->db_myflags = 0;
180 d->db_next = 0;
182 if (sh->sh_type != SHT_NOBITS)
183 d->db_fsz = sh->sh_size;
184 else
185 d->db_fsz = 0;
187 s->s_myflags |= SF_READY;
189 return (OK_YES);
194 Snode *
195 _elf_snode()
197 register Snode *s;
199 if ((s = malloc(sizeof (Snode))) == 0) {
200 _elf_seterr(EMEM_SNODE, errno);
201 return (0);
203 *s = _elf_snode_init;
204 ELFMUTEXINIT(&s->sb_scn.s_mutex);
205 s->sb_scn.s_myflags = SF_ALLOC | SF_READY;
206 s->sb_scn.s_shdr = &s->sb_shdr;
207 return (s);
213 _elf_ehdr(Elf * elf, int inplace)
215 register size_t fsz; /* field size */
216 Elf_Data dst, src;
218 fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version);
219 if (fsz > elf->ed_fsz) {
220 _elf_seterr(EFMT_EHDRSZ, 0);
221 return (-1);
223 if (inplace && (fsz >= sizeof (Ehdr))) {
225 * The translated Ehdr will fit over the original Ehdr.
227 /* LINTED */
228 elf->ed_ehdr = (Ehdr *)elf->ed_ident;
229 elf->ed_status = ES_COOKED;
230 } else {
231 elf->ed_ehdr = malloc(sizeof (Ehdr));
232 if (elf->ed_ehdr == 0) {
233 _elf_seterr(EMEM_EHDR, errno);
234 return (-1);
236 elf->ed_myflags |= EDF_EHALLOC;
240 * Memory size >= fsz, because otherwise the memory version
241 * loses information and cannot accurately implement the
242 * file.
245 src.d_buf = (Elf_Void *)elf->ed_ident;
246 src.d_type = ELF_T_EHDR;
247 src.d_size = fsz;
248 src.d_version = elf->ed_version;
249 dst.d_buf = (Elf_Void *)elf->ed_ehdr;
250 dst.d_size = sizeof (Ehdr);
251 dst.d_version = EV_CURRENT;
253 if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) ||
254 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
255 if (elf->ed_myflags & EDF_EHALLOC) {
256 elf->ed_myflags &= ~EDF_EHALLOC;
257 free(elf->ed_ehdr);
259 elf->ed_ehdr = 0;
260 return (-1);
263 if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) {
264 _elf_seterr(EREQ_CLASS, 0);
265 if (elf->ed_myflags & EDF_EHALLOC) {
266 elf->ed_myflags &= ~EDF_EHALLOC;
267 free(elf->ed_ehdr);
269 elf->ed_ehdr = 0;
270 return (-1);
273 if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) {
274 _elf_seterr(EFMT_VER2, 0);
275 if (elf->ed_myflags & EDF_EHALLOC) {
276 elf->ed_myflags &= ~EDF_EHALLOC;
277 free(elf->ed_ehdr);
279 elf->ed_ehdr = 0;
280 return (-1);
283 return (0);
289 _elf_phdr(Elf * elf, int inplace)
291 register size_t fsz, msz;
292 Elf_Data dst, src;
293 Ehdr * eh = elf->ed_ehdr; /* must be present */
294 unsigned work;
296 if (eh->e_phnum == 0)
297 return (0);
299 fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version);
300 if (eh->e_phentsize != fsz) {
301 _elf_seterr(EFMT_PHDRSZ, 0);
302 return (-1);
305 fsz *= eh->e_phnum;
306 ELFACCESSDATA(work, _elf_work)
307 msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum;
308 if ((eh->e_phoff == 0) ||
309 (elf->ed_fsz <= eh->e_phoff) ||
310 (elf->ed_fsz - eh->e_phoff < fsz)) {
311 _elf_seterr(EFMT_PHTAB, 0);
312 return (-1);
315 if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) {
316 elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
317 elf->ed_status = ES_COOKED;
318 } else {
319 if ((elf->ed_phdr = malloc(msz)) == 0) {
320 _elf_seterr(EMEM_PHDR, errno);
321 return (-1);
323 elf->ed_myflags |= EDF_PHALLOC;
325 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
326 src.d_type = ELF_T_PHDR;
327 src.d_size = fsz;
328 src.d_version = elf->ed_version;
329 dst.d_buf = elf->ed_phdr;
330 dst.d_size = msz;
331 dst.d_version = work;
332 if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) ||
333 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
334 if (elf->ed_myflags & EDF_PHALLOC) {
335 elf->ed_myflags &= ~EDF_PHALLOC;
336 free(elf->ed_phdr);
338 elf->ed_phdr = 0;
339 return (-1);
341 elf->ed_phdrsz = msz;
342 return (0);
348 _elf_shdr(Elf * elf, int inplace)
350 register size_t fsz, msz;
351 size_t scncnt;
352 Elf_Data dst, src;
353 register Ehdr *eh = elf->ed_ehdr; /* must be present */
355 if ((eh->e_shnum == 0) && (eh->e_shoff == 0))
356 return (0);
358 fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version);
359 if (eh->e_shentsize != fsz) {
360 _elf_seterr(EFMT_SHDRSZ, 0);
361 return (-1);
364 * If we are dealing with a file with 'extended section
365 * indexes' - then we need to load the first section
366 * header. The actual section count is stored in
367 * Shdr[0].sh_size.
369 if ((scncnt = eh->e_shnum) == 0) {
370 Shdr sh;
371 if ((eh->e_shoff == 0) ||
372 (elf->ed_fsz <= eh->e_shoff) ||
373 (elf->ed_fsz - eh->e_shoff < fsz)) {
374 _elf_seterr(EFMT_SHTAB, 0);
375 return (-1);
377 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
378 src.d_type = ELF_T_SHDR;
379 src.d_size = fsz;
380 src.d_version = elf->ed_version;
381 dst.d_buf = (Elf_Void *)&sh;
382 dst.d_size = sizeof (Shdr);
383 dst.d_version = EV_CURRENT;
384 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
385 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
386 return (-1);
388 scncnt = sh.sh_size;
391 fsz *= scncnt;
392 msz = scncnt * sizeof (Shdr);
393 if ((eh->e_shoff == 0) ||
394 (elf->ed_fsz <= eh->e_shoff) ||
395 (elf->ed_fsz - eh->e_shoff < fsz)) {
396 _elf_seterr(EFMT_SHTAB, 0);
397 return (-1);
400 if (inplace && (fsz >= msz) &&
401 ((eh->e_shoff % sizeof (ElfField)) == 0)) {
402 /* LINTED */
403 elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff);
404 elf->ed_status = ES_COOKED;
405 } else {
406 if ((elf->ed_shdr = malloc(msz)) == 0) {
407 _elf_seterr(EMEM_SHDR, errno);
408 return (-1);
410 elf->ed_myflags |= EDF_SHALLOC;
412 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
413 src.d_type = ELF_T_SHDR;
414 src.d_size = fsz;
415 src.d_version = elf->ed_version;
416 dst.d_buf = (Elf_Void *)elf->ed_shdr;
417 dst.d_size = msz;
418 dst.d_version = EV_CURRENT;
419 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
420 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) ||
421 (_elf_prepscn(elf, scncnt) != OK_YES)) {
422 if (elf->ed_myflags & EDF_SHALLOC) {
423 elf->ed_myflags &= ~EDF_SHALLOC;
424 free(elf->ed_shdr);
426 elf->ed_shdr = 0;
427 return (-1);
429 return (0);