xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/newdata.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI" 	/* SVr4.0 1.2	*/
33 
34 #pragma weak	elf_newdata = _elf_newdata
35 
36 
37 #include "syn.h"
38 #include "libelf.h"
39 #include "decl.h"
40 #include "msg.h"
41 
42 
43 Elf_Data *
44 elf_newdata(Elf_Scn * s)
45 {
46 	Dnode *		d;
47 	Elf_Data *	rc;
48 	Elf *		elf;
49 	unsigned	work;
50 
51 	if (s == 0)
52 		return (0);
53 	elf = s->s_elf;
54 	READLOCKS(elf, s)
55 	if (s->s_index == SHN_UNDEF) {
56 		_elf_seterr(EREQ_SCNNULL, 0);
57 		READUNLOCKS(elf, s)
58 		return (0);
59 	}
60 
61 	if ((s->s_myflags & SF_READY) == 0) {
62 		UPGRADELOCKS(elf, s)
63 		/*
64 		 * re-confirm that another 'thread' hasn't come along
65 		 * and cooked this section while the locks were
66 		 * obtained.
67 		 */
68 		if ((s->s_myflags & SF_READY) == 0)
69 			(void) _elf_cookscn(s);
70 		DOWNGRADELOCKS(elf, s)
71 	}
72 
73 	/*
74 	 * If this is the first new node, use the one allocated
75 	 * in the scn itself.  Update data buffer in both cases.
76 	 */
77 	ELFACCESSDATA(work, _elf_work)
78 	if (s->s_hdnode == 0) {
79 		s->s_dnode.db_uflags |= ELF_F_DIRTY;
80 		s->s_dnode.db_myflags |= DBF_READY;
81 		s->s_hdnode = &s->s_dnode;
82 		s->s_tlnode = &s->s_dnode;
83 		s->s_dnode.db_scn = s;
84 		s->s_dnode.db_data.d_version = work;
85 		rc = &s->s_dnode.db_data;
86 		READUNLOCKS(elf, s)
87 		return (rc);
88 	}
89 	if ((d = _elf_dnode()) == 0) {
90 		READUNLOCKS(elf, s)
91 		return (0);
92 	}
93 	NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d))
94 	d->db_data.d_version = work;
95 	d->db_scn = s;
96 	d->db_uflags |= ELF_F_DIRTY;
97 	d->db_myflags |= DBF_READY;
98 	s->s_tlnode->db_next = d;
99 	s->s_tlnode = d;
100 	rc = &d->db_data;
101 	NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d))
102 	READUNLOCKS(elf, s)
103 	return (rc);
104 }
105