Print this page
10812 ctf tools shouldn't add blank labels
10813 ctf symbol mapping needs work
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libctf/common/ctf_merge.c
+++ new/usr/src/lib/libctf/common/ctf_merge.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright (c) 2015 Joyent, Inc.
13 + * Copyright (c) 2019 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * To perform a merge of two CTF containers, we first diff the two containers
18 18 * types. For every type that's in the src container, but not in the dst
19 19 * container, we note it and add it to dst container. If there are any objects
20 20 * or functions associated with src, we go through and update the types that
21 21 * they refer to such that they all refer to types in the dst container.
22 22 *
23 23 * The bulk of the logic for the merge, after we've run the diff, occurs in
24 24 * ctf_merge_common().
25 25 *
26 26 * In terms of exported APIs, we don't really export a simple merge two
27 27 * containers, as the general way this is used, in something like ctfmerge(1),
28 28 * is to add all the containers and then let us figure out the best way to merge
29 29 * it.
30 30 */
31 31
32 32 #include <libctf_impl.h>
33 33 #include <sys/debug.h>
34 34 #include <sys/list.h>
35 35 #include <stddef.h>
36 36 #include <fcntl.h>
37 37 #include <sys/types.h>
38 38 #include <sys/stat.h>
39 39 #include <mergeq.h>
40 40 #include <errno.h>
41 41
42 42 typedef struct ctf_merge_tinfo {
43 43 uint16_t cmt_map; /* Map to the type in out */
44 44 boolean_t cmt_fixup;
45 45 boolean_t cmt_forward;
46 46 boolean_t cmt_missing;
47 47 } ctf_merge_tinfo_t;
48 48
49 49 /*
50 50 * State required for doing an individual merge of two containers.
51 51 */
52 52 typedef struct ctf_merge_types {
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
53 53 ctf_file_t *cm_out; /* Output CTF file */
54 54 ctf_file_t *cm_src; /* Input CTF file */
55 55 ctf_merge_tinfo_t *cm_tmap; /* Type state information */
56 56 boolean_t cm_dedup; /* Are we doing a dedup? */
57 57 boolean_t cm_unique; /* are we doing a uniquify? */
58 58 } ctf_merge_types_t;
59 59
60 60 typedef struct ctf_merge_objmap {
61 61 list_node_t cmo_node;
62 62 const char *cmo_name; /* Symbol name */
63 + const char *cmo_file; /* Symbol file */
63 64 ulong_t cmo_idx; /* Symbol ID */
65 + Elf64_Sym cmo_sym; /* Symbol Entry */
64 66 ctf_id_t cmo_tid; /* Type ID */
65 67 } ctf_merge_objmap_t;
66 68
67 69 typedef struct ctf_merge_funcmap {
68 70 list_node_t cmf_node;
69 71 const char *cmf_name; /* Symbol name */
72 + const char *cmf_file; /* Symbol file */
70 73 ulong_t cmf_idx; /* Symbol ID */
74 + Elf64_Sym cmf_sym; /* Symbol Entry */
71 75 ctf_id_t cmf_rtid; /* Type ID */
72 76 uint_t cmf_flags; /* ctf_funcinfo_t ctc_flags */
73 77 uint_t cmf_argc; /* Number of arguments */
74 78 ctf_id_t cmf_args[]; /* Types of arguments */
75 79 } ctf_merge_funcmap_t;
76 80
77 81 typedef struct ctf_merge_input {
78 82 list_node_t cmi_node;
79 83 ctf_file_t *cmi_input;
80 84 list_t cmi_omap;
81 85 list_t cmi_fmap;
82 86 boolean_t cmi_created;
83 87 } ctf_merge_input_t;
84 88
85 89 struct ctf_merge_handle {
86 90 list_t cmh_inputs; /* Input list */
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
87 91 uint_t cmh_ninputs; /* Number of inputs */
88 92 uint_t cmh_nthreads; /* Number of threads to use */
89 93 ctf_file_t *cmh_unique; /* ctf to uniquify against */
90 94 boolean_t cmh_msyms; /* Should we merge symbols/funcs? */
91 95 int cmh_ofd; /* FD for output file */
92 96 int cmh_flags; /* Flags that control merge behavior */
93 97 char *cmh_label; /* Optional label */
94 98 char *cmh_pname; /* Parent name */
95 99 };
96 100
101 +typedef struct ctf_merge_symbol_arg {
102 + list_t *cmsa_objmap;
103 + list_t *cmsa_funcmap;
104 + ctf_file_t *cmsa_out;
105 + boolean_t cmsa_dedup;
106 +} ctf_merge_symbol_arg_t;
107 +
97 108 static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
98 109
99 110 static ctf_id_t
100 111 ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
101 112 {
102 113 if (cmp->cm_dedup == B_FALSE) {
103 114 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
104 115 return (cmp->cm_tmap[id].cmt_map);
105 116 }
106 117
107 118 while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
108 119 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
109 120 id = cmp->cm_tmap[id].cmt_map;
110 121 }
111 122 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
112 123 return (cmp->cm_tmap[id].cmt_map);
113 124 }
114 125
115 126 static void
116 127 ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
117 128 ctf_id_t oid, void *arg)
118 129 {
119 130 ctf_merge_types_t *cmp = arg;
120 131 ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
121 132
122 133 if (same == B_TRUE) {
123 134 if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD &&
124 135 ctf_type_kind(ofp, oid) != CTF_K_FORWARD) {
125 136 VERIFY(cmt[oid].cmt_map == 0);
126 137
127 138 /*
128 139 * If we're uniquifying types, it's possible for the
129 140 * container that we're uniquifying against to have a
130 141 * forward which exists in the container being reduced.
131 142 * For example, genunix has the machcpu structure as a
132 143 * forward which is actually in unix and we uniquify
133 144 * unix against genunix. In such cases, we explicitly do
134 145 * not do any mapping of the forward information, lest
135 146 * we risk losing the real definition. Instead, mark
136 147 * that it's missing.
137 148 */
138 149 if (cmp->cm_unique == B_TRUE) {
139 150 cmt[oid].cmt_missing = B_TRUE;
140 151 return;
141 152 }
142 153
143 154 cmt[oid].cmt_map = iid;
144 155 cmt[oid].cmt_forward = B_TRUE;
145 156 ctf_dprintf("merge diff forward mapped %d->%d\n", oid,
146 157 iid);
147 158 return;
148 159 }
149 160
150 161 /*
151 162 * We could have multiple things that a given type ends up
152 163 * matching in the world of forwards and pointers to forwards.
153 164 * For now just take the first one...
154 165 */
155 166 if (cmt[oid].cmt_map != 0)
156 167 return;
157 168 cmt[oid].cmt_map = iid;
158 169 ctf_dprintf("merge diff mapped %d->%d\n", oid, iid);
159 170 } else if (ifp == cmp->cm_src) {
160 171 VERIFY(cmt[iid].cmt_map == 0);
161 172 cmt[iid].cmt_missing = B_TRUE;
162 173 ctf_dprintf("merge diff said %d is missing\n", iid);
163 174 }
164 175 }
165 176
166 177 static int
167 178 ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id)
168 179 {
169 180 int ret, flags;
170 181 const ctf_type_t *tp;
171 182 const char *name;
172 183 ctf_encoding_t en;
173 184
174 185 if (ctf_type_encoding(cmp->cm_src, id, &en) != 0)
175 186 return (CTF_ERR);
176 187
177 188 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
178 189 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
179 190 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
180 191 flags = CTF_ADD_ROOT;
181 192 else
182 193 flags = CTF_ADD_NONROOT;
183 194
184 195 ret = ctf_add_encoded(cmp->cm_out, flags, name, &en,
185 196 ctf_type_kind(cmp->cm_src, id));
186 197
187 198 if (ret == CTF_ERR)
188 199 return (ret);
189 200
190 201 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
191 202 cmp->cm_tmap[id].cmt_map = ret;
192 203 return (0);
193 204 }
194 205
195 206 static int
196 207 ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id)
197 208 {
198 209 int ret, flags;
199 210 const ctf_type_t *tp;
200 211 ctf_arinfo_t ar;
201 212
202 213 if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR)
203 214 return (CTF_ERR);
204 215
205 216 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
206 217 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
207 218 flags = CTF_ADD_ROOT;
208 219 else
209 220 flags = CTF_ADD_NONROOT;
210 221
211 222 if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) {
212 223 ret = ctf_merge_add_type(cmp, ar.ctr_contents);
213 224 if (ret != 0)
214 225 return (ret);
215 226 ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0);
216 227 }
217 228 ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents);
218 229
219 230 if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) {
220 231 ret = ctf_merge_add_type(cmp, ar.ctr_index);
221 232 if (ret != 0)
222 233 return (ret);
223 234 ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0);
224 235 }
225 236 ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index);
226 237
227 238 ret = ctf_add_array(cmp->cm_out, flags, &ar);
228 239 if (ret == CTF_ERR)
229 240 return (ret);
230 241
231 242 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
232 243 cmp->cm_tmap[id].cmt_map = ret;
233 244
234 245 return (0);
235 246 }
236 247
237 248 static int
238 249 ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id)
239 250 {
240 251 int ret, flags;
241 252 const ctf_type_t *tp;
242 253 ctf_id_t reftype;
243 254 const char *name;
244 255
245 256 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
246 257 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
247 258 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
248 259 flags = CTF_ADD_ROOT;
249 260 else
250 261 flags = CTF_ADD_NONROOT;
251 262
252 263 reftype = ctf_type_reference(cmp->cm_src, id);
253 264 if (reftype == CTF_ERR)
254 265 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
255 266
256 267 if (cmp->cm_tmap[reftype].cmt_map == 0) {
257 268 ret = ctf_merge_add_type(cmp, reftype);
258 269 if (ret != 0)
259 270 return (ret);
260 271 ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
261 272 }
262 273 reftype = ctf_merge_gettype(cmp, reftype);
263 274
264 275 ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype,
265 276 ctf_type_kind(cmp->cm_src, id));
266 277 if (ret == CTF_ERR)
267 278 return (ret);
268 279
269 280 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
270 281 cmp->cm_tmap[id].cmt_map = ret;
271 282 return (0);
272 283 }
273 284
274 285 static int
275 286 ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id)
276 287 {
277 288 int ret, flags;
278 289 const ctf_type_t *tp;
279 290 const char *name;
280 291 ctf_id_t reftype;
281 292
282 293 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
283 294 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
284 295 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
285 296 flags = CTF_ADD_ROOT;
286 297 else
287 298 flags = CTF_ADD_NONROOT;
288 299
289 300 reftype = ctf_type_reference(cmp->cm_src, id);
290 301 if (reftype == CTF_ERR)
291 302 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
292 303
293 304 if (cmp->cm_tmap[reftype].cmt_map == 0) {
294 305 ret = ctf_merge_add_type(cmp, reftype);
295 306 if (ret != 0)
296 307 return (ret);
297 308 ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
298 309 }
299 310 reftype = ctf_merge_gettype(cmp, reftype);
300 311
301 312 ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype);
302 313 if (ret == CTF_ERR)
303 314 return (ret);
304 315
305 316 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
306 317 cmp->cm_tmap[id].cmt_map = ret;
307 318 return (0);
308 319 }
309 320
310 321 typedef struct ctf_merge_enum {
311 322 ctf_file_t *cme_fp;
312 323 ctf_id_t cme_id;
313 324 } ctf_merge_enum_t;
314 325
315 326 static int
316 327 ctf_merge_add_enumerator(const char *name, int value, void *arg)
317 328 {
318 329 ctf_merge_enum_t *cmep = arg;
319 330
320 331 return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) ==
321 332 CTF_ERR);
322 333 }
323 334
324 335 static int
325 336 ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id)
326 337 {
327 338 int flags;
328 339 const ctf_type_t *tp;
329 340 const char *name;
330 341 ctf_id_t enumid;
331 342 ctf_merge_enum_t cme;
332 343
333 344 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
334 345 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
335 346 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
336 347 flags = CTF_ADD_ROOT;
337 348 else
338 349 flags = CTF_ADD_NONROOT;
339 350
340 351 enumid = ctf_add_enum(cmp->cm_out, flags, name);
341 352 if (enumid == CTF_ERR)
342 353 return (enumid);
343 354
344 355 cme.cme_fp = cmp->cm_out;
345 356 cme.cme_id = enumid;
346 357 if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator,
347 358 &cme) != 0)
348 359 return (CTF_ERR);
349 360
350 361 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
351 362 cmp->cm_tmap[id].cmt_map = enumid;
352 363 return (0);
353 364 }
354 365
355 366 static int
356 367 ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id)
357 368 {
358 369 int ret, flags, i;
359 370 const ctf_type_t *tp;
360 371 ctf_funcinfo_t ctc;
361 372 ctf_id_t *argv;
362 373
363 374 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
364 375 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
365 376 flags = CTF_ADD_ROOT;
366 377 else
367 378 flags = CTF_ADD_NONROOT;
368 379
369 380 if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR)
370 381 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
371 382
372 383 argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc);
373 384 if (argv == NULL)
374 385 return (ctf_set_errno(cmp->cm_out, ENOMEM));
375 386 if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) ==
376 387 CTF_ERR) {
377 388 ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
378 389 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
379 390 }
380 391
381 392 if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) {
382 393 ret = ctf_merge_add_type(cmp, ctc.ctc_return);
383 394 if (ret != 0)
384 395 return (ret);
385 396 ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0);
386 397 }
387 398 ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return);
388 399
389 400 for (i = 0; i < ctc.ctc_argc; i++) {
390 401 if (cmp->cm_tmap[argv[i]].cmt_map == 0) {
391 402 ret = ctf_merge_add_type(cmp, argv[i]);
392 403 if (ret != 0)
393 404 return (ret);
394 405 ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0);
395 406 }
396 407 argv[i] = ctf_merge_gettype(cmp, argv[i]);
397 408 }
398 409
399 410 ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv);
400 411 ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
401 412 if (ret == CTF_ERR)
402 413 return (ret);
403 414
404 415 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
405 416 cmp->cm_tmap[id].cmt_map = ret;
406 417 return (0);
407 418 }
408 419
409 420 static int
410 421 ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id)
411 422 {
412 423 int ret, flags;
413 424 const ctf_type_t *tp;
414 425 const char *name;
415 426
416 427 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
417 428 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
418 429 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
419 430 flags = CTF_ADD_ROOT;
420 431 else
421 432 flags = CTF_ADD_NONROOT;
422 433
423 434 /*
424 435 * ctf_add_forward tries to check to see if a given forward already
425 436 * exists in one of its hash tables. If we're here then we know that we
426 437 * have a forward in a container that isn't present in another.
427 438 * Therefore, we choose a token hash table to satisfy the API choice
428 439 * here.
429 440 */
430 441 ret = ctf_add_forward(cmp->cm_out, flags, name, CTF_K_STRUCT);
431 442 if (ret == CTF_ERR)
432 443 return (CTF_ERR);
433 444
434 445 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
435 446 cmp->cm_tmap[id].cmt_map = ret;
436 447 return (0);
437 448 }
438 449
439 450 typedef struct ctf_merge_su {
440 451 ctf_merge_types_t *cms_cm;
441 452 ctf_id_t cms_id;
442 453 } ctf_merge_su_t;
443 454
444 455 static int
445 456 ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg)
446 457 {
447 458 ctf_merge_su_t *cms = arg;
448 459
449 460 VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0);
450 461 type = cms->cms_cm->cm_tmap[type].cmt_map;
451 462
452 463 ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id);
453 464 return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name,
454 465 type, offset) == CTF_ERR);
455 466 }
456 467
457 468 /*
458 469 * During the first pass, we always add the generic structure and union but none
459 470 * of its members as they might not all have been mapped yet. Instead we just
460 471 * mark all structures and unions as needing to be fixed up.
461 472 */
462 473 static int
463 474 ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward)
464 475 {
465 476 int flags, kind;
466 477 const ctf_type_t *tp;
467 478 const char *name;
468 479 ctf_id_t suid;
469 480
470 481 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
471 482 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
472 483 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
473 484 flags = CTF_ADD_ROOT;
474 485 else
475 486 flags = CTF_ADD_NONROOT;
476 487 kind = ctf_type_kind(cmp->cm_src, id);
477 488
478 489 if (kind == CTF_K_STRUCT)
479 490 suid = ctf_add_struct(cmp->cm_out, flags, name);
480 491 else
481 492 suid = ctf_add_union(cmp->cm_out, flags, name);
482 493
483 494 if (suid == CTF_ERR)
484 495 return (suid);
485 496
486 497 /*
487 498 * If this is a forward reference then its mapping should already
488 499 * exist.
489 500 */
490 501 if (forward == B_FALSE) {
491 502 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
492 503 cmp->cm_tmap[id].cmt_map = suid;
493 504 ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id,
494 505 suid);
495 506 } else {
496 507 VERIFY(cmp->cm_tmap[id].cmt_map == suid);
497 508 }
498 509 cmp->cm_tmap[id].cmt_fixup = B_TRUE;
499 510
500 511 return (0);
501 512 }
502 513
503 514 static int
504 515 ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id)
505 516 {
506 517 int kind, ret;
507 518
508 519 /*
509 520 * We may end up evaluating a type more than once as we may deal with it
510 521 * as we recursively evaluate some kind of reference and then we may see
511 522 * it normally.
512 523 */
513 524 if (cmp->cm_tmap[id].cmt_map != 0)
514 525 return (0);
515 526
516 527 kind = ctf_type_kind(cmp->cm_src, id);
517 528 switch (kind) {
518 529 case CTF_K_INTEGER:
519 530 case CTF_K_FLOAT:
520 531 ret = ctf_merge_add_number(cmp, id);
521 532 break;
522 533 case CTF_K_ARRAY:
523 534 ret = ctf_merge_add_array(cmp, id);
524 535 break;
525 536 case CTF_K_POINTER:
526 537 case CTF_K_VOLATILE:
527 538 case CTF_K_CONST:
528 539 case CTF_K_RESTRICT:
529 540 ret = ctf_merge_add_reftype(cmp, id);
530 541 break;
531 542 case CTF_K_TYPEDEF:
532 543 ret = ctf_merge_add_typedef(cmp, id);
533 544 break;
534 545 case CTF_K_ENUM:
535 546 ret = ctf_merge_add_enum(cmp, id);
536 547 break;
537 548 case CTF_K_FUNCTION:
538 549 ret = ctf_merge_add_func(cmp, id);
539 550 break;
540 551 case CTF_K_FORWARD:
541 552 ret = ctf_merge_add_forward(cmp, id);
542 553 break;
543 554 case CTF_K_STRUCT:
544 555 case CTF_K_UNION:
545 556 ret = ctf_merge_add_sou(cmp, id, B_FALSE);
546 557 break;
547 558 case CTF_K_UNKNOWN:
548 559 /*
549 560 * We don't add unknown types, and we later assert that nothing
550 561 * should reference them.
551 562 */
552 563 return (0);
553 564 default:
554 565 abort();
555 566 }
556 567
557 568 return (ret);
558 569 }
559 570
560 571 static int
561 572 ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id)
562 573 {
563 574 ctf_dtdef_t *dtd;
564 575 ctf_merge_su_t cms;
565 576 ctf_id_t mapid;
566 577 ssize_t size;
567 578
568 579 mapid = cmp->cm_tmap[id].cmt_map;
569 580 VERIFY(mapid != 0);
570 581 dtd = ctf_dtd_lookup(cmp->cm_out, mapid);
571 582 VERIFY(dtd != NULL);
572 583
573 584 ctf_dprintf("Trying to fix up sou %d\n", id);
574 585 cms.cms_cm = cmp;
575 586 cms.cms_id = mapid;
576 587 if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0)
577 588 return (CTF_ERR);
578 589
579 590 if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR)
580 591 return (CTF_ERR);
581 592 if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR)
582 593 return (CTF_ERR);
583 594
584 595 return (0);
585 596 }
586 597
587 598 static int
588 599 ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
589 600 {
590 601 int kind, ret;
591 602
592 603 kind = ctf_type_kind(cmp->cm_src, id);
593 604 switch (kind) {
594 605 case CTF_K_STRUCT:
595 606 case CTF_K_UNION:
596 607 ret = ctf_merge_fixup_sou(cmp, id);
597 608 break;
598 609 default:
599 610 VERIFY(0);
600 611 ret = CTF_ERR;
601 612 }
602 613
603 614 return (ret);
604 615 }
605 616
606 617 /*
607 618 * Now that we've successfully merged everything, we're going to clean
608 619 * up the merge type table. Traditionally if we had just two different
609 620 * files that we were working between, the types would be fully
610 621 * resolved. However, because we were comparing with ourself every step
611 622 * of the way and not our reduced self, we need to go through and update
612 623 * every mapped entry to what it now points to in the deduped file.
613 624 */
614 625 static void
615 626 ctf_merge_fixup_dedup_map(ctf_merge_types_t *cmp)
616 627 {
617 628 int i;
618 629
619 630 for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
620 631 ctf_id_t tid;
621 632
622 633 /*
623 634 * Missing types always have their id updated to exactly what it
624 635 * should be.
625 636 */
626 637 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
627 638 VERIFY(cmp->cm_tmap[i].cmt_map != 0);
628 639 continue;
629 640 }
630 641
631 642 tid = i;
632 643 while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
633 644 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
634 645 tid = cmp->cm_tmap[tid].cmt_map;
635 646 }
636 647 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
637 648 cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
638 649 }
639 650 }
640 651
641 652
642 653 /*
643 654 * We're going to do three passes over the containers.
644 655 *
645 656 * Pass 1 checks for forward references in the output container that we know
646 657 * exist in the source container.
647 658 *
648 659 * Pass 2 adds all the missing types from the source container. As part of this
649 660 * we may be adding a type as a forward reference that doesn't exist yet.
650 661 * Any types that we encounter in this form, we need to add to a third pass.
651 662 *
652 663 * Pass 3 is the fixup pass. Here we go through and find all the types that were
653 664 * missing in the first.
↓ open down ↓ |
547 lines elided |
↑ open up ↑ |
654 665 *
655 666 * Importantly, we *must* call ctf_update between the second and third pass,
656 667 * otherwise several of the libctf functions will not properly find the data in
657 668 * the container. If we're doing a dedup we also fix up the type mapping.
658 669 */
659 670 static int
660 671 ctf_merge_common(ctf_merge_types_t *cmp)
661 672 {
662 673 int ret, i;
663 674
664 - ctf_phase_dump(cmp->cm_src, "merge-common-src");
665 - ctf_phase_dump(cmp->cm_out, "merge-common-dest");
675 + ctf_phase_dump(cmp->cm_src, "merge-common-src", NULL);
676 + ctf_phase_dump(cmp->cm_out, "merge-common-dest", NULL);
666 677
667 678 /* Pass 1 */
668 679 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
669 680 if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
670 681 ret = ctf_merge_add_sou(cmp, i, B_TRUE);
671 682 if (ret != 0) {
672 683 return (ret);
673 684 }
674 685 }
675 686 }
676 687
677 688 /* Pass 2 */
678 689 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
679 690 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
680 691 ret = ctf_merge_add_type(cmp, i);
681 692 if (ret != 0) {
682 693 ctf_dprintf("Failed to merge type %d\n", i);
683 694 return (ret);
684 695 }
685 696 }
686 697 }
687 698
688 699 ret = ctf_update(cmp->cm_out);
689 700 if (ret != 0)
690 701 return (ret);
691 702
692 703 if (cmp->cm_dedup == B_TRUE) {
693 704 ctf_merge_fixup_dedup_map(cmp);
694 705 }
695 706
696 707 ctf_dprintf("Beginning merge pass 3\n");
697 708 /* Pass 3 */
698 709 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
699 710 if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
700 711 ret = ctf_merge_fixup_type(cmp, i);
701 712 if (ret != 0)
702 713 return (ret);
703 714 }
704 715 }
705 716
706 717 if (cmp->cm_dedup == B_TRUE) {
707 718 ctf_merge_fixup_dedup_map(cmp);
708 719 }
709 720
710 721 return (0);
711 722 }
712 723
713 724 /*
714 725 * Uniquification is slightly different from a stock merge. For starters, we
715 726 * don't need to replace any forward references in the output. In this case
716 727 * though, the types that already exist are in a parent container to the empty
717 728 * output container.
718 729 */
719 730 static int
720 731 ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
721 732 {
722 733 int i, ret;
723 734
724 735 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
725 736 if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
726 737 continue;
727 738 ret = ctf_merge_add_type(cmp, i);
728 739 if (ret != 0)
729 740 return (ret);
730 741 }
731 742
732 743 ret = ctf_update(cmp->cm_out);
733 744 if (ret != 0)
734 745 return (ret);
735 746
736 747 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
737 748 if (cmp->cm_tmap[i].cmt_fixup == B_FALSE)
738 749 continue;
739 750 ret = ctf_merge_fixup_type(cmp, i);
740 751 if (ret != 0)
741 752 return (ret);
742 753 }
743 754
744 755 return (0);
745 756 }
746 757
747 758 static int
748 759 ctf_merge_types_init(ctf_merge_types_t *cmp)
749 760 {
750 761 cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
751 762 (cmp->cm_src->ctf_typemax + 1));
752 763 if (cmp->cm_tmap == NULL)
753 764 return (ctf_set_errno(cmp->cm_out, ENOMEM));
754 765 bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
755 766 (cmp->cm_src->ctf_typemax + 1));
756 767 return (0);
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
757 768 }
758 769
759 770 static void
760 771 ctf_merge_types_fini(ctf_merge_types_t *cmp)
761 772 {
762 773 ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
763 774 (cmp->cm_src->ctf_typemax + 1));
764 775 }
765 776
766 777 /*
778 + * After performing a pass, we need to go through the object and function type
779 + * maps and potentially fix them up based on the new maps that we have.
780 + */
781 +static void
782 +ctf_merge_fixup_symmaps(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
783 +{
784 + ctf_merge_objmap_t *cmo;
785 + ctf_merge_funcmap_t *cmf;
786 +
787 + for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
788 + cmo = list_next(&cmi->cmi_omap, cmo)) {
789 + VERIFY3S(cmo->cmo_tid, !=, 0);
790 + VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
791 + cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
792 + }
793 +
794 + for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
795 + cmf = list_next(&cmi->cmi_fmap, cmf)) {
796 + int i;
797 +
798 + VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
799 + cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
800 + for (i = 0; i < cmf->cmf_argc; i++) {
801 + VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
802 + cmf->cmf_args[i] =
803 + cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
804 + }
805 + }
806 +}
807 +
808 +/*
767 809 * Merge the types contained inside of two input files. The second input file is
768 810 * always going to be the destination. We're guaranteed that it's always
769 811 * writeable.
770 812 */
771 813 static int
772 814 ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
773 815 {
774 816 int ret;
775 817 ctf_merge_types_t cm;
776 818 ctf_diff_t *cdp;
777 - ctf_merge_objmap_t *cmo;
778 - ctf_merge_funcmap_t *cmf;
779 819 ctf_merge_input_t *scmi = arg;
780 820 ctf_merge_input_t *dcmi = arg2;
781 821 ctf_file_t *out = dcmi->cmi_input;
782 822 ctf_file_t *source = scmi->cmi_input;
783 823
784 824 ctf_dprintf("merging %p->%p\n", source, out);
785 825
786 826 if (!(out->ctf_flags & LCTF_RDWR))
787 827 return (ctf_set_errno(out, ECTF_RDONLY));
788 828
789 829 if (ctf_getmodel(out) != ctf_getmodel(source))
790 830 return (ctf_set_errno(out, ECTF_DMODEL));
791 831
792 832 if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
793 833 return (ret);
794 834
795 835 cm.cm_out = out;
796 836 cm.cm_src = source;
797 837 cm.cm_dedup = B_FALSE;
798 838 cm.cm_unique = B_FALSE;
799 839 ret = ctf_merge_types_init(&cm);
800 840 if (ret != 0) {
801 841 ctf_diff_fini(cdp);
802 842 return (ctf_set_errno(out, ret));
803 843 }
804 844
805 845 ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
806 846 if (ret != 0)
807 847 goto cleanup;
808 848 ret = ctf_merge_common(&cm);
809 849 ctf_dprintf("merge common returned with %d\n", ret);
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
810 850 if (ret == 0) {
811 851 ret = ctf_update(out);
812 852 ctf_dprintf("update returned with %d\n", ret);
813 853 } else {
814 854 goto cleanup;
815 855 }
816 856
817 857 /*
818 858 * Now we need to fix up the object and function maps.
819 859 */
820 - for (cmo = list_head(&scmi->cmi_omap); cmo != NULL;
821 - cmo = list_next(&scmi->cmi_omap, cmo)) {
822 - if (cmo->cmo_tid == 0)
823 - continue;
824 - VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0);
825 - cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map;
826 - }
860 + ctf_merge_fixup_symmaps(&cm, scmi);
827 861
828 - for (cmf = list_head(&scmi->cmi_fmap); cmf != NULL;
829 - cmf = list_next(&scmi->cmi_fmap, cmf)) {
830 - int i;
831 -
832 - VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0);
833 - cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map;
834 - for (i = 0; i < cmf->cmf_argc; i++) {
835 - VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
836 - cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map;
837 - }
838 - }
839 -
840 862 /*
841 863 * Now that we've fixed things up, we need to give our function and
842 864 * object maps to the destination, such that it can continue to update
843 865 * them going forward.
844 866 */
845 867 list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
846 868 list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
847 869
848 870 cleanup:
849 871 if (ret == 0)
850 872 *outp = dcmi;
851 873 ctf_merge_types_fini(&cm);
852 874 ctf_diff_fini(cdp);
853 875 if (ret != 0)
854 876 return (ctf_errno(out));
877 + ctf_phase_bump();
855 878 return (0);
856 879 }
857 880
858 -/*
859 - * After performing a pass, we need to go through the object and function type
860 - * maps and potentially fix them up based on the new maps that we haev.
861 - */
862 -static void
863 -ctf_merge_fixup_nontypes(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
864 -{
865 - ctf_merge_objmap_t *cmo;
866 - ctf_merge_funcmap_t *cmf;
867 -
868 - for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
869 - cmo = list_next(&cmi->cmi_omap, cmo)) {
870 - if (cmo->cmo_tid == 0)
871 - continue;
872 - VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
873 - cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
874 - }
875 -
876 - for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
877 - cmf = list_next(&cmi->cmi_fmap, cmf)) {
878 - int i;
879 -
880 - VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
881 - cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
882 - for (i = 0; i < cmf->cmf_argc; i++) {
883 - VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map !=
884 - 0);
885 - cmf->cmf_args[i] =
886 - cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
887 - }
888 - }
889 -}
890 -
891 881 static int
892 882 ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
893 883 {
894 884 int err, ret;
895 885 ctf_file_t *out;
896 886 ctf_merge_types_t cm;
897 887 ctf_diff_t *cdp;
898 888 ctf_merge_input_t *cmi;
899 889 ctf_file_t *parent = cmh->cmh_unique;
900 890
901 891 *outp = NULL;
902 892 out = ctf_fdcreate(cmh->cmh_ofd, &err);
903 893 if (out == NULL)
904 894 return (ctf_set_errno(src, err));
905 895
906 896 out->ctf_parname = cmh->cmh_pname;
907 897 if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
908 898 (void) ctf_set_errno(src, ctf_errno(out));
909 899 ctf_close(out);
910 900 return (CTF_ERR);
911 901 }
912 902
913 903 if (ctf_import(out, parent) != 0) {
914 904 (void) ctf_set_errno(src, ctf_errno(out));
915 905 ctf_close(out);
916 906 return (CTF_ERR);
917 907 }
918 908
919 909 if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) {
920 910 ctf_close(out);
921 911 return (ctf_set_errno(src, ctf_errno(parent)));
922 912 }
923 913
924 914 cm.cm_out = parent;
925 915 cm.cm_src = src;
926 916 cm.cm_dedup = B_FALSE;
927 917 cm.cm_unique = B_TRUE;
928 918 ret = ctf_merge_types_init(&cm);
929 919 if (ret != 0) {
930 920 ctf_close(out);
931 921 ctf_diff_fini(cdp);
932 922 return (ctf_set_errno(src, ret));
933 923 }
934 924
935 925 ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
936 926 if (ret == 0) {
937 927 cm.cm_out = out;
938 928 ret = ctf_merge_uniquify_types(&cm);
939 929 if (ret == 0)
940 930 ret = ctf_update(out);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
941 931 }
942 932
943 933 if (ret != 0) {
944 934 ctf_merge_types_fini(&cm);
945 935 ctf_diff_fini(cdp);
946 936 return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
947 937 }
948 938
949 939 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
950 940 cmi = list_next(&cmh->cmh_inputs, cmi)) {
951 - ctf_merge_fixup_nontypes(&cm, cmi);
941 + ctf_merge_fixup_symmaps(&cm, cmi);
952 942 }
953 943
954 944 ctf_merge_types_fini(&cm);
955 945 ctf_diff_fini(cdp);
956 946 *outp = out;
957 947 return (0);
958 948 }
959 949
960 950 static void
961 951 ctf_merge_fini_input(ctf_merge_input_t *cmi)
962 952 {
963 953 ctf_merge_objmap_t *cmo;
964 954 ctf_merge_funcmap_t *cmf;
965 955
966 956 while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
967 957 ctf_free(cmo, sizeof (ctf_merge_objmap_t));
968 958
969 959 while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
970 960 ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
971 961 sizeof (ctf_id_t) * cmf->cmf_argc);
972 962
973 963 if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL)
974 964 ctf_close(cmi->cmi_input);
975 965
976 966 ctf_free(cmi, sizeof (ctf_merge_input_t));
977 967 }
978 968
979 969 void
980 970 ctf_merge_fini(ctf_merge_t *cmh)
981 971 {
982 972 size_t len;
983 973 ctf_merge_input_t *cmi;
984 974
985 975 if (cmh->cmh_label != NULL) {
986 976 len = strlen(cmh->cmh_label) + 1;
987 977 ctf_free(cmh->cmh_label, len);
988 978 }
989 979
990 980 if (cmh->cmh_pname != NULL) {
991 981 len = strlen(cmh->cmh_pname) + 1;
992 982 ctf_free(cmh->cmh_pname, len);
993 983 }
994 984
995 985 while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL)
996 986 ctf_merge_fini_input(cmi);
997 987
998 988 ctf_free(cmh, sizeof (ctf_merge_t));
999 989 }
1000 990
1001 991 ctf_merge_t *
1002 992 ctf_merge_init(int fd, int *errp)
1003 993 {
1004 994 int err;
1005 995 ctf_merge_t *out;
1006 996 struct stat st;
1007 997
1008 998 if (errp == NULL)
1009 999 errp = &err;
1010 1000
1011 1001 if (fd != -1 && fstat(fd, &st) != 0) {
1012 1002 *errp = EINVAL;
1013 1003 return (NULL);
1014 1004 }
1015 1005
1016 1006 out = ctf_alloc(sizeof (ctf_merge_t));
1017 1007 if (out == NULL) {
1018 1008 *errp = ENOMEM;
1019 1009 return (NULL);
1020 1010 }
1021 1011
1022 1012 if (fd == -1) {
1023 1013 out->cmh_msyms = B_FALSE;
1024 1014 } else {
1025 1015 out->cmh_msyms = B_TRUE;
1026 1016 }
1027 1017
1028 1018 list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t),
1029 1019 offsetof(ctf_merge_input_t, cmi_node));
1030 1020 out->cmh_ninputs = 0;
1031 1021 out->cmh_nthreads = 1;
1032 1022 out->cmh_unique = NULL;
1033 1023 out->cmh_ofd = fd;
1034 1024 out->cmh_flags = 0;
1035 1025 out->cmh_label = NULL;
1036 1026 out->cmh_pname = NULL;
1037 1027
1038 1028 return (out);
1039 1029 }
1040 1030
1041 1031 int
1042 1032 ctf_merge_label(ctf_merge_t *cmh, const char *label)
1043 1033 {
1044 1034 char *dup;
1045 1035
1046 1036 if (label == NULL)
1047 1037 return (EINVAL);
1048 1038
1049 1039 dup = ctf_strdup(label);
1050 1040 if (dup == NULL)
1051 1041 return (EAGAIN);
1052 1042
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
1053 1043 if (cmh->cmh_label != NULL) {
1054 1044 size_t len = strlen(cmh->cmh_label) + 1;
1055 1045 ctf_free(cmh->cmh_label, len);
1056 1046 }
1057 1047
1058 1048 cmh->cmh_label = dup;
1059 1049 return (0);
1060 1050 }
1061 1051
1062 1052 static int
1063 -ctf_merge_add_funcs_cb(const char *name, ulong_t idx, ctf_funcinfo_t *fip,
1064 - void *arg)
1053 +ctf_merge_add_function(ctf_merge_input_t *cmi, ctf_funcinfo_t *fip, ulong_t idx,
1054 + const char *file, const char *name, const Elf64_Sym *symp)
1065 1055 {
1066 - ctf_merge_input_t *cmi = arg;
1067 1056 ctf_merge_funcmap_t *fmap;
1068 1057
1069 1058 fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1070 1059 sizeof (ctf_id_t) * fip->ctc_argc);
1071 1060 if (fmap == NULL)
1072 1061 return (ENOMEM);
1073 1062
1074 1063 fmap->cmf_idx = idx;
1064 + fmap->cmf_sym = *symp;
1075 1065 fmap->cmf_rtid = fip->ctc_return;
1076 1066 fmap->cmf_flags = fip->ctc_flags;
1077 1067 fmap->cmf_argc = fip->ctc_argc;
1078 1068 fmap->cmf_name = name;
1069 + if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1070 + fmap->cmf_file = file;
1071 + } else {
1072 + fmap->cmf_file = NULL;
1073 + }
1079 1074
1080 1075 if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1081 1076 fmap->cmf_args) != 0) {
1082 1077 ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1083 1078 sizeof (ctf_id_t) * fip->ctc_argc);
1084 1079 return (ctf_errno(cmi->cmi_input));
1085 1080 }
1086 1081
1082 + ctf_dprintf("added initial function %s, %lu, %s %u\n", name, idx,
1083 + fmap->cmf_file != NULL ? fmap->cmf_file : "global",
1084 + ELF64_ST_BIND(symp->st_info));
1087 1085 list_insert_tail(&cmi->cmi_fmap, fmap);
1088 1086 return (0);
1089 1087 }
1090 1088
1091 1089 static int
1092 -ctf_merge_add_objs_cb(const char *name, ctf_id_t id, ulong_t idx, void *arg)
1090 +ctf_merge_add_object(ctf_merge_input_t *cmi, ctf_id_t id, ulong_t idx,
1091 + const char *file, const char *name, const Elf64_Sym *symp)
1093 1092 {
1094 - ctf_merge_input_t *cmi = arg;
1095 1093 ctf_merge_objmap_t *cmo;
1096 1094
1097 1095 cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1098 1096 if (cmo == NULL)
1099 1097 return (ENOMEM);
1100 1098
1101 1099 cmo->cmo_name = name;
1100 + if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1101 + cmo->cmo_file = file;
1102 + } else {
1103 + cmo->cmo_file = NULL;
1104 + }
1102 1105 cmo->cmo_idx = idx;
1103 1106 cmo->cmo_tid = id;
1107 + cmo->cmo_sym = *symp;
1104 1108 list_insert_tail(&cmi->cmi_omap, cmo);
1109 +
1110 + ctf_dprintf("added initial object %s, %lu, %ld, %s\n", name, idx, id,
1111 + cmo->cmo_file != NULL ? cmo->cmo_file : "global");
1112 +
1105 1113 return (0);
1106 1114 }
1107 1115
1116 +static int
1117 +ctf_merge_add_symbol(const Elf64_Sym *symp, ulong_t idx, const char *file,
1118 + const char *name, boolean_t primary, void *arg)
1119 +{
1120 + ctf_merge_input_t *cmi = arg;
1121 + ctf_file_t *fp = cmi->cmi_input;
1122 + ushort_t *data, funcbase;
1123 + uint_t type;
1124 + ctf_funcinfo_t fi;
1125 +
1126 + /*
1127 + * See if there is type information for this. If there is no
1128 + * type information for this entry or no translation, then we
1129 + * will find the value zero. This indicates no type ID for
1130 + * objects and encodes unknown information for functions.
1131 + */
1132 + if (fp->ctf_sxlate[idx] == -1u)
1133 + return (0);
1134 + data = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[idx]);
1135 + if (*data == 0)
1136 + return (0);
1137 +
1138 + type = ELF64_ST_TYPE(symp->st_info);
1139 +
1140 + switch (type) {
1141 + case STT_FUNC:
1142 + funcbase = *data;
1143 + if (LCTF_INFO_KIND(fp, funcbase) != CTF_K_FUNCTION)
1144 + return (0);
1145 + data++;
1146 + fi.ctc_return = *data;
1147 + data++;
1148 + fi.ctc_argc = LCTF_INFO_VLEN(fp, funcbase);
1149 + fi.ctc_flags = 0;
1150 +
1151 + if (fi.ctc_argc != 0 && data[fi.ctc_argc - 1] == 0) {
1152 + fi.ctc_flags |= CTF_FUNC_VARARG;
1153 + fi.ctc_argc--;
1154 + }
1155 + return (ctf_merge_add_function(cmi, &fi, idx, file, name,
1156 + symp));
1157 + case STT_OBJECT:
1158 + return (ctf_merge_add_object(cmi, *data, idx, file, name,
1159 + symp));
1160 + default:
1161 + return (0);
1162 + }
1163 +}
1164 +
1108 1165 /*
1109 1166 * Whenever we create an entry to merge, we then go and add a second empty
1110 1167 * ctf_file_t which we use for the purposes of our merging. It's not the best,
1111 1168 * but it's the best that we've got at the moment.
1112 1169 */
1113 1170 int
1114 1171 ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1115 1172 {
1116 1173 int ret;
1117 1174 ctf_merge_input_t *cmi;
1118 1175 ctf_file_t *empty;
1119 1176
1177 + ctf_dprintf("adding input %p\n", input);
1178 +
1120 1179 if (input->ctf_flags & LCTF_CHILD)
1121 1180 return (ECTF_MCHILD);
1122 1181
1123 1182 cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1124 1183 if (cmi == NULL)
1125 1184 return (ENOMEM);
1126 1185
1127 1186 cmi->cmi_created = B_FALSE;
1128 1187 cmi->cmi_input = input;
1129 1188 list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1130 1189 offsetof(ctf_merge_funcmap_t, cmf_node));
1131 1190 list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1132 1191 offsetof(ctf_merge_objmap_t, cmo_node));
1133 1192
1134 1193 if (cmh->cmh_msyms == B_TRUE) {
1135 - if ((ret = ctf_function_iter(input, ctf_merge_add_funcs_cb,
1194 + if ((ret = ctf_symtab_iter(input, ctf_merge_add_symbol,
1136 1195 cmi)) != 0) {
1137 1196 ctf_merge_fini_input(cmi);
1138 1197 return (ret);
1139 1198 }
1140 -
1141 - if ((ret = ctf_object_iter(input, ctf_merge_add_objs_cb,
1142 - cmi)) != 0) {
1143 - ctf_merge_fini_input(cmi);
1144 - return (ret);
1145 - }
1146 1199 }
1147 1200
1148 1201 list_insert_tail(&cmh->cmh_inputs, cmi);
1149 1202 cmh->cmh_ninputs++;
1150 1203
1151 1204 /* And now the empty one to merge into this */
1152 1205 cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1153 1206 if (cmi == NULL)
1154 1207 return (ENOMEM);
1155 1208 list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1156 1209 offsetof(ctf_merge_funcmap_t, cmf_node));
1157 1210 list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1158 1211 offsetof(ctf_merge_objmap_t, cmo_node));
1159 1212
1160 1213 empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1161 1214 if (empty == NULL)
1162 1215 return (ret);
1163 1216 cmi->cmi_input = empty;
1164 1217 cmi->cmi_created = B_TRUE;
1165 1218
1166 1219 if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {
1167 1220 return (ctf_errno(empty));
1168 1221 }
1169 1222
1170 1223 list_insert_tail(&cmh->cmh_inputs, cmi);
1171 1224 cmh->cmh_ninputs++;
1172 1225 ctf_dprintf("added containers %p and %p\n", input, empty);
1173 1226 return (0);
1174 1227 }
1175 1228
1176 1229 int
1177 1230 ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1178 1231 {
1179 1232 char *dup;
1180 1233
1181 1234 if (u->ctf_flags & LCTF_CHILD)
1182 1235 return (ECTF_MCHILD);
1183 1236 if (pname == NULL)
1184 1237 return (EINVAL);
1185 1238 dup = ctf_strdup(pname);
1186 1239 if (dup == NULL)
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
1187 1240 return (EINVAL);
1188 1241 if (cmh->cmh_pname != NULL) {
1189 1242 size_t len = strlen(cmh->cmh_pname) + 1;
1190 1243 ctf_free(cmh->cmh_pname, len);
1191 1244 }
1192 1245 cmh->cmh_pname = dup;
1193 1246 cmh->cmh_unique = u;
1194 1247 return (0);
1195 1248 }
1196 1249
1197 -static int
1198 -ctf_merge_symbols(ctf_merge_t *cmh, ctf_file_t *fp)
1250 +/*
1251 + * Symbol matching rules: the purpose of this is to verify that the type
1252 + * information that we have for a given symbol actually matches the output
1253 + * symbol. This is unfortunately complicated by several different factors:
1254 + *
1255 + * 1. When merging multiple .o's into a single item, the symbol table index will
1256 + * not match.
1257 + *
1258 + * 2. Visibility of a symbol may not be identical to the object file or the
1259 + * DWARF information due to symbol reduction via a mapfile.
1260 + *
1261 + * As such, we have to employ the following rules:
1262 + *
1263 + * 1. A global symbol table entry always matches a global CTF symbol with the
1264 + * same name.
1265 + *
1266 + * 2. A local symbol table entry always matches a local CTF symbol if they have
1267 + * the same name and they belong to the same file.
1268 + *
1269 + * 3. A weak symbol matches a non-weak symbol. This happens if we find that the
1270 + * types match, the values match, the sizes match, and the section indexes
1271 + * match. This happens when we do a conversion in one pass, it almost never
1272 + * happens when we're merging multiple object files. If we match a CTF global
1273 + * symbol, that's a fixed match, otherwise it's a fuzzy match.
1274 + *
1275 + * 4. A local symbol table entry matches a global CTF entry if the
1276 + * other pieces fail, but they have the same name. This is considered a fuzzy
1277 + * match and is not used unless we have no other options.
1278 + *
1279 + * 5. A weak symbol table entry matches a weak CTF entry if the other pieces
1280 + * fail, but they have the same name. This is considered a fuzzy match and is
1281 + * not used unless we have no other options. When merging independent .o files,
1282 + * this is often the only recourse we have to matching weak symbols.
1283 + *
1284 + * In the end, this would all be much simpler if we were able to do this as part
1285 + * of libld which would be able to do all the symbol transformations.
1286 + */
1287 +static boolean_t
1288 +ctf_merge_symbol_match(const char *ctf_file, const char *ctf_name,
1289 + const Elf64_Sym *ctf_symp, const char *symtab_file, const char *symtab_name,
1290 + const Elf64_Sym *symtab_symp, boolean_t *is_fuzzy)
1199 1291 {
1200 - int err;
1201 - ulong_t i;
1292 + *is_fuzzy = B_FALSE;
1293 + uint_t symtab_bind, ctf_bind;
1202 1294
1203 - uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1204 - uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1295 + symtab_bind = ELF64_ST_BIND(symtab_symp->st_info);
1296 + ctf_bind = ELF64_ST_BIND(ctf_symp->st_info);
1205 1297
1206 - for (i = 0; i < fp->ctf_nsyms; i++) {
1207 - const char *name;
1208 - ctf_merge_input_t *cmi;
1209 - ctf_merge_objmap_t *cmo;
1298 + ctf_dprintf("comparing merge match for %s/%s/%u->%s/%s/%u\n",
1299 + symtab_file, symtab_name, symtab_bind,
1300 + ctf_file, ctf_name, ctf_bind);
1301 + if (strcmp(ctf_name, symtab_name) != 0) {
1302 + return (B_FALSE);
1303 + }
1210 1304
1211 - if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1212 - const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1213 - int type = ELF32_ST_TYPE(symp->st_info);
1214 - if (type != STT_OBJECT)
1215 - continue;
1216 - if (ctf_sym_valid(strbase, type, symp->st_shndx,
1217 - symp->st_value, symp->st_name) == B_FALSE)
1218 - continue;
1219 - name = (char *)(strbase + symp->st_name);
1220 - } else {
1221 - const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1222 - int type = ELF64_ST_TYPE(symp->st_info);
1223 - if (type != STT_OBJECT)
1224 - continue;
1225 - if (ctf_sym_valid(strbase, type, symp->st_shndx,
1226 - symp->st_value, symp->st_name) == B_FALSE)
1227 - continue;
1228 - name = (char *)(strbase + symp->st_name);
1305 + if (symtab_bind == STB_GLOBAL && ctf_bind == STB_GLOBAL) {
1306 + return (B_TRUE);
1307 + } else if (symtab_bind == STB_GLOBAL) {
1308 + return (B_FALSE);
1309 + }
1310 +
1311 + if (ctf_bind == STB_LOCAL && ctf_bind == symtab_bind &&
1312 + ctf_file != NULL && symtab_file != NULL &&
1313 + strcmp(ctf_file, symtab_file) == 0) {
1314 + return (B_TRUE);
1315 + }
1316 +
1317 + if (symtab_bind == STB_WEAK && ctf_bind != STB_WEAK &&
1318 + ELF64_ST_TYPE(symtab_symp->st_info) ==
1319 + ELF64_ST_TYPE(ctf_symp->st_info) &&
1320 + symtab_symp->st_value == ctf_symp->st_value &&
1321 + symtab_symp->st_size == ctf_symp->st_size &&
1322 + symtab_symp->st_shndx == ctf_symp->st_shndx) {
1323 + if (ctf_bind == STB_GLOBAL) {
1324 + return (B_TRUE);
1229 1325 }
1230 1326
1231 - cmo = NULL;
1232 - for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1233 - cmi = list_next(&cmh->cmh_inputs, cmi)) {
1234 - for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
1235 - cmo = list_next(&cmi->cmi_omap, cmo)) {
1236 - if (strcmp(cmo->cmo_name, name) == 0)
1237 - goto found;
1238 - }
1327 + if (ctf_bind == STB_LOCAL && ctf_file != NULL &&
1328 + symtab_file != NULL && strcmp(ctf_file, symtab_file) == 0) {
1329 + *is_fuzzy = B_TRUE;
1330 + return (B_TRUE);
1239 1331 }
1240 -found:
1241 - if (cmo != NULL) {
1242 - if (cmo->cmo_tid == 0)
1243 - continue;
1244 - if ((err = ctf_add_object(fp, i, cmo->cmo_tid)) != 0) {
1245 - ctf_dprintf("Failed to add symbol %s->%d: %s\n",
1246 - name, cmo->cmo_tid,
1247 - ctf_errmsg(ctf_errno(fp)));
1248 - return (err);
1249 - }
1250 - }
1251 1332 }
1252 1333
1253 - return (0);
1334 + if (ctf_bind == STB_GLOBAL ||
1335 + (ctf_bind == STB_WEAK && symtab_bind == STB_WEAK)) {
1336 + *is_fuzzy = B_TRUE;
1337 + return (B_TRUE);
1338 + }
1339 +
1340 + return (B_FALSE);
1254 1341 }
1255 1342
1343 +/*
1344 + * For each symbol, try and find a match. We will attempt to find an exact
1345 + * match; however, we will settle for a fuzzy match in general. There is one
1346 + * case where we will not opt to use a fuzzy match, which is when performing the
1347 + * deduplication of a container. In such a case we are trying to reduce common
1348 + * types and a fuzzy match would be inappropriate as if we're in the context of
1349 + * a single container, the conversion process should have identified any exact
1350 + * or fuzzy matches that were required.
1351 + */
1256 1352 static int
1257 -ctf_merge_functions(ctf_merge_t *cmh, ctf_file_t *fp)
1353 +ctf_merge_symbols(const Elf64_Sym *symp, ulong_t idx, const char *file,
1354 + const char *name, boolean_t primary, void *arg)
1258 1355 {
1259 1356 int err;
1260 - ulong_t i;
1261 - ctf_funcinfo_t fi;
1357 + uint_t type, bind;
1358 + ctf_merge_symbol_arg_t *csa = arg;
1359 + ctf_file_t *fp = csa->cmsa_out;
1262 1360
1263 - uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1264 - uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1361 + type = ELF64_ST_TYPE(symp->st_info);
1362 + bind = ELF64_ST_BIND(symp->st_info);
1265 1363
1266 - for (i = 0; i < fp->ctf_nsyms; i++) {
1267 - const char *name;
1268 - ctf_merge_input_t *cmi;
1269 - ctf_merge_funcmap_t *cmf;
1364 + ctf_dprintf("Trying to find match for %s/%s/%u\n", file, name,
1365 + ELF64_ST_BIND(symp->st_info));
1270 1366
1271 - if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1272 - const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1273 - int type = ELF32_ST_TYPE(symp->st_info);
1274 - if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
1275 - continue;
1276 - if (ctf_sym_valid(strbase, type, symp->st_shndx,
1277 - symp->st_value, symp->st_name) == B_FALSE)
1278 - continue;
1279 - name = (char *)(strbase + symp->st_name);
1280 - } else {
1281 - const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1282 - int type = ELF64_ST_TYPE(symp->st_info);
1283 - if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
1284 - continue;
1285 - if (ctf_sym_valid(strbase, type, symp->st_shndx,
1286 - symp->st_value, symp->st_name) == B_FALSE)
1287 - continue;
1288 - name = (char *)(strbase + symp->st_name);
1367 + if (type == STT_OBJECT) {
1368 + ctf_merge_objmap_t *cmo, *match = NULL;
1369 +
1370 + for (cmo = list_head(csa->cmsa_objmap); cmo != NULL;
1371 + cmo = list_next(csa->cmsa_objmap, cmo)) {
1372 + boolean_t is_fuzzy = B_FALSE;
1373 + if (ctf_merge_symbol_match(cmo->cmo_file, cmo->cmo_name,
1374 + &cmo->cmo_sym, file, name, symp, &is_fuzzy)) {
1375 + if (is_fuzzy && csa->cmsa_dedup &&
1376 + bind != STB_WEAK) {
1377 + continue;
1378 + }
1379 + match = cmo;
1380 + if (is_fuzzy) {
1381 + continue;
1382 + }
1383 + break;
1384 + }
1289 1385 }
1290 1386
1291 - cmf = NULL;
1292 - for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1293 - cmi = list_next(&cmh->cmh_inputs, cmi)) {
1294 - for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
1295 - cmf = list_next(&cmi->cmi_fmap, cmf)) {
1296 - if (strcmp(cmf->cmf_name, name) == 0)
1297 - goto found;
1387 + if (match == NULL) {
1388 + return (0);
1389 + }
1390 +
1391 + if ((err = ctf_add_object(fp, idx, match->cmo_tid)) != 0) {
1392 + ctf_dprintf("Failed to add symbol %s->%d: %s\n", name,
1393 + match->cmo_tid, ctf_errmsg(ctf_errno(fp)));
1394 + return (ctf_errno(fp));
1395 + }
1396 + ctf_dprintf("mapped object into output %s/%s->%ld\n", file,
1397 + name, match->cmo_tid);
1398 + } else {
1399 + ctf_merge_funcmap_t *cmf, *match = NULL;
1400 + ctf_funcinfo_t fi;
1401 +
1402 + for (cmf = list_head(csa->cmsa_funcmap); cmf != NULL;
1403 + cmf = list_next(csa->cmsa_funcmap, cmf)) {
1404 + boolean_t is_fuzzy = B_FALSE;
1405 + if (ctf_merge_symbol_match(cmf->cmf_file, cmf->cmf_name,
1406 + &cmf->cmf_sym, file, name, symp, &is_fuzzy)) {
1407 + if (is_fuzzy && csa->cmsa_dedup &&
1408 + bind != STB_WEAK) {
1409 + continue;
1410 + }
1411 + match = cmf;
1412 + if (is_fuzzy) {
1413 + continue;
1414 + }
1415 + break;
1298 1416 }
1299 1417 }
1300 -found:
1301 - if (cmf != NULL) {
1302 - fi.ctc_return = cmf->cmf_rtid;
1303 - fi.ctc_argc = cmf->cmf_argc;
1304 - fi.ctc_flags = cmf->cmf_flags;
1305 - if ((err = ctf_add_function(fp, i, &fi,
1306 - cmf->cmf_args)) != 0)
1307 - return (err);
1418 +
1419 + if (match == NULL) {
1420 + return (0);
1308 1421 }
1422 +
1423 + fi.ctc_return = match->cmf_rtid;
1424 + fi.ctc_argc = match->cmf_argc;
1425 + fi.ctc_flags = match->cmf_flags;
1426 + if ((err = ctf_add_function(fp, idx, &fi, match->cmf_args)) !=
1427 + 0) {
1428 + ctf_dprintf("Failed to add function %s: %s\n", name,
1429 + ctf_errmsg(ctf_errno(fp)));
1430 + return (ctf_errno(fp));
1431 + }
1432 + ctf_dprintf("mapped function into output %s/%s\n", file,
1433 + name);
1309 1434 }
1310 1435
1311 1436 return (0);
1312 -
1313 1437 }
1314 1438
1315 1439 int
1316 1440 ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1317 1441 {
1318 1442 int err, merr;
1319 1443 ctf_merge_input_t *cmi;
1320 1444 ctf_id_t ltype;
1321 1445 mergeq_t *mqp;
1322 1446 ctf_merge_input_t *final;
1323 1447 ctf_file_t *out;
1324 1448
1449 + ctf_dprintf("Beginning ctf_merge_merge()\n");
1325 1450 if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1326 1451 const char *label = ctf_label_topmost(cmh->cmh_unique);
1327 1452 if (label == NULL)
1328 1453 return (ECTF_NOLABEL);
1329 1454 if (strcmp(label, cmh->cmh_label) != 0)
1330 1455 return (ECTF_LCONFLICT);
1331 1456 }
1332 1457
1333 1458 if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1334 1459 return (errno);
1335 1460 }
1336 1461
1337 1462 VERIFY(cmh->cmh_ninputs % 2 == 0);
1338 1463 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1339 1464 cmi = list_next(&cmh->cmh_inputs, cmi)) {
1340 1465 if (mergeq_add(mqp, cmi) == -1) {
1341 1466 err = errno;
1342 1467 mergeq_fini(mqp);
1343 1468 }
1344 1469 }
1345 1470
1346 1471 err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr);
1347 1472 mergeq_fini(mqp);
1348 1473
1349 1474 if (err == MERGEQ_ERROR) {
1350 1475 return (errno);
1351 1476 } else if (err == MERGEQ_UERROR) {
1352 1477 return (merr);
1353 1478 }
1354 1479
1355 1480 /*
1356 1481 * Disassociate the generated ctf_file_t from the original input. That
1357 1482 * way when the input gets cleaned up, we don't accidentally kill the
1358 1483 * final reference to the ctf_file_t. If it gets uniquified then we'll
1359 1484 * kill it.
1360 1485 */
1361 1486 VERIFY(final->cmi_input != NULL);
1362 1487 out = final->cmi_input;
1363 1488 final->cmi_input = NULL;
1364 1489
1365 1490 ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique);
1366 1491 if (cmh->cmh_unique != NULL) {
1367 1492 ctf_file_t *u;
1368 1493 err = ctf_uniquify_types(cmh, out, &u);
1369 1494 if (err != 0) {
1370 1495 err = ctf_errno(out);
1371 1496 ctf_close(out);
1372 1497 return (err);
1373 1498 }
1374 1499 ctf_close(out);
1375 1500 out = u;
1376 1501 }
1377 1502
1378 1503 ltype = out->ctf_typemax;
1379 1504 if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
1380 1505 ltype += CTF_CHILD_START;
1381 1506 ctf_dprintf("trying to add the label\n");
1382 1507 if (cmh->cmh_label != NULL &&
1383 1508 ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1384 1509 ctf_close(out);
1385 1510 return (ctf_errno(out));
1386 1511 }
1387 1512
1388 1513 ctf_dprintf("merging symbols and the like\n");
1389 1514 if (cmh->cmh_msyms == B_TRUE) {
1390 - err = ctf_merge_symbols(cmh, out);
1515 + ctf_merge_symbol_arg_t arg;
1516 + arg.cmsa_objmap = &final->cmi_omap;
1517 + arg.cmsa_funcmap = &final->cmi_fmap;
1518 + arg.cmsa_out = out;
1519 + arg.cmsa_dedup = B_FALSE;
1520 + err = ctf_symtab_iter(out, ctf_merge_symbols, &arg);
1391 1521 if (err != 0) {
1392 1522 ctf_close(out);
1393 - return (ctf_errno(out));
1523 + return (err);
1394 1524 }
1395 -
1396 - err = ctf_merge_functions(cmh, out);
1397 - if (err != 0) {
1398 - ctf_close(out);
1399 - return (ctf_errno(out));
1400 - }
1401 1525 }
1402 1526
1403 1527 err = ctf_update(out);
1404 1528 if (err != 0) {
1529 + err = ctf_errno(out);
1405 1530 ctf_close(out);
1406 - return (ctf_errno(out));
1531 + return (err);
1407 1532 }
1408 1533
1409 1534 *outp = out;
1410 1535 return (0);
1411 1536 }
1412 1537
1413 1538 /*
1414 1539 * When we get told that something is unique, eg. same is B_FALSE, then that
1415 1540 * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1416 1541 * want to record it in the mapping table so that we know how to redirect types
1417 1542 * to the extant ones.
1418 1543 */
1419 1544 static void
1420 1545 ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1421 1546 ctf_id_t oid, void *arg)
1422 1547 {
1423 1548 ctf_merge_types_t *cmp = arg;
1424 1549 ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1425 1550
1426 1551 if (same == B_TRUE) {
1427 1552 /*
1428 1553 * The output id here may itself map to something else.
1429 1554 * Therefore, we need to basically walk a chain and see what it
1430 1555 * points to until it itself points to a base type, eg. -1.
1431 1556 * Otherwise we'll dedup to something which no longer exists.
1432 1557 */
1433 1558 while (cmt[oid].cmt_missing == B_FALSE)
1434 1559 oid = cmt[oid].cmt_map;
1435 1560 cmt[iid].cmt_map = oid;
1436 1561 ctf_dprintf("%d->%d \n", iid, oid);
1437 1562 } else {
1438 1563 VERIFY(cmt[iid].cmt_map == 0);
1439 1564 cmt[iid].cmt_missing = B_TRUE;
1440 1565 ctf_dprintf("%d is missing\n", iid);
1441 1566 }
1442 1567 }
1443 1568
1444 1569 /*
1445 1570 * Dedup a CTF container.
1446 1571 *
1447 1572 * DWARF and other encoding formats that we use to create CTF data may create
1448 1573 * multiple copies of a given type. However, after doing a conversion, and
1449 1574 * before doing a merge, we'd prefer, if possible, to have every input container
1450 1575 * to be unique.
1451 1576 *
1452 1577 * Doing a deduplication is like a normal merge. However, when we diff the types
1453 1578 * in the container, rather than doing a normal diff, we instead want to diff
1454 1579 * against any already processed types. eg, for a given type i in a container,
1455 1580 * we want to diff it from 0 to i - 1.
1456 1581 */
1457 1582 int
1458 1583 ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp)
1459 1584 {
1460 1585 int ret;
1461 1586 ctf_diff_t *cdp = NULL;
1462 1587 ctf_merge_input_t *cmi, *cmc;
1463 1588 ctf_file_t *ifp, *ofp;
1464 1589 ctf_merge_types_t cm;
1465 1590
1466 1591 if (cmp == NULL || outp == NULL)
1467 1592 return (EINVAL);
1468 1593
1469 1594 ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs);
1470 1595 if (cmp->cmh_ninputs != 2)
1471 1596 return (EINVAL);
1472 1597
1473 1598 ctf_dprintf("passed argument sanity check\n");
1474 1599
1475 1600 cmi = list_head(&cmp->cmh_inputs);
1476 1601 VERIFY(cmi != NULL);
1477 1602 cmc = list_next(&cmp->cmh_inputs, cmi);
1478 1603 VERIFY(cmc != NULL);
1479 1604 ifp = cmi->cmi_input;
1480 1605 ofp = cmc->cmi_input;
1481 1606 VERIFY(ifp != NULL);
1482 1607 VERIFY(ofp != NULL);
1483 1608 cm.cm_src = ifp;
1484 1609 cm.cm_out = ofp;
1485 1610 cm.cm_dedup = B_TRUE;
1486 1611 cm.cm_unique = B_FALSE;
1487 1612
1488 1613 if ((ret = ctf_merge_types_init(&cm)) != 0) {
1489 1614 return (ret);
1490 1615 }
1491 1616
1492 1617 if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1493 1618 goto err;
1494 1619
1495 1620 ctf_dprintf("Successfully initialized dedup\n");
1496 1621 if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1497 1622 goto err;
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
1498 1623
1499 1624 ctf_dprintf("Successfully diffed types\n");
1500 1625 ret = ctf_merge_common(&cm);
1501 1626 ctf_dprintf("deduping types result: %d\n", ret);
1502 1627 if (ret == 0)
1503 1628 ret = ctf_update(cm.cm_out);
1504 1629 if (ret != 0)
1505 1630 goto err;
1506 1631
1507 1632 ctf_dprintf("Successfully deduped types\n");
1508 - ctf_phase_dump(cm.cm_out, "dedup-pre-syms");
1633 + ctf_phase_dump(cm.cm_out, "dedup-pre-syms", NULL);
1509 1634
1510 1635 /*
1511 1636 * Now we need to fix up the object and function maps.
1512 1637 */
1513 - ctf_merge_fixup_nontypes(&cm, cmi);
1638 + ctf_merge_fixup_symmaps(&cm, cmi);
1514 1639
1515 1640 if (cmp->cmh_msyms == B_TRUE) {
1516 - ret = ctf_merge_symbols(cmp, cm.cm_out);
1641 + ctf_merge_symbol_arg_t arg;
1642 + arg.cmsa_objmap = &cmi->cmi_omap;
1643 + arg.cmsa_funcmap = &cmi->cmi_fmap;
1644 + arg.cmsa_out = cm.cm_out;
1645 + arg.cmsa_dedup = B_TRUE;
1646 + ret = ctf_symtab_iter(cm.cm_out, ctf_merge_symbols, &arg);
1517 1647 if (ret != 0) {
1518 - ret = ctf_errno(cm.cm_out);
1519 1648 ctf_dprintf("failed to dedup symbols: %s\n",
1520 1649 ctf_errmsg(ret));
1521 1650 goto err;
1522 1651 }
1523 -
1524 - ret = ctf_merge_functions(cmp, cm.cm_out);
1525 - if (ret != 0) {
1526 - ret = ctf_errno(cm.cm_out);
1527 - ctf_dprintf("failed to dedup functions: %s\n",
1528 - ctf_errmsg(ret));
1529 - goto err;
1530 - }
1531 1652 }
1532 1653
1533 1654 ret = ctf_update(cm.cm_out);
1534 1655 if (ret == 0) {
1535 1656 cmc->cmi_input = NULL;
1536 1657 *outp = cm.cm_out;
1537 1658 }
1659 + ctf_phase_dump(cm.cm_out, "dedup-post-syms", NULL);
1538 1660 err:
1539 1661 ctf_merge_types_fini(&cm);
1540 1662 ctf_diff_fini(cdp);
1541 1663 return (ret);
1542 1664 }
1543 1665
1544 1666 int
1545 1667 ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1546 1668 {
1547 1669 if (nthrs == 0)
1548 1670 return (EINVAL);
1549 1671 cmp->cmh_nthreads = nthrs;
1550 1672 return (0);
1551 1673 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX