1 1.1 darran /* 2 1.1 darran * CDDL HEADER START 3 1.1 darran * 4 1.1 darran * The contents of this file are subject to the terms of the 5 1.1 darran * Common Development and Distribution License (the "License"). 6 1.1 darran * You may not use this file except in compliance with the License. 7 1.1 darran * 8 1.1 darran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 1.1 darran * or http://www.opensolaris.org/os/licensing. 10 1.1 darran * See the License for the specific language governing permissions 11 1.1 darran * and limitations under the License. 12 1.1 darran * 13 1.1 darran * When distributing Covered Code, include this CDDL HEADER in each 14 1.1 darran * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 1.1 darran * If applicable, add the following below this CDDL HEADER, with the 16 1.1 darran * fields enclosed by brackets "[]" replaced with your own identifying 17 1.1 darran * information: Portions Copyright [yyyy] [name of copyright owner] 18 1.1 darran * 19 1.1 darran * CDDL HEADER END 20 1.1 darran */ 21 1.1 darran /* 22 1.1 darran * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 1.1 darran * Use is subject to license terms. 24 1.1 darran */ 25 1.1 darran 26 1.1 darran #pragma ident "%Z%%M% %I% %E% SMI" 27 1.1 darran 28 1.1 darran /* 29 1.1 darran * Workarounds for stabs generation bugs in the compiler and general needed 30 1.1 darran * fixups. 31 1.1 darran */ 32 1.1 darran 33 1.3 darran #if HAVE_NBTOOL_CONFIG_H 34 1.3 darran # include "nbtool_config.h" 35 1.3 darran #endif 36 1.3 darran 37 1.1 darran #include <stdio.h> 38 1.1 darran #include <strings.h> 39 1.1 darran 40 1.1 darran #include "ctf_headers.h" 41 1.1 darran #include "ctftools.h" 42 1.1 darran #include "hash.h" 43 1.1 darran #include "memory.h" 44 1.5 hannken #include "traverse.h" 45 1.1 darran 46 1.1 darran /* 47 1.1 darran * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer 48 1.1 darran * stabs. Given a struct foo, and a corresponding typedef struct foo foo_t. 49 1.1 darran * In some cases, when faced with a pointer to a foo_t, the compiler will 50 1.1 darran * sometimes generate a stab that describes a pointer to a struct foo. 51 1.1 darran * Regardless of correctness, this breaks merges, as it occurs inconsistently 52 1.1 darran * by file. The following two routines know how to recognize and repair foo_t * 53 1.1 darran * and foo_t ** bugs in a specific set of cases. There is no general way to 54 1.1 darran * solve this problem without a fix to the compiler. In general, cases should 55 1.1 darran * only be added to these routines to fix merging problems in genunix. 56 1.1 darran */ 57 1.1 darran static void 58 1.1 darran fix_ptrptr_to_struct(tdata_t *td) 59 1.1 darran { 60 1.2 darran const char *strs[2] = { "as", "fdbuffer" }; 61 1.2 darran const char *mems[2] = { "a_objectdir", "fd_shadow" }; 62 1.2 darran const char *acts[2] = { "vnode", "page" }; 63 1.2 darran const char *tgts[2] = { "vnode_t", "page_t" }; 64 1.1 darran tdesc_t *str; 65 1.1 darran tdesc_t *act, *tgt; 66 1.1 darran tdesc_t *p1, *p2; 67 1.1 darran mlist_t *ml; 68 1.1 darran int i; 69 1.1 darran 70 1.2 darran for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) { 71 1.1 darran if (!(str = lookupname(strs[i])) || str->t_type != STRUCT) 72 1.1 darran continue; 73 1.1 darran 74 1.1 darran for (ml = str->t_members; ml; ml = ml->ml_next) { 75 1.1 darran if (streq(ml->ml_name, mems[i])) 76 1.1 darran break; 77 1.1 darran } 78 1.1 darran if (!ml) 79 1.1 darran continue; 80 1.1 darran 81 1.1 darran if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name || 82 1.1 darran ml->ml_type->t_tdesc->t_type != POINTER || 83 1.1 darran ml->ml_type->t_tdesc->t_name) 84 1.1 darran continue; 85 1.1 darran 86 1.1 darran act = ml->ml_type->t_tdesc->t_tdesc; 87 1.1 darran if (act->t_type != STRUCT || !streq(act->t_name, acts[i])) 88 1.1 darran continue; 89 1.1 darran 90 1.1 darran if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF) 91 1.1 darran continue; 92 1.1 darran 93 1.1 darran /* We have an instance of the bug */ 94 1.1 darran p2 = xcalloc(sizeof (*p2)); 95 1.1 darran p2->t_type = POINTER; 96 1.1 darran p2->t_id = td->td_nextid++; 97 1.1 darran p2->t_tdesc = tgt; 98 1.1 darran 99 1.1 darran p1 = xcalloc(sizeof (*p1)); 100 1.1 darran p1->t_type = POINTER; 101 1.1 darran p1->t_id = td->td_nextid++; 102 1.1 darran p1->t_tdesc = p2; 103 1.1 darran 104 1.1 darran ml->ml_type = p1; 105 1.1 darran 106 1.1 darran debug(3, "Fixed %s->%s => ptrptr struct %s bug\n", 107 1.1 darran strs[i], mems[i], acts[i]); 108 1.1 darran } 109 1.1 darran } 110 1.1 darran 111 1.1 darran static void 112 1.1 darran fix_ptr_to_struct(tdata_t *td) 113 1.1 darran { 114 1.2 darran const char *strs[2] = { "vmem", "id_space" }; 115 1.2 darran const char *mems[2] = { NULL, "is_vmem" }; 116 1.1 darran tdesc_t *ptr = NULL; 117 1.1 darran tdesc_t *str, *vmt; 118 1.1 darran mlist_t *ml; 119 1.1 darran int i; 120 1.1 darran 121 1.1 darran if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF) 122 1.1 darran return; 123 1.1 darran 124 1.2 darran for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) { 125 1.1 darran if (!(str = lookupname(strs[i])) || str->t_type != STRUCT) 126 1.1 darran continue; 127 1.1 darran 128 1.1 darran for (ml = str->t_members; ml; ml = ml->ml_next) { 129 1.1 darran if (mems[i] && !streq(ml->ml_name, mems[i])) 130 1.1 darran continue; 131 1.1 darran 132 1.1 darran if (ml->ml_type->t_type != POINTER || 133 1.1 darran ml->ml_type->t_name || 134 1.1 darran (ml->ml_type->t_tdesc->t_type != STRUCT && 135 1.1 darran ml->ml_type->t_tdesc->t_type != FORWARD) || 136 1.1 darran !streq(ml->ml_type->t_tdesc->t_name, "vmem")) 137 1.1 darran continue; 138 1.1 darran 139 1.1 darran debug(3, "Fixed %s->%s => ptr struct vmem bug\n", 140 1.1 darran strs[i], ml->ml_name); 141 1.1 darran 142 1.1 darran if (!ptr) { 143 1.1 darran ptr = xcalloc(sizeof (*ptr)); 144 1.1 darran ptr->t_type = POINTER; 145 1.1 darran ptr->t_id = td->td_nextid++; 146 1.1 darran ptr->t_tdesc = vmt; 147 1.1 darran } 148 1.1 darran 149 1.1 darran ml->ml_type = ptr; 150 1.1 darran } 151 1.1 darran } 152 1.1 darran } 153 1.1 darran 154 1.1 darran /* 155 1.1 darran * Fix stabs generation bugs. These routines must be run before the 156 1.1 darran * post-conversion merge 157 1.1 darran */ 158 1.1 darran void 159 1.1 darran cvt_fixstabs(tdata_t *td) 160 1.1 darran { 161 1.1 darran fix_ptrptr_to_struct(td); 162 1.1 darran fix_ptr_to_struct(td); 163 1.1 darran } 164 1.1 darran 165 1.1 darran struct match { 166 1.1 darran tdesc_t *m_ret; 167 1.1 darran const char *m_name; 168 1.1 darran }; 169 1.1 darran 170 1.1 darran static int 171 1.2 darran matching_iidesc(void *arg1, void *arg2) 172 1.1 darran { 173 1.2 darran iidesc_t *iidesc = arg1; 174 1.2 darran struct match *match = arg2; 175 1.1 darran if (!streq(iidesc->ii_name, match->m_name)) 176 1.1 darran return (0); 177 1.1 darran 178 1.1 darran if (iidesc->ii_type != II_TYPE && iidesc->ii_type != II_SOU) 179 1.1 darran return (0); 180 1.1 darran 181 1.1 darran match->m_ret = iidesc->ii_dtype; 182 1.1 darran return (-1); 183 1.1 darran } 184 1.1 darran 185 1.1 darran static tdesc_t * 186 1.2 darran lookup_tdesc(tdata_t *td, char const *name) 187 1.1 darran { 188 1.1 darran struct match match = { NULL, name }; 189 1.2 darran iter_iidescs_by_name(td, name, matching_iidesc, &match); 190 1.1 darran return (match.m_ret); 191 1.1 darran } 192 1.1 darran 193 1.1 darran /* 194 1.1 darran * The cpu structure grows, with the addition of a machcpu member, if 195 1.1 darran * _MACHDEP is defined. This means that, for example, the cpu structure 196 1.1 darran * in unix is different from the cpu structure in genunix. As one might 197 1.1 darran * expect, this causes merges to fail. Since everyone indirectly contains 198 1.1 darran * a pointer to a CPU structure, the failed merges can cause massive amounts 199 1.1 darran * of duplication. In the case of unix uniquifying against genunix, upwards 200 1.1 darran * of 50% of the structures were unmerged due to this problem. We fix this 201 1.1 darran * by adding a cpu_m member. If machcpu hasn't been defined in our module, 202 1.1 darran * we make a forward node for it. 203 1.1 darran */ 204 1.1 darran static void 205 1.1 darran fix_small_cpu_struct(tdata_t *td, size_t ptrsize) 206 1.1 darran { 207 1.1 darran tdesc_t *cput, *cpu; 208 1.1 darran tdesc_t *machcpu; 209 1.1 darran mlist_t *ml, *lml; 210 1.1 darran mlist_t *cpum; 211 1.1 darran int foundcpucyc = 0; 212 1.1 darran 213 1.1 darran /* 214 1.1 darran * We're going to take the circuitous route finding the cpu structure, 215 1.1 darran * because we want to make sure that we find the right one. It would 216 1.1 darran * be nice if we could verify the header name too. DWARF might not 217 1.1 darran * have the cpu_t, so we let this pass. 218 1.1 darran */ 219 1.1 darran if ((cput = lookup_tdesc(td, "cpu_t")) != NULL) { 220 1.1 darran if (cput->t_type != TYPEDEF) 221 1.1 darran return; 222 1.1 darran cpu = cput->t_tdesc; 223 1.1 darran } else { 224 1.1 darran cpu = lookup_tdesc(td, "cpu"); 225 1.1 darran } 226 1.1 darran 227 1.1 darran if (cpu == NULL) 228 1.1 darran return; 229 1.1 darran 230 1.1 darran if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT) 231 1.1 darran return; 232 1.1 darran 233 1.1 darran for (ml = cpu->t_members, lml = NULL; ml; 234 1.1 darran lml = ml, ml = ml->ml_next) { 235 1.1 darran if (strcmp(ml->ml_name, "cpu_cyclic") == 0) 236 1.1 darran foundcpucyc = 1; 237 1.1 darran } 238 1.1 darran 239 1.1 darran if (foundcpucyc == 0 || lml == NULL || 240 1.1 darran strcmp(lml->ml_name, "cpu_m") == 0) 241 1.1 darran return; 242 1.1 darran 243 1.1 darran /* 244 1.1 darran * We need to derive the right offset for the fake cpu_m member. To do 245 1.1 darran * that, we require a special unused member to be the last member 246 1.1 darran * before the 'cpu_m', that we encode knowledge of here. ABI alignment 247 1.1 darran * on all platforms is such that we only need to add a pointer-size 248 1.1 darran * number of bits to get the right offset for cpu_m. This would most 249 1.1 darran * likely break if gcc's -malign-double were ever used, but that option 250 1.1 darran * breaks the ABI anyway. 251 1.1 darran */ 252 1.1 darran if (!streq(lml->ml_name, "cpu_m_pad") && 253 1.1 darran getenv("CTFCONVERT_PERMISSIVE") == NULL) { 254 1.1 darran terminate("last cpu_t member before cpu_m is %s; " 255 1.1 darran "it must be cpu_m_pad.\n", lml->ml_name); 256 1.1 darran } 257 1.1 darran 258 1.1 darran if ((machcpu = lookup_tdesc(td, "machcpu")) == NULL) { 259 1.1 darran machcpu = xcalloc(sizeof (*machcpu)); 260 1.1 darran machcpu->t_name = xstrdup("machcpu"); 261 1.1 darran machcpu->t_id = td->td_nextid++; 262 1.1 darran machcpu->t_type = FORWARD; 263 1.1 darran } else if (machcpu->t_type != STRUCT) { 264 1.1 darran return; 265 1.1 darran } 266 1.1 darran 267 1.1 darran debug(3, "Adding cpu_m machcpu %s to cpu struct\n", 268 1.1 darran (machcpu->t_type == FORWARD ? "forward" : "struct")); 269 1.1 darran 270 1.1 darran cpum = xmalloc(sizeof (*cpum)); 271 1.1 darran cpum->ml_offset = lml->ml_offset + (ptrsize * NBBY); 272 1.1 darran cpum->ml_size = 0; 273 1.1 darran cpum->ml_name = xstrdup("cpu_m"); 274 1.1 darran cpum->ml_type = machcpu; 275 1.1 darran cpum->ml_next = NULL; 276 1.1 darran 277 1.1 darran lml->ml_next = cpum; 278 1.1 darran } 279 1.1 darran 280 1.8 christos #if defined(__NetBSD__) || HAVE_NBTOOL_CONFIG_H 281 1.4 hannken 282 1.4 hannken /* 283 1.5 hannken * XXX: A crude hack to bring down the number of types for a 284 1.7 wiz * GENERIC kernel below 2**15-1 (from ~34000 to ~29800). 285 1.5 hannken * 286 1.5 hannken * Remove the type attributes "volatile", "const" and "restrict", 287 1.5 hannken * for DTRACE these attributes are of little value. 288 1.5 hannken */ 289 1.5 hannken 290 1.5 hannken static int 291 1.5 hannken fix_kill_attr_cb(tdesc_t *tdp, tdesc_t **tdpp, void *private __unused) 292 1.5 hannken { 293 1.5 hannken 294 1.5 hannken while (tdp->t_type == VOLATILE || 295 1.5 hannken tdp->t_type == RESTRICT || 296 1.5 hannken tdp->t_type == CONST) 297 1.5 hannken tdp = tdp->t_tdesc; 298 1.5 hannken 299 1.5 hannken *tdpp = tdp; 300 1.5 hannken 301 1.5 hannken return 1; 302 1.5 hannken } 303 1.5 hannken 304 1.5 hannken static tdtrav_cb_f fix_kill_attr_tab[] = { 305 1.5 hannken NULL, 306 1.5 hannken NULL, /* intrinsic */ 307 1.5 hannken NULL, /* pointer */ 308 1.5 hannken NULL, /* reference */ 309 1.5 hannken NULL, /* array */ 310 1.5 hannken NULL, /* function */ 311 1.5 hannken NULL, /* struct */ 312 1.5 hannken NULL, /* union */ 313 1.5 hannken NULL, /* class */ 314 1.5 hannken NULL, /* enum */ 315 1.5 hannken NULL , /* forward */ 316 1.5 hannken NULL, /* typedef */ 317 1.5 hannken NULL, /* typedef unres */ 318 1.5 hannken fix_kill_attr_cb, /* volatile */ 319 1.5 hannken fix_kill_attr_cb, /* const */ 320 1.5 hannken fix_kill_attr_cb, /* restrict */ 321 1.5 hannken }; 322 1.5 hannken 323 1.5 hannken static void 324 1.5 hannken fix_kill_attr(tdata_t *td, size_t ptrsize) 325 1.5 hannken { 326 1.5 hannken 327 1.5 hannken (void) iitraverse_hash(td->td_iihash, &td->td_curvgen, 328 1.5 hannken fix_kill_attr_tab, NULL, NULL, NULL); 329 1.5 hannken } 330 1.5 hannken 331 1.9 ozaki #endif /* __NetBSD__ || HAVE_NBTOOL_CONFIG_H */ 332 1.4 hannken 333 1.1 darran void 334 1.1 darran cvt_fixups(tdata_t *td, size_t ptrsize) 335 1.1 darran { 336 1.1 darran fix_small_cpu_struct(td, ptrsize); 337 1.9 ozaki #if defined(__NetBSD__) || HAVE_NBTOOL_CONFIG_H 338 1.5 hannken fix_kill_attr(td, ptrsize); 339 1.4 hannken #endif 340 1.1 darran } 341