Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
39586 views
1
/*
2
* CDDL HEADER START
3
*
4
* The contents of this file are subject to the terms of the
5
* Common Development and Distribution License (the "License").
6
* You may not use this file except in compliance with the License.
7
*
8
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9
* or http://www.opensolaris.org/os/licensing.
10
* See the License for the specific language governing permissions
11
* and limitations under the License.
12
*
13
* When distributing Covered Code, include this CDDL HEADER in each
14
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15
* If applicable, add the following below this CDDL HEADER, with the
16
* fields enclosed by brackets "[]" replaced with your own identifying
17
* information: Portions Copyright [yyyy] [name of copyright owner]
18
*
19
* CDDL HEADER END
20
*/
21
/*
22
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23
* Use is subject to license terms.
24
*/
25
26
/*
27
* Routines for preparing tdata trees for conversion into CTF data, and
28
* for placing the resulting data into an output file.
29
*/
30
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <strings.h>
34
#include <sys/types.h>
35
#include <sys/stat.h>
36
#include <fcntl.h>
37
#include <libelf.h>
38
#include <gelf.h>
39
#include <unistd.h>
40
41
#include "ctftools.h"
42
#include "list.h"
43
#include "memory.h"
44
#include "traverse.h"
45
#include "symbol.h"
46
47
typedef struct iidesc_match {
48
int iim_fuzzy;
49
iidesc_t *iim_ret;
50
char *iim_name;
51
char *iim_file;
52
uchar_t iim_bind;
53
} iidesc_match_t;
54
55
static int
56
burst_iitypes(void *data, void *arg)
57
{
58
iidesc_t *ii = data;
59
iiburst_t *iiburst = arg;
60
61
switch (ii->ii_type) {
62
case II_GFUN:
63
case II_SFUN:
64
case II_GVAR:
65
case II_SVAR:
66
if (!(ii->ii_flags & IIDESC_F_USED))
67
return (0);
68
break;
69
default:
70
break;
71
}
72
73
ii->ii_dtype->t_flags |= TDESC_F_ISROOT;
74
(void) iitraverse_td(ii, iiburst->iib_tdtd);
75
return (1);
76
}
77
78
/*ARGSUSED1*/
79
static int
80
save_type_by_id(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
81
{
82
iiburst_t *iiburst = private;
83
84
/*
85
* Doing this on every node is horribly inefficient, but given that
86
* we may be suppressing some types, we can't trust nextid in the
87
* tdata_t.
88
*/
89
if (tdp->t_id > iiburst->iib_maxtypeid)
90
iiburst->iib_maxtypeid = tdp->t_id;
91
92
slist_add(&iiburst->iib_types, tdp, tdesc_idcmp);
93
94
return (1);
95
}
96
97
static tdtrav_cb_f burst_types_cbs[] = {
98
NULL,
99
save_type_by_id, /* intrinsic */
100
save_type_by_id, /* pointer */
101
save_type_by_id, /* array */
102
save_type_by_id, /* function */
103
save_type_by_id, /* struct */
104
save_type_by_id, /* union */
105
save_type_by_id, /* enum */
106
save_type_by_id, /* forward */
107
save_type_by_id, /* typedef */
108
tdtrav_assert, /* typedef_unres */
109
save_type_by_id, /* volatile */
110
save_type_by_id, /* const */
111
save_type_by_id /* restrict */
112
};
113
114
115
static iiburst_t *
116
iiburst_new(tdata_t *td, int max)
117
{
118
iiburst_t *iiburst = xcalloc(sizeof (iiburst_t));
119
iiburst->iib_td = td;
120
iiburst->iib_funcs = xcalloc(sizeof (iidesc_t *) * max);
121
iiburst->iib_nfuncs = 0;
122
iiburst->iib_objts = xcalloc(sizeof (iidesc_t *) * max);
123
iiburst->iib_nobjts = 0;
124
return (iiburst);
125
}
126
127
static void
128
iiburst_types(iiburst_t *iiburst)
129
{
130
tdtrav_data_t tdtd;
131
132
tdtrav_init(&tdtd, &iiburst->iib_td->td_curvgen, NULL, burst_types_cbs,
133
NULL, (void *)iiburst);
134
135
iiburst->iib_tdtd = &tdtd;
136
137
(void) hash_iter(iiburst->iib_td->td_iihash, burst_iitypes, iiburst);
138
}
139
140
static void
141
iiburst_free(iiburst_t *iiburst)
142
{
143
free(iiburst->iib_funcs);
144
free(iiburst->iib_objts);
145
list_free(iiburst->iib_types, NULL, NULL);
146
free(iiburst);
147
}
148
149
/*
150
* See if this iidesc matches the ELF symbol data we pass in.
151
*
152
* A fuzzy match is where we have a local symbol matching the name of a
153
* global type description. This is common when a mapfile is used for a
154
* DSO, but we don't accept it by default.
155
*
156
* A weak fuzzy match is when a weak symbol was resolved and matched to
157
* a global type description.
158
*/
159
static int
160
matching_iidesc(void *arg1, void *arg2)
161
{
162
iidesc_t *iidesc = arg1;
163
iidesc_match_t *match = arg2;
164
if (streq(iidesc->ii_name, match->iim_name) == 0)
165
return (0);
166
167
switch (iidesc->ii_type) {
168
case II_GFUN:
169
case II_GVAR:
170
if (match->iim_bind == STB_GLOBAL) {
171
match->iim_ret = iidesc;
172
return (-1);
173
} else if (match->iim_fuzzy && match->iim_ret == NULL) {
174
match->iim_ret = iidesc;
175
/* continue to look for strong match */
176
return (0);
177
}
178
break;
179
case II_SFUN:
180
case II_SVAR:
181
if (match->iim_bind == STB_LOCAL &&
182
match->iim_file != NULL &&
183
streq(iidesc->ii_owner, match->iim_file)) {
184
match->iim_ret = iidesc;
185
return (-1);
186
}
187
break;
188
default:
189
break;
190
}
191
return (0);
192
}
193
194
static iidesc_t *
195
find_iidesc(tdata_t *td, iidesc_match_t *match)
196
{
197
match->iim_ret = NULL;
198
iter_iidescs_by_name(td, match->iim_name,
199
matching_iidesc, match);
200
return (match->iim_ret);
201
}
202
203
/*
204
* If we have a weak symbol, attempt to find the strong symbol it will
205
* resolve to. Note: the code where this actually happens is in
206
* sym_process() in cmd/sgs/libld/common/syms.c
207
*
208
* Finding the matching symbol is unfortunately not trivial. For a
209
* symbol to be a candidate, it must:
210
*
211
* - have the same type (function, object)
212
* - have the same value (address)
213
* - have the same size
214
* - not be another weak symbol
215
* - belong to the same section (checked via section index)
216
*
217
* If such a candidate is global, then we assume we've found it. The
218
* linker generates the symbol table such that the curfile might be
219
* incorrect; this is OK for global symbols, since find_iidesc() doesn't
220
* need to check for the source file for the symbol.
221
*
222
* We might have found a strong local symbol, where the curfile is
223
* accurate and matches that of the weak symbol. We assume this is a
224
* reasonable match.
225
*
226
* If we've got a local symbol with a non-matching curfile, there are
227
* two possibilities. Either this is a completely different symbol, or
228
* it's a once-global symbol that was scoped to local via a mapfile. In
229
* the latter case, curfile is likely inaccurate since the linker does
230
* not preserve the needed curfile in the order of the symbol table (see
231
* the comments about locally scoped symbols in libld's update_osym()).
232
* As we can't tell this case from the former one, we use this symbol
233
* iff no other matching symbol is found.
234
*
235
* What we really need here is a SUNW section containing weak<->strong
236
* mappings that we can consume.
237
*/
238
static int
239
check_for_weak(GElf_Sym *weak, char const *weakfile,
240
Elf_Data *data, int nent, Elf_Data *strdata,
241
GElf_Sym *retsym, char **curfilep)
242
{
243
char *curfile = NULL;
244
char *tmpfile1 = NULL;
245
GElf_Sym tmpsym;
246
int candidate = 0;
247
int i;
248
tmpsym.st_info = 0;
249
tmpsym.st_name = 0;
250
251
if (GELF_ST_BIND(weak->st_info) != STB_WEAK)
252
return (0);
253
254
for (i = 0; i < nent; i++) {
255
GElf_Sym sym;
256
uchar_t type;
257
258
if (gelf_getsym(data, i, &sym) == NULL)
259
continue;
260
261
type = GELF_ST_TYPE(sym.st_info);
262
263
if (type == STT_FILE)
264
curfile = (char *)strdata->d_buf + sym.st_name;
265
266
if (GELF_ST_TYPE(weak->st_info) != type ||
267
weak->st_value != sym.st_value)
268
continue;
269
270
if (weak->st_size != sym.st_size)
271
continue;
272
273
if (GELF_ST_BIND(sym.st_info) == STB_WEAK)
274
continue;
275
276
if (sym.st_shndx != weak->st_shndx)
277
continue;
278
279
if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
280
(curfile == NULL || weakfile == NULL ||
281
strcmp(curfile, weakfile) != 0)) {
282
candidate = 1;
283
tmpfile1 = curfile;
284
tmpsym = sym;
285
continue;
286
}
287
288
*curfilep = curfile;
289
*retsym = sym;
290
return (1);
291
}
292
293
if (candidate) {
294
*curfilep = tmpfile1;
295
*retsym = tmpsym;
296
return (1);
297
}
298
299
return (0);
300
}
301
302
/*
303
* When we've found the underlying symbol's type description
304
* for a weak symbol, we need to copy it and rename it to match
305
* the weak symbol. We also need to add it to the td so it's
306
* handled along with the others later.
307
*/
308
static iidesc_t *
309
copy_from_strong(tdata_t *td, GElf_Sym *sym, iidesc_t *strongdesc,
310
const char *weakname, const char *weakfile)
311
{
312
iidesc_t *new = iidesc_dup_rename(strongdesc, weakname, weakfile);
313
uchar_t type = GELF_ST_TYPE(sym->st_info);
314
315
switch (type) {
316
case STT_OBJECT:
317
new->ii_type = II_GVAR;
318
break;
319
case STT_FUNC:
320
new->ii_type = II_GFUN;
321
break;
322
}
323
324
hash_add(td->td_iihash, new);
325
326
return (new);
327
}
328
329
/*
330
* Process the symbol table of the output file, associating each symbol
331
* with a type description if possible, and sorting them into functions
332
* and data, maintaining symbol table order.
333
*/
334
static iiburst_t *
335
sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch,
336
int dynsym)
337
{
338
iiburst_t *iiburst;
339
Elf_Scn *scn;
340
GElf_Shdr shdr;
341
Elf_Data *data, *strdata;
342
int i, stidx;
343
int nent;
344
iidesc_match_t match;
345
346
match.iim_fuzzy = fuzzymatch;
347
match.iim_file = NULL;
348
349
if ((stidx = findelfsecidx(elf, file,
350
dynsym ? ".dynsym" : ".symtab")) < 0)
351
terminate("%s: Can't open symbol table\n", file);
352
scn = elf_getscn(elf, stidx);
353
data = elf_getdata(scn, NULL);
354
gelf_getshdr(scn, &shdr);
355
nent = shdr.sh_size / shdr.sh_entsize;
356
357
scn = elf_getscn(elf, shdr.sh_link);
358
strdata = elf_getdata(scn, NULL);
359
360
iiburst = iiburst_new(td, nent);
361
362
for (i = 0; i < nent; i++) {
363
GElf_Sym sym;
364
char *bname;
365
iidesc_t **tolist;
366
GElf_Sym ssym;
367
iidesc_match_t smatch;
368
int *curr;
369
iidesc_t *iidesc;
370
371
if (gelf_getsym(data, i, &sym) == NULL)
372
elfterminate(file, "Couldn't read symbol %d", i);
373
374
match.iim_name = (char *)strdata->d_buf + sym.st_name;
375
match.iim_bind = GELF_ST_BIND(sym.st_info);
376
377
switch (GELF_ST_TYPE(sym.st_info)) {
378
case STT_FILE:
379
bname = strrchr(match.iim_name, '/');
380
match.iim_file = bname == NULL ? match.iim_name : bname + 1;
381
continue;
382
case STT_OBJECT:
383
tolist = iiburst->iib_objts;
384
curr = &iiburst->iib_nobjts;
385
break;
386
case STT_FUNC:
387
tolist = iiburst->iib_funcs;
388
curr = &iiburst->iib_nfuncs;
389
break;
390
default:
391
continue;
392
}
393
394
if (ignore_symbol(&sym, match.iim_name))
395
continue;
396
397
iidesc = find_iidesc(td, &match);
398
399
if (iidesc != NULL) {
400
tolist[*curr] = iidesc;
401
iidesc->ii_flags |= IIDESC_F_USED;
402
(*curr)++;
403
continue;
404
}
405
406
if (!check_for_weak(&sym, match.iim_file, data, nent, strdata,
407
&ssym, &smatch.iim_file)) {
408
(*curr)++;
409
continue;
410
}
411
412
smatch.iim_fuzzy = fuzzymatch;
413
smatch.iim_name = (char *)strdata->d_buf + ssym.st_name;
414
smatch.iim_bind = GELF_ST_BIND(ssym.st_info);
415
416
debug(3, "Weak symbol %s resolved to %s\n", match.iim_name,
417
smatch.iim_name);
418
419
iidesc = find_iidesc(td, &smatch);
420
421
if (iidesc != NULL) {
422
tolist[*curr] = copy_from_strong(td, &sym,
423
iidesc, match.iim_name, match.iim_file);
424
tolist[*curr]->ii_flags |= IIDESC_F_USED;
425
}
426
427
(*curr)++;
428
}
429
430
/*
431
* Stabs are generated for every function declared in a given C source
432
* file. When converting an object file, we may encounter a stab that
433
* has no symbol table entry because the optimizer has decided to omit
434
* that item (for example, an unreferenced static function). We may
435
* see iidescs that do not have an associated symtab entry, and so
436
* we do not write records for those functions into the CTF data.
437
* All others get marked as a root by this function.
438
*/
439
iiburst_types(iiburst);
440
441
/*
442
* By not adding some of the functions and/or objects, we may have
443
* caused some types that were referenced solely by those
444
* functions/objects to be suppressed. This could cause a label,
445
* generated prior to the evisceration, to be incorrect. Find the
446
* highest type index, and change the label indicies to be no higher
447
* than this value.
448
*/
449
tdata_label_newmax(td, iiburst->iib_maxtypeid);
450
451
return (iiburst);
452
}
453
454
static void
455
write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
456
caddr_t ctfdata, size_t ctfsize, int flags)
457
{
458
GElf_Ehdr sehdr, dehdr;
459
Elf_Scn *sscn, *dscn;
460
Elf_Data *sdata, *ddata;
461
GElf_Shdr shdr;
462
GElf_Word symtab_type;
463
int symtab_idx = -1;
464
off_t new_offset = 0;
465
off_t ctfnameoff = 0;
466
int dynsym = (flags & CTF_USE_DYNSYM);
467
int keep_stabs = (flags & CTF_KEEP_STABS);
468
int *secxlate;
469
int srcidx, dstidx;
470
int changing = 0;
471
int pad;
472
int i;
473
474
if (gelf_newehdr(dst, gelf_getclass(src)) == NULL)
475
elfterminate(dstname, "Cannot copy ehdr to temp file");
476
gelf_getehdr(src, &sehdr);
477
memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr));
478
gelf_update_ehdr(dst, &dehdr);
479
480
symtab_type = dynsym ? SHT_DYNSYM : SHT_SYMTAB;
481
482
/*
483
* Neither the existing stab sections nor the SUNW_ctf sections (new or
484
* existing) are SHF_ALLOC'd, so they won't be in areas referenced by
485
* program headers. As such, we can just blindly copy the program
486
* headers from the existing file to the new file.
487
*/
488
if (sehdr.e_phnum != 0) {
489
(void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT);
490
if (gelf_newphdr(dst, sehdr.e_phnum) == NULL)
491
elfterminate(dstname, "Cannot make phdrs in temp file");
492
493
for (i = 0; i < sehdr.e_phnum; i++) {
494
GElf_Phdr phdr;
495
496
gelf_getphdr(src, i, &phdr);
497
gelf_update_phdr(dst, i, &phdr);
498
}
499
}
500
501
secxlate = xmalloc(sizeof (int) * sehdr.e_shnum);
502
for (srcidx = dstidx = 0; srcidx < sehdr.e_shnum; srcidx++) {
503
Elf_Scn *scn = elf_getscn(src, srcidx);
504
GElf_Shdr shdr1;
505
char *sname;
506
507
gelf_getshdr(scn, &shdr1);
508
sname = elf_strptr(src, sehdr.e_shstrndx, shdr1.sh_name);
509
if (sname == NULL) {
510
elfterminate(srcname, "Can't find string at %u",
511
shdr1.sh_name);
512
}
513
514
if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) {
515
secxlate[srcidx] = -1;
516
} else if (!keep_stabs &&
517
(strncmp(sname, ".stab", 5) == 0 ||
518
strncmp(sname, ".debug", 6) == 0 ||
519
strncmp(sname, ".rel.debug", 10) == 0 ||
520
strncmp(sname, ".rela.debug", 11) == 0)) {
521
secxlate[srcidx] = -1;
522
} else if (dynsym && shdr1.sh_type == SHT_SYMTAB) {
523
/*
524
* If we're building CTF against the dynsym,
525
* we'll rip out the symtab so debuggers aren't
526
* confused.
527
*/
528
secxlate[srcidx] = -1;
529
} else {
530
secxlate[srcidx] = dstidx++;
531
}
532
533
new_offset = (off_t)dehdr.e_phoff;
534
}
535
536
for (srcidx = 1; srcidx < sehdr.e_shnum; srcidx++) {
537
char *sname;
538
539
sscn = elf_getscn(src, srcidx);
540
gelf_getshdr(sscn, &shdr);
541
542
if (secxlate[srcidx] == -1) {
543
changing = 1;
544
continue;
545
}
546
547
dscn = elf_newscn(dst);
548
549
/*
550
* If this file has program headers, we need to explicitly lay
551
* out sections. If none of the sections prior to this one have
552
* been removed, then we can just use the existing location. If
553
* one or more sections have been changed, then we need to
554
* adjust this one to avoid holes.
555
*/
556
if (changing && sehdr.e_phnum != 0) {
557
pad = new_offset % shdr.sh_addralign;
558
559
if (pad)
560
new_offset += shdr.sh_addralign - pad;
561
shdr.sh_offset = new_offset;
562
}
563
564
shdr.sh_link = secxlate[shdr.sh_link];
565
566
if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA)
567
shdr.sh_info = secxlate[shdr.sh_info];
568
569
sname = elf_strptr(src, sehdr.e_shstrndx, shdr.sh_name);
570
if (sname == NULL) {
571
elfterminate(srcname, "Can't find string at %u",
572
shdr.sh_name);
573
}
574
575
#ifndef illumos
576
if (gelf_update_shdr(dscn, &shdr) == 0)
577
elfterminate(dstname, "Cannot update sect %s", sname);
578
#endif
579
580
if ((sdata = elf_getdata(sscn, NULL)) == NULL)
581
elfterminate(srcname, "Cannot get sect %s data", sname);
582
if ((ddata = elf_newdata(dscn)) == NULL)
583
elfterminate(dstname, "Can't make sect %s data", sname);
584
#ifdef illumos
585
bcopy(sdata, ddata, sizeof (Elf_Data));
586
#else
587
/*
588
* FreeBSD's Elf_Data has private fields which the
589
* elf_* routines manage. Simply copying the
590
* entire structure corrupts the data. So we need
591
* to copy the public fields explictly.
592
*/
593
ddata->d_align = sdata->d_align;
594
ddata->d_off = sdata->d_off;
595
ddata->d_size = sdata->d_size;
596
ddata->d_type = sdata->d_type;
597
ddata->d_version = sdata->d_version;
598
#endif
599
600
if (srcidx == sehdr.e_shstrndx) {
601
char seclen = strlen(CTF_ELF_SCN_NAME);
602
603
ddata->d_buf = xmalloc(ddata->d_size + shdr.sh_size +
604
seclen + 1);
605
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
606
strcpy((caddr_t)ddata->d_buf + shdr.sh_size,
607
CTF_ELF_SCN_NAME);
608
ctfnameoff = (off_t)shdr.sh_size;
609
shdr.sh_size += seclen + 1;
610
ddata->d_size += seclen + 1;
611
612
if (sehdr.e_phnum != 0)
613
changing = 1;
614
}
615
616
if (shdr.sh_type == symtab_type && shdr.sh_entsize != 0) {
617
int nsym = shdr.sh_size / shdr.sh_entsize;
618
619
symtab_idx = secxlate[srcidx];
620
621
ddata->d_buf = xmalloc(shdr.sh_size);
622
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
623
624
for (i = 0; i < nsym; i++) {
625
GElf_Sym sym;
626
short newscn;
627
628
if (gelf_getsym(ddata, i, &sym) == NULL)
629
printf("Could not get symbol %d\n",i);
630
631
if (sym.st_shndx >= SHN_LORESERVE)
632
continue;
633
634
if ((newscn = secxlate[sym.st_shndx]) !=
635
sym.st_shndx) {
636
sym.st_shndx =
637
(newscn == -1 ? 1 : newscn);
638
639
gelf_update_sym(ddata, i, &sym);
640
}
641
}
642
}
643
644
#ifndef illumos
645
if (ddata->d_buf == NULL && sdata->d_buf != NULL) {
646
ddata->d_buf = xmalloc(shdr.sh_size);
647
bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size);
648
}
649
#endif
650
651
if (gelf_update_shdr(dscn, &shdr) == 0)
652
elfterminate(dstname, "Cannot update sect %s", sname);
653
654
new_offset = (off_t)shdr.sh_offset;
655
if (shdr.sh_type != SHT_NOBITS)
656
new_offset += shdr.sh_size;
657
}
658
659
if (symtab_idx == -1) {
660
terminate("%s: Cannot find %s section\n", srcname,
661
dynsym ? "SHT_DYNSYM" : "SHT_SYMTAB");
662
}
663
664
/* Add the ctf section */
665
dscn = elf_newscn(dst);
666
gelf_getshdr(dscn, &shdr);
667
shdr.sh_name = ctfnameoff;
668
shdr.sh_type = SHT_PROGBITS;
669
shdr.sh_size = ctfsize;
670
shdr.sh_link = symtab_idx;
671
shdr.sh_addralign = 4;
672
if (changing && sehdr.e_phnum != 0) {
673
pad = new_offset % shdr.sh_addralign;
674
675
if (pad)
676
new_offset += shdr.sh_addralign - pad;
677
678
shdr.sh_offset = new_offset;
679
new_offset += shdr.sh_size;
680
}
681
682
ddata = elf_newdata(dscn);
683
ddata->d_buf = ctfdata;
684
ddata->d_size = ctfsize;
685
ddata->d_align = shdr.sh_addralign;
686
ddata->d_off = 0;
687
688
gelf_update_shdr(dscn, &shdr);
689
690
/* update the section header location */
691
if (sehdr.e_phnum != 0) {
692
size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT);
693
size_t r = new_offset % align;
694
695
if (r)
696
new_offset += align - r;
697
698
dehdr.e_shoff = new_offset;
699
}
700
701
/* commit to disk */
702
dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx];
703
gelf_update_ehdr(dst, &dehdr);
704
if (elf_update(dst, ELF_C_WRITE) < 0)
705
elfterminate(dstname, "Cannot finalize temp file");
706
707
free(secxlate);
708
}
709
710
static caddr_t
711
make_ctf_data(tdata_t *td, Elf *elf, const char *file, size_t *lenp, int flags)
712
{
713
iiburst_t *iiburst;
714
caddr_t data;
715
716
iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH,
717
flags & CTF_USE_DYNSYM);
718
data = ctf_gen(iiburst, lenp, flags & (CTF_COMPRESS | CTF_SWAP_BYTES));
719
720
iiburst_free(iiburst);
721
722
return (data);
723
}
724
725
void
726
write_ctf(tdata_t *td, const char *curname, const char *newname, int flags)
727
{
728
struct stat st;
729
Elf *elf = NULL;
730
Elf *telf = NULL;
731
GElf_Ehdr ehdr;
732
caddr_t data;
733
size_t len;
734
int fd = -1;
735
int tfd = -1;
736
int byteorder;
737
738
(void) elf_version(EV_CURRENT);
739
if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
740
terminate("%s: Cannot open for re-reading", curname);
741
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
742
elfterminate(curname, "Cannot re-read");
743
744
if ((tfd = open(newname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0)
745
terminate("Cannot open temp file %s for writing", newname);
746
if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL)
747
elfterminate(curname, "Cannot write");
748
749
if (gelf_getehdr(elf, &ehdr)) {
750
#if BYTE_ORDER == _BIG_ENDIAN
751
byteorder = ELFDATA2MSB;
752
#else
753
byteorder = ELFDATA2LSB;
754
#endif
755
/*
756
* If target and host has the same byte order
757
* clear byte swapping request
758
*/
759
if (ehdr.e_ident[EI_DATA] == byteorder)
760
flags &= ~CTF_SWAP_BYTES;
761
}
762
else
763
elfterminate(curname, "Failed to get EHDR");
764
765
data = make_ctf_data(td, elf, curname, &len, flags);
766
write_file(elf, curname, telf, newname, data, len, flags);
767
free(data);
768
769
elf_end(telf);
770
elf_end(elf);
771
(void) close(fd);
772
(void) close(tfd);
773
}
774
775