1178481Sjb/*
2178481Sjb * CDDL HEADER START
3178481Sjb *
4178481Sjb * The contents of this file are subject to the terms of the
5178481Sjb * Common Development and Distribution License (the "License").
6178481Sjb * You may not use this file except in compliance with the License.
7178481Sjb *
8178481Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9178481Sjb * or http://www.opensolaris.org/os/licensing.
10178481Sjb * See the License for the specific language governing permissions
11178481Sjb * and limitations under the License.
12178481Sjb *
13178481Sjb * When distributing Covered Code, include this CDDL HEADER in each
14178481Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15178481Sjb * If applicable, add the following below this CDDL HEADER, with the
16178481Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17178481Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18178481Sjb *
19178481Sjb * CDDL HEADER END
20178481Sjb */
21178481Sjb/*
22178481Sjb * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23178481Sjb * Use is subject to license terms.
24178481Sjb */
25178481Sjb
26178481Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
27178481Sjb
28178481Sjb/*
29178481Sjb * Workarounds for stabs generation bugs in the compiler and general needed
30178481Sjb * fixups.
31178481Sjb */
32178481Sjb
33178481Sjb#include <stdio.h>
34178481Sjb#include <strings.h>
35178481Sjb
36178481Sjb#include "ctf_headers.h"
37178481Sjb#include "ctftools.h"
38178481Sjb#include "hash.h"
39178481Sjb#include "memory.h"
40178481Sjb
41178481Sjb/*
42178481Sjb * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
43178481Sjb * stabs.  Given a struct foo, and a corresponding typedef struct foo foo_t.
44178481Sjb * In some cases, when faced with a pointer to a foo_t, the compiler will
45178481Sjb * sometimes generate a stab that describes a pointer to a struct foo.
46178481Sjb * Regardless of correctness, this breaks merges, as it occurs inconsistently
47178481Sjb * by file.  The following two routines know how to recognize and repair foo_t *
48178481Sjb * and foo_t ** bugs in a specific set of cases.  There is no general way to
49178481Sjb * solve this problem without a fix to the compiler.  In general, cases should
50178481Sjb * only be added to these routines to fix merging problems in genunix.
51178481Sjb */
52178481Sjbstatic void
53178481Sjbfix_ptrptr_to_struct(tdata_t *td)
54178481Sjb{
55178546Sjb	const char *strs[2] = { "as", "fdbuffer" };
56178546Sjb	const char *mems[2] = { "a_objectdir", "fd_shadow" };
57178546Sjb	const char *acts[2] = { "vnode", "page" };
58178546Sjb	const char *tgts[2] = { "vnode_t", "page_t" };
59178481Sjb	tdesc_t *str;
60178481Sjb	tdesc_t *act, *tgt;
61178481Sjb	tdesc_t *p1, *p2;
62178481Sjb	mlist_t *ml;
63178481Sjb	int i;
64178481Sjb
65178546Sjb	for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
66178481Sjb		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
67178481Sjb			continue;
68178481Sjb
69178481Sjb		for (ml = str->t_members; ml; ml = ml->ml_next) {
70178481Sjb			if (streq(ml->ml_name, mems[i]))
71178481Sjb				break;
72178481Sjb		}
73178481Sjb		if (!ml)
74178481Sjb			continue;
75178481Sjb
76178481Sjb		if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
77178481Sjb		    ml->ml_type->t_tdesc->t_type != POINTER ||
78178481Sjb		    ml->ml_type->t_tdesc->t_name)
79178481Sjb			continue;
80178481Sjb
81178481Sjb		act = ml->ml_type->t_tdesc->t_tdesc;
82178481Sjb		if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
83178481Sjb			continue;
84178481Sjb
85178481Sjb		if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
86178481Sjb			continue;
87178481Sjb
88178481Sjb		/* We have an instance of the bug */
89178481Sjb		p2 = xcalloc(sizeof (*p2));
90178481Sjb		p2->t_type = POINTER;
91178481Sjb		p2->t_id = td->td_nextid++;
92178481Sjb		p2->t_tdesc = tgt;
93178481Sjb
94178481Sjb		p1 = xcalloc(sizeof (*p1));
95178481Sjb		p1->t_type = POINTER;
96178481Sjb		p1->t_id = td->td_nextid++;
97178481Sjb		p1->t_tdesc = p2;
98178481Sjb
99178481Sjb		ml->ml_type = p1;
100178481Sjb
101178481Sjb		debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
102178481Sjb		    strs[i], mems[i], acts[i]);
103178481Sjb	}
104178481Sjb}
105178481Sjb
106178481Sjbstatic void
107178481Sjbfix_ptr_to_struct(tdata_t *td)
108178481Sjb{
109178546Sjb	const char *strs[2] = { "vmem", "id_space" };
110178546Sjb	const char *mems[2] = { NULL, "is_vmem" };
111178481Sjb	tdesc_t *ptr = NULL;
112178481Sjb	tdesc_t *str, *vmt;
113178481Sjb	mlist_t *ml;
114178481Sjb	int i;
115178481Sjb
116178481Sjb	if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
117178481Sjb		return;
118178481Sjb
119178546Sjb	for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
120178481Sjb		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
121178481Sjb			continue;
122178481Sjb
123178481Sjb		for (ml = str->t_members; ml; ml = ml->ml_next) {
124178481Sjb			if (mems[i] && !streq(ml->ml_name, mems[i]))
125178481Sjb				continue;
126178481Sjb
127178481Sjb			if (ml->ml_type->t_type != POINTER ||
128178481Sjb			    ml->ml_type->t_name ||
129178481Sjb			    (ml->ml_type->t_tdesc->t_type != STRUCT &&
130178481Sjb			    ml->ml_type->t_tdesc->t_type != FORWARD) ||
131178481Sjb			    !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
132178481Sjb				continue;
133178481Sjb
134178481Sjb			debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
135178481Sjb			    strs[i], ml->ml_name);
136178481Sjb
137178481Sjb			if (!ptr) {
138178481Sjb				ptr = xcalloc(sizeof (*ptr));
139178481Sjb				ptr->t_type = POINTER;
140178481Sjb				ptr->t_id = td->td_nextid++;
141178481Sjb				ptr->t_tdesc = vmt;
142178481Sjb			}
143178481Sjb
144178481Sjb			ml->ml_type = ptr;
145178481Sjb		}
146178481Sjb	}
147178481Sjb}
148178481Sjb
149178481Sjb/*
150178481Sjb * Fix stabs generation bugs.  These routines must be run before the
151178481Sjb * post-conversion merge
152178481Sjb */
153178481Sjbvoid
154178481Sjbcvt_fixstabs(tdata_t *td)
155178481Sjb{
156178481Sjb	fix_ptrptr_to_struct(td);
157178481Sjb	fix_ptr_to_struct(td);
158178481Sjb}
159178481Sjb
160178481Sjbstruct match {
161178481Sjb	tdesc_t *m_ret;
162178481Sjb	const char *m_name;
163178481Sjb};
164178481Sjb
165178481Sjbstatic int
166178546Sjbmatching_iidesc(void *arg1, void *arg2)
167178481Sjb{
168178546Sjb	iidesc_t *iidesc = arg1;
169178546Sjb	struct match *match = arg2;
170178481Sjb	if (!streq(iidesc->ii_name, match->m_name))
171178481Sjb		return (0);
172178481Sjb
173178481Sjb	if (iidesc->ii_type != II_TYPE && iidesc->ii_type != II_SOU)
174178481Sjb		return (0);
175178481Sjb
176178481Sjb	match->m_ret = iidesc->ii_dtype;
177178481Sjb	return (-1);
178178481Sjb}
179178481Sjb
180178481Sjbstatic tdesc_t *
181178546Sjblookup_tdesc(tdata_t *td, char const *name)
182178481Sjb{
183178481Sjb	struct match match = { NULL, name };
184178546Sjb	iter_iidescs_by_name(td, name, matching_iidesc, &match);
185178481Sjb	return (match.m_ret);
186178481Sjb}
187178481Sjb
188178481Sjb/*
189178481Sjb * The cpu structure grows, with the addition of a machcpu member, if
190178481Sjb * _MACHDEP is defined.  This means that, for example, the cpu structure
191178481Sjb * in unix is different from the cpu structure in genunix.  As one might
192178481Sjb * expect, this causes merges to fail.  Since everyone indirectly contains
193178481Sjb * a pointer to a CPU structure, the failed merges can cause massive amounts
194178481Sjb * of duplication.  In the case of unix uniquifying against genunix, upwards
195178481Sjb * of 50% of the structures were unmerged due to this problem.  We fix this
196178481Sjb * by adding a cpu_m member.  If machcpu hasn't been defined in our module,
197178481Sjb * we make a forward node for it.
198178481Sjb */
199178481Sjbstatic void
200178481Sjbfix_small_cpu_struct(tdata_t *td, size_t ptrsize)
201178481Sjb{
202178481Sjb	tdesc_t *cput, *cpu;
203178481Sjb	tdesc_t *machcpu;
204178481Sjb	mlist_t *ml, *lml;
205178481Sjb	mlist_t *cpum;
206178481Sjb	int foundcpucyc = 0;
207178481Sjb
208178481Sjb	/*
209178481Sjb	 * We're going to take the circuitous route finding the cpu structure,
210178481Sjb	 * because we want to make sure that we find the right one.  It would
211178481Sjb	 * be nice if we could verify the header name too.  DWARF might not
212178481Sjb	 * have the cpu_t, so we let this pass.
213178481Sjb	 */
214178481Sjb	if ((cput = lookup_tdesc(td, "cpu_t")) != NULL) {
215178481Sjb		if (cput->t_type != TYPEDEF)
216178481Sjb			return;
217178481Sjb		cpu = cput->t_tdesc;
218178481Sjb	} else {
219178481Sjb		cpu = lookup_tdesc(td, "cpu");
220178481Sjb	}
221178481Sjb
222178481Sjb	if (cpu == NULL)
223178481Sjb		return;
224178481Sjb
225178481Sjb	if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT)
226178481Sjb		return;
227178481Sjb
228178481Sjb	for (ml = cpu->t_members, lml = NULL; ml;
229178481Sjb	    lml = ml, ml = ml->ml_next) {
230178481Sjb		if (strcmp(ml->ml_name, "cpu_cyclic") == 0)
231178481Sjb			foundcpucyc = 1;
232178481Sjb	}
233178481Sjb
234178481Sjb	if (foundcpucyc == 0 || lml == NULL ||
235178481Sjb	    strcmp(lml->ml_name, "cpu_m") == 0)
236178481Sjb		return;
237178481Sjb
238178481Sjb	/*
239178481Sjb	 * We need to derive the right offset for the fake cpu_m member.  To do
240178481Sjb	 * that, we require a special unused member to be the last member
241178481Sjb	 * before the 'cpu_m', that we encode knowledge of here.  ABI alignment
242178481Sjb	 * on all platforms is such that we only need to add a pointer-size
243178481Sjb	 * number of bits to get the right offset for cpu_m.  This would most
244178481Sjb	 * likely break if gcc's -malign-double were ever used, but that option
245178481Sjb	 * breaks the ABI anyway.
246178481Sjb	 */
247178481Sjb	if (!streq(lml->ml_name, "cpu_m_pad") &&
248178481Sjb	    getenv("CTFCONVERT_PERMISSIVE") == NULL) {
249178481Sjb		terminate("last cpu_t member before cpu_m is %s; "
250178481Sjb		    "it must be cpu_m_pad.\n", lml->ml_name);
251178481Sjb	}
252178481Sjb
253178481Sjb	if ((machcpu = lookup_tdesc(td, "machcpu")) == NULL) {
254178481Sjb		machcpu = xcalloc(sizeof (*machcpu));
255178481Sjb		machcpu->t_name = xstrdup("machcpu");
256178481Sjb		machcpu->t_id = td->td_nextid++;
257178481Sjb		machcpu->t_type = FORWARD;
258178481Sjb	} else if (machcpu->t_type != STRUCT) {
259178481Sjb		return;
260178481Sjb	}
261178481Sjb
262178481Sjb	debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
263178481Sjb	    (machcpu->t_type == FORWARD ? "forward" : "struct"));
264178481Sjb
265178481Sjb	cpum = xmalloc(sizeof (*cpum));
266178481Sjb	cpum->ml_offset = lml->ml_offset + (ptrsize * NBBY);
267178481Sjb	cpum->ml_size = 0;
268178481Sjb	cpum->ml_name = xstrdup("cpu_m");
269178481Sjb	cpum->ml_type = machcpu;
270178481Sjb	cpum->ml_next = NULL;
271178481Sjb
272178481Sjb	lml->ml_next = cpum;
273178481Sjb}
274178481Sjb
275178481Sjbvoid
276178481Sjbcvt_fixups(tdata_t *td, size_t ptrsize)
277178481Sjb{
278178481Sjb	fix_small_cpu_struct(td, ptrsize);
279178481Sjb}
280