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