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.
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.
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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Workarounds for stabs generation bugs in the compiler and general needed
36 #include "ctf_headers.h"
42 * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
43 * stabs. Given a struct foo, and a corresponding typedef struct foo foo_t.
44 * In some cases, when faced with a pointer to a foo_t, the compiler will
45 * sometimes generate a stab that describes a pointer to a struct foo.
46 * Regardless of correctness, this breaks merges, as it occurs inconsistently
47 * by file. The following two routines know how to recognize and repair foo_t *
48 * and foo_t ** bugs in a specific set of cases. There is no general way to
49 * solve this problem without a fix to the compiler. In general, cases should
50 * only be added to these routines to fix merging problems in genunix.
53 fix_ptrptr_to_struct(tdata_t
*td
)
55 char *strs
[2] = { "as", "fdbuffer" };
56 char *mems
[2] = { "a_objectdir", "fd_shadow" };
57 char *acts
[2] = { "vnode", "page" };
58 char *tgts
[2] = { "vnode_t", "page_t" };
65 for (i
= 0; i
< sizeof (strs
) / sizeof (strs
[0]); i
++) {
66 if (!(str
= lookupname(strs
[i
])) || str
->t_type
!= STRUCT
)
69 for (ml
= str
->t_members
; ml
; ml
= ml
->ml_next
) {
70 if (streq(ml
->ml_name
, mems
[i
]))
76 if (ml
->ml_type
->t_type
!= POINTER
|| ml
->ml_type
->t_name
||
77 ml
->ml_type
->t_tdesc
->t_type
!= POINTER
||
78 ml
->ml_type
->t_tdesc
->t_name
)
81 act
= ml
->ml_type
->t_tdesc
->t_tdesc
;
82 if (act
->t_type
!= STRUCT
|| !streq(act
->t_name
, acts
[i
]))
85 if (!(tgt
= lookupname(tgts
[i
])) || tgt
->t_type
!= TYPEDEF
)
88 /* We have an instance of the bug */
89 p2
= xcalloc(sizeof (*p2
));
91 p2
->t_id
= td
->td_nextid
++;
94 p1
= xcalloc(sizeof (*p1
));
96 p1
->t_id
= td
->td_nextid
++;
101 debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
102 strs
[i
], mems
[i
], acts
[i
]);
107 fix_ptr_to_struct(tdata_t
*td
)
109 char *strs
[2] = { "vmem", "id_space" };
110 char *mems
[2] = { NULL
, "is_vmem" };
116 if ((vmt
= lookupname("vmem_t")) == NULL
|| vmt
->t_type
!= TYPEDEF
)
119 for (i
= 0; i
< sizeof (strs
) / sizeof (strs
[0]); i
++) {
120 if (!(str
= lookupname(strs
[i
])) || str
->t_type
!= STRUCT
)
123 for (ml
= str
->t_members
; ml
; ml
= ml
->ml_next
) {
124 if (mems
[i
] && !streq(ml
->ml_name
, mems
[i
]))
127 if (ml
->ml_type
->t_type
!= POINTER
||
128 ml
->ml_type
->t_name
||
129 (ml
->ml_type
->t_tdesc
->t_type
!= STRUCT
&&
130 ml
->ml_type
->t_tdesc
->t_type
!= FORWARD
) ||
131 !streq(ml
->ml_type
->t_tdesc
->t_name
, "vmem"))
134 debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
135 strs
[i
], ml
->ml_name
);
138 ptr
= xcalloc(sizeof (*ptr
));
139 ptr
->t_type
= POINTER
;
140 ptr
->t_id
= td
->td_nextid
++;
150 * Fix stabs generation bugs. These routines must be run before the
151 * post-conversion merge
154 cvt_fixstabs(tdata_t
*td
)
156 fix_ptrptr_to_struct(td
);
157 fix_ptr_to_struct(td
);
166 matching_iidesc(iidesc_t
*iidesc
, struct match
*match
)
168 if (!streq(iidesc
->ii_name
, match
->m_name
))
171 if (iidesc
->ii_type
!= II_TYPE
&& iidesc
->ii_type
!= II_SOU
)
174 match
->m_ret
= iidesc
->ii_dtype
;
179 lookup_tdesc(tdata_t
*td
, const char *name
)
181 struct match match
= { NULL
, name
};
182 iter_iidescs_by_name(td
, name
, (int (*)())matching_iidesc
, &match
);
183 return (match
.m_ret
);
187 * The cpu structure grows, with the addition of a machcpu member, if
188 * _MACHDEP is defined. This means that, for example, the cpu structure
189 * in unix is different from the cpu structure in genunix. As one might
190 * expect, this causes merges to fail. Since everyone indirectly contains
191 * a pointer to a CPU structure, the failed merges can cause massive amounts
192 * of duplication. In the case of unix uniquifying against genunix, upwards
193 * of 50% of the structures were unmerged due to this problem. We fix this
194 * by adding a cpu_m member. If machcpu hasn't been defined in our module,
195 * we make a forward node for it.
198 fix_small_cpu_struct(tdata_t
*td
, size_t ptrsize
)
207 * We're going to take the circuitous route finding the cpu structure,
208 * because we want to make sure that we find the right one. It would
209 * be nice if we could verify the header name too. DWARF might not
210 * have the cpu_t, so we let this pass.
212 if ((cput
= lookup_tdesc(td
, "cpu_t")) != NULL
) {
213 if (cput
->t_type
!= TYPEDEF
)
217 cpu
= lookup_tdesc(td
, "cpu");
223 if (!streq(cpu
->t_name
, "cpu") || cpu
->t_type
!= STRUCT
)
226 for (ml
= cpu
->t_members
, lml
= NULL
; ml
;
227 lml
= ml
, ml
= ml
->ml_next
) {
228 if (strcmp(ml
->ml_name
, "cpu_cyclic") == 0)
232 if (foundcpucyc
== 0 || lml
== NULL
||
233 strcmp(lml
->ml_name
, "cpu_m") == 0)
237 * We need to derive the right offset for the fake cpu_m member. To do
238 * that, we require a special unused member to be the last member
239 * before the 'cpu_m', that we encode knowledge of here. ABI alignment
240 * on all platforms is such that we only need to add a pointer-size
241 * number of bits to get the right offset for cpu_m. This would most
242 * likely break if gcc's -malign-double were ever used, but that option
243 * breaks the ABI anyway.
245 if (!streq(lml
->ml_name
, "cpu_m_pad") &&
246 getenv("CTFCONVERT_PERMISSIVE") == NULL
) {
247 terminate("last cpu_t member before cpu_m is %s; "
248 "it must be cpu_m_pad.\n", lml
->ml_name
);
251 if ((machcpu
= lookup_tdesc(td
, "machcpu")) == NULL
) {
252 machcpu
= xcalloc(sizeof (*machcpu
));
253 machcpu
->t_name
= xstrdup("machcpu");
254 machcpu
->t_id
= td
->td_nextid
++;
255 machcpu
->t_type
= FORWARD
;
256 } else if (machcpu
->t_type
!= STRUCT
) {
260 debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
261 (machcpu
->t_type
== FORWARD
? "forward" : "struct"));
263 cpum
= xmalloc(sizeof (*cpum
));
264 cpum
->ml_offset
= lml
->ml_offset
+ (ptrsize
* NBBY
);
266 cpum
->ml_name
= xstrdup("cpu_m");
267 cpum
->ml_type
= machcpu
;
268 cpum
->ml_next
= NULL
;
274 cvt_fixups(tdata_t
*td
, size_t ptrsize
)
276 fix_small_cpu_struct(td
, ptrsize
);