xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/newscn.c (revision e2f4f3da)
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 #include "libelf.h"
31 #include "decl.h"
32 #include "msg.h"
33 
34 
35 Elf_Scn *
elf_newscn(Elf * elf)36 elf_newscn(Elf * elf)
37 {
38 	Elf_Scn	*	tl;
39 
40 	if (elf == 0)
41 		return (0);
42 
43 	ELFWLOCK(elf)
44 	/*
45 	 * if no sections yet, the file either isn't cooked
46 	 * or it truly is empty.  Then allocate shdr[0]
47 	 */
48 	if ((elf->ed_hdscn == 0) && (_elf_cook(elf) != OK_YES)) {
49 		ELFUNLOCK(elf)
50 		return (0);
51 	}
52 	if (elf->ed_ehdr == 0) {
53 		_elf_seterr(ESEQ_EHDR, 0);
54 		ELFUNLOCK(elf)
55 		return (0);
56 	}
57 
58 	if (elf->ed_class == ELFCLASS32) {
59 		Snode32	*s;
60 
61 		if (elf->ed_hdscn == 0)	{
62 			if ((s = _elf32_snode()) == 0) {
63 				ELFUNLOCK(elf)
64 				return (0);
65 			}
66 			s->sb_scn.s_elf = elf;
67 			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
68 			s->sb_scn.s_uflags |= ELF_F_DIRTY;
69 		}
70 		if ((s = _elf32_snode()) == 0) {
71 			ELFUNLOCK(elf)
72 			return (0);
73 		}
74 		tl = elf->ed_tlscn;
75 		s->sb_scn.s_elf = elf;
76 		s->sb_scn.s_index = tl->s_index + 1;
77 		elf->ed_tlscn = tl->s_next = &s->sb_scn;
78 		((Elf32_Ehdr *)elf->ed_ehdr)->e_shnum
79 		    /* LINTED */
80 		    = (Elf32_Half)(tl->s_index + 2);
81 		s->sb_scn.s_uflags |= ELF_F_DIRTY;
82 		tl = &s->sb_scn;
83 		ELFUNLOCK(elf)
84 		return (tl);
85 	} else if (elf->ed_class == ELFCLASS64) {
86 		Snode64	*s;
87 
88 		if (elf->ed_hdscn == 0)	{
89 			if ((s = _elf64_snode()) == 0) {
90 				ELFUNLOCK(elf)
91 				return (0);
92 			}
93 			s->sb_scn.s_elf = elf;
94 			elf->ed_hdscn = elf->ed_tlscn = &s->sb_scn;
95 			s->sb_scn.s_uflags |= ELF_F_DIRTY;
96 		}
97 		if ((s = _elf64_snode()) == 0) {
98 			ELFUNLOCK(elf)
99 			return (0);
100 		}
101 		tl = elf->ed_tlscn;
102 		s->sb_scn.s_elf = elf;
103 		s->sb_scn.s_index = tl->s_index + 1;
104 		elf->ed_tlscn = tl->s_next = &s->sb_scn;
105 		((Elf64_Ehdr *)elf->ed_ehdr)->e_shnum
106 		    /* LINTED */
107 		    = (Elf64_Half)(tl->s_index + 2);
108 		s->sb_scn.s_uflags |= ELF_F_DIRTY;
109 		tl = &s->sb_scn;
110 		ELFUNLOCK(elf)
111 		return (tl);
112 	} else {
113 		_elf_seterr(EREQ_CLASS, 0);
114 		ELFUNLOCK(elf)
115 		return (0);
116 	}
117 }
118