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	"@(#)rawdata.c	1.13	08/05/31 SMI"
31
32#include <stdlib.h>
33#include "libelf.h"
34#include "decl.h"
35#include "msg.h"
36
37
38Elf_Data *
39elf_rawdata(Elf_Scn * scn, Elf_Data * data)
40{
41	Dnode *		d = (Dnode *)data;
42	Dnode *		raw;
43	Elf_Data *	rc;
44	Elf *		elf;
45
46	if (scn == 0)
47		return (0);
48	elf = scn->s_elf;
49	READLOCKS(elf, scn)
50	if ((scn->s_myflags & SF_READY) == 0) {
51		UPGRADELOCKS(elf, scn)
52		if ((scn->s_myflags & SF_READY) == 0)
53			(void) _elf_cookscn(scn);
54		DOWNGRADELOCKS(elf, scn)
55	}
56
57	if (d == 0)
58		d = scn->s_hdnode;
59	else
60		d = d->db_next;
61
62	if (d == 0) {
63		READUNLOCKS(elf, scn)
64		return (0);
65	}
66
67	if (d->db_scn != scn) {
68		_elf_seterr(EREQ_DATA, 0);
69		READUNLOCKS(elf, scn)
70		return (0);
71	}
72
73	/*
74	 * The data may come from a previously constructed Dbuf,
75	 * from the file's raw memory image, or the file system.
76	 * "Empty" regions get an empty buffer.
77	 */
78
79	if (d->db_raw != 0) {
80		rc = &d->db_raw->db_data;
81		READUNLOCKS(elf, scn)
82		return (rc);
83	}
84
85	if ((raw = _elf_dnode()) == 0)  {
86		READUNLOCKS(elf, scn)
87		return (0);
88	}
89	raw->db_myflags |= DBF_READY;
90	if ((d->db_off == 0) || (d->db_fsz == 0)) {
91		d->db_raw = raw;
92		raw->db_data.d_size = d->db_shsz;
93		rc = &raw->db_data;
94		READUNLOCKS(elf, scn)
95		return (rc);
96	}
97
98	/*
99	 * validate the region
100	 */
101
102	if ((d->db_off < 0) ||
103	    (d->db_off >= elf->ed_fsz) ||
104	    (elf->ed_fsz - d->db_off < d->db_fsz)) {
105		_elf_seterr(EFMT_DATA, 0);
106		free(raw);
107		READUNLOCKS(elf, scn)
108		return (0);
109	}
110	raw->db_data.d_size = d->db_fsz;
111	if (elf->ed_raw != 0) {
112		raw->db_data.d_buf = (Elf_Void *)(elf->ed_raw + d->db_off);
113		d->db_raw = raw;
114		rc = &raw->db_data;
115		READUNLOCKS(elf, scn)
116		return (rc);
117	}
118	raw->db_buf = (Elf_Void *)_elf_read(elf->ed_fd,
119			elf->ed_baseoff + d->db_off, d->db_fsz);
120	if (raw->db_buf == 0) {
121		free(raw);
122		READUNLOCKS(elf, scn)
123		return (0);
124	}
125	raw->db_data.d_buf = raw->db_buf;
126	d->db_raw = raw;
127	rc = &raw->db_data;
128	READUNLOCKS(elf, scn)
129	return (rc);
130}
131