xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/newscn.c (revision 3db86aab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1988 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright (c) 1998 by Sun Microsystems, Inc.
28  * All rights reserved.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI" 	/* SVr4.0 1.4	*/
32 
33 #pragma weak	elf_newscn = _elf_newscn
34 
35 
36 #include "syn.h"
37 #include "libelf.h"
38 #include "decl.h"
39 #include "msg.h"
40 
41 
42 Elf_Scn *
43 elf_newscn(Elf * elf)
44 {
45 	Elf_Scn	*	tl;
46 
47 	if (elf == 0)
48 		return (0);
49 
50 	ELFWLOCK(elf)
51 	/*
52 	 * if no sections yet, the file either isn't cooked
53 	 * or it truly is empty.  Then allocate shdr[0]
54 	 */
55 	if ((elf->ed_hdscn == 0) && (_elf_cook(elf) != OK_YES)) {
56 		ELFUNLOCK(elf)
57 		return (0);
58 	}
59 	if (elf->ed_ehdr == 0) {
60 		_elf_seterr(ESEQ_EHDR, 0);
61 		ELFUNLOCK(elf)
62 		return (0);
63 	}
64 
65 	if (elf->ed_class == ELFCLASS32) {
66 		Snode32	*s;
67 
68 		if (elf->ed_hdscn == 0)	{
69 			if ((s = _elf32_snode()) == 0) {
70 				ELFUNLOCK(elf)
71 				return (0);
72 			}
73 			NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
74 			s->sb_scn.s_elf = elf;
75 			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
76 			s->sb_scn.s_uflags |= ELF_F_DIRTY;
77 		}
78 		if ((s = _elf32_snode()) == 0) {
79 			ELFUNLOCK(elf)
80 			return (0);
81 		}
82 		NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
83 		tl = elf->ed_tlscn;
84 		s->sb_scn.s_elf = elf;
85 		s->sb_scn.s_index = tl->s_index + 1;
86 		elf->ed_tlscn = tl->s_next = &s->sb_scn;
87 		((Elf32_Ehdr *)elf->ed_ehdr)->e_shnum
88 		    /* LINTED */
89 		    = (Elf32_Half)(tl->s_index + 2);
90 		s->sb_scn.s_uflags |= ELF_F_DIRTY;
91 		tl = &s->sb_scn;
92 		NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
93 		ELFUNLOCK(elf)
94 		return (tl);
95 	} else if (elf->ed_class == ELFCLASS64) {
96 		Snode64	*s;
97 
98 		if (elf->ed_hdscn == 0)	{
99 			if ((s = _elf64_snode()) == 0) {
100 				ELFUNLOCK(elf)
101 				return (0);
102 			}
103 			NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
104 			s->sb_scn.s_elf = elf;
105 			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
106 			s->sb_scn.s_uflags |= ELF_F_DIRTY;
107 		}
108 		if ((s = _elf64_snode()) == 0) {
109 			ELFUNLOCK(elf)
110 			return (0);
111 		}
112 		NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
113 		tl = elf->ed_tlscn;
114 		s->sb_scn.s_elf = elf;
115 		s->sb_scn.s_index = tl->s_index + 1;
116 		elf->ed_tlscn = tl->s_next = &s->sb_scn;
117 		((Elf64_Ehdr *)elf->ed_ehdr)->e_shnum
118 		    /* LINTED */
119 		    = (Elf64_Half)(tl->s_index + 2);
120 		s->sb_scn.s_uflags |= ELF_F_DIRTY;
121 		tl = &s->sb_scn;
122 		NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
123 		ELFUNLOCK(elf)
124 		return (tl);
125 	} else {
126 		_elf_seterr(EREQ_CLASS, 0);
127 		ELFUNLOCK(elf)
128 		return (0);
129 	}
130 }
131