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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1988 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30#pragma ident	"@(#)newscn.c	1.13	08/05/31 SMI"
31
32#include "libelf.h"
33#include "decl.h"
34#include "msg.h"
35
36
37Elf_Scn *
38elf_newscn(Elf * elf)
39{
40	Elf_Scn	*	tl;
41
42	if (elf == 0)
43		return (0);
44
45	ELFWLOCK(elf)
46	/*
47	 * if no sections yet, the file either isn't cooked
48	 * or it truly is empty.  Then allocate shdr[0]
49	 */
50	if ((elf->ed_hdscn == 0) && (_elf_cook(elf) != OK_YES)) {
51		ELFUNLOCK(elf)
52		return (0);
53	}
54	if (elf->ed_ehdr == 0) {
55		_elf_seterr(ESEQ_EHDR, 0);
56		ELFUNLOCK(elf)
57		return (0);
58	}
59
60	if (elf->ed_class == ELFCLASS32) {
61		Snode32	*s;
62
63		if (elf->ed_hdscn == 0)	{
64			if ((s = _elf32_snode()) == 0) {
65				ELFUNLOCK(elf)
66				return (0);
67			}
68			NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
69			s->sb_scn.s_elf = elf;
70			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
71			s->sb_scn.s_uflags |= ELF_F_DIRTY;
72		}
73		if ((s = _elf32_snode()) == 0) {
74			ELFUNLOCK(elf)
75			return (0);
76		}
77		NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
78		tl = elf->ed_tlscn;
79		s->sb_scn.s_elf = elf;
80		s->sb_scn.s_index = tl->s_index + 1;
81		elf->ed_tlscn = tl->s_next = &s->sb_scn;
82		((Elf32_Ehdr *)elf->ed_ehdr)->e_shnum
83		    /* LINTED */
84		    = (Elf32_Half)(tl->s_index + 2);
85		s->sb_scn.s_uflags |= ELF_F_DIRTY;
86		tl = &s->sb_scn;
87		NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
88		ELFUNLOCK(elf)
89		return (tl);
90	} else if (elf->ed_class == ELFCLASS64) {
91		Snode64	*s;
92
93		if (elf->ed_hdscn == 0)	{
94			if ((s = _elf64_snode()) == 0) {
95				ELFUNLOCK(elf)
96				return (0);
97			}
98			NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
99			s->sb_scn.s_elf = elf;
100			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
101			s->sb_scn.s_uflags |= ELF_F_DIRTY;
102		}
103		if ((s = _elf64_snode()) == 0) {
104			ELFUNLOCK(elf)
105			return (0);
106		}
107		NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
108		tl = elf->ed_tlscn;
109		s->sb_scn.s_elf = elf;
110		s->sb_scn.s_index = tl->s_index + 1;
111		elf->ed_tlscn = tl->s_next = &s->sb_scn;
112		((Elf64_Ehdr *)elf->ed_ehdr)->e_shnum
113		    /* LINTED */
114		    = (Elf64_Half)(tl->s_index + 2);
115		s->sb_scn.s_uflags |= ELF_F_DIRTY;
116		tl = &s->sb_scn;
117		NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
118		ELFUNLOCK(elf)
119		return (tl);
120	} else {
121		_elf_seterr(EREQ_CLASS, 0);
122		ELFUNLOCK(elf)
123		return (0);
124	}
125}
126