pahole: Describe expected use of 'default' in the man page
[dwarves.git] / libctf.c
blobedb34dbf10de09e711abd032bf8a4b8e4c608e2e
1 /*
2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2019 Arnaldo Carvalho de Melo <acme@redhat.com>
5 */
7 #include <fcntl.h>
8 #include <gelf.h>
9 #include <limits.h>
10 #include <malloc.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <zlib.h>
18 #include "libctf.h"
19 #include "ctf.h"
20 #include "dutil.h"
21 #include "gobuffer.h"
23 bool ctf__ignore_symtab_function(const GElf_Sym *sym, const char *sym_name)
25 return (!elf_sym__is_local_function(sym) ||
26 elf_sym__visibility(sym) != STV_DEFAULT ||
27 sym->st_size == 0 ||
28 memcmp(sym_name, "__libc_csu_",
29 sizeof("__libc_csu_") - 1) == 0);
32 bool ctf__ignore_symtab_object(const GElf_Sym *sym, const char *sym_name)
34 return (!elf_sym__is_local_object(sym) || sym->st_size == 0 ||
35 elf_sym__visibility(sym) != STV_DEFAULT ||
36 strchr(sym_name, '.') != NULL);
39 uint16_t ctf__get16(struct ctf *ctf, uint16_t *p)
41 uint16_t val = *p;
43 if (ctf->swapped)
44 val = ((val >> 8) | (val << 8));
45 return val;
48 uint32_t ctf__get32(struct ctf *ctf, uint32_t *p)
50 uint32_t val = *p;
52 if (ctf->swapped)
53 val = ((val >> 24) |
54 ((val >> 8) & 0x0000ff00) |
55 ((val << 8) & 0x00ff0000) |
56 (val << 24));
57 return val;
60 void ctf__put16(struct ctf *ctf, uint16_t *p, uint16_t val)
62 if (ctf->swapped)
63 val = ((val >> 8) | (val << 8));
64 *p = val;
67 void ctf__put32(struct ctf *ctf, uint32_t *p, uint32_t val)
69 if (ctf->swapped)
70 val = ((val >> 24) |
71 ((val >> 8) & 0x0000ff00) |
72 ((val << 8) & 0x00ff0000) |
73 (val << 24));
74 *p = val;
77 static int ctf__decompress(struct ctf *ctf, void *orig_buf, size_t orig_size)
79 struct ctf_header *hp = orig_buf;
80 const char *err_str;
81 z_stream state;
82 size_t len;
83 void *new;
85 len = (ctf__get32(ctf, &hp->ctf_str_off) +
86 ctf__get32(ctf, &hp->ctf_str_len));
87 new = malloc(len + sizeof(*hp));
88 if (!new) {
89 fprintf(stderr, "CTF decompression allocation failure.\n");
90 return -ENOMEM;
92 memcpy(new, hp, sizeof(*hp));
94 memset(&state, 0, sizeof(state));
95 state.next_in = (Bytef *) (hp + 1);
96 state.avail_in = orig_size - sizeof(*hp);
97 state.next_out = new + sizeof(*hp);
98 state.avail_out = len;
100 if (inflateInit(&state) != Z_OK) {
101 err_str = "struct ctf decompression inflateInit failure.";
102 goto err;
105 if (inflate(&state, Z_FINISH) != Z_STREAM_END) {
106 err_str = "struct ctf decompression inflate failure.";
107 goto err;
110 if (inflateEnd(&state) != Z_OK) {
111 err_str = "struct ctf decompression inflateEnd failure.";
112 goto err;
115 if (state.total_out != len) {
116 err_str = "struct ctf decompression truncation error.";
117 goto err;
120 ctf->buf = new;
121 ctf->size = len + sizeof(*hp);
123 return 0;
125 err:
126 fputs(err_str, stderr);
127 free(new);
128 return -EINVAL;
131 int ctf__load(struct ctf *ctf)
133 int err = -ENOTSUP;
134 GElf_Shdr shdr;
135 Elf_Scn *sec = elf_section_by_name(ctf->elf, &shdr, ".SUNW_ctf", NULL);
137 if (sec == NULL)
138 return -ESRCH;
140 Elf_Data *data = elf_getdata(sec, NULL);
141 if (data == NULL) {
142 fprintf(stderr, "%s: cannot get data of CTF section.\n",
143 __func__);
144 return -1;
147 struct ctf_header *hp = data->d_buf;
148 size_t orig_size = data->d_size;
150 if (hp->ctf_version != CTF_VERSION)
151 goto out;
153 err = -EINVAL;
154 if (hp->ctf_magic == CTF_MAGIC)
155 ctf->swapped = 0;
156 else if (hp->ctf_magic == CTF_MAGIC_SWAP)
157 ctf->swapped = 1;
158 else
159 goto out;
161 if (!(hp->ctf_flags & CTF_FLAGS_COMPR)) {
162 err = -ENOMEM;
163 ctf->buf = malloc(orig_size);
164 if (ctf->buf != NULL) {
165 memcpy(ctf->buf, hp, orig_size);
166 ctf->size = orig_size;
167 err = 0;
169 } else
170 err = ctf__decompress(ctf, hp, orig_size);
171 out:
172 return err;
175 bool ctf__verbose;
177 struct ctf *ctf__new(const char *filename, Elf *elf)
179 struct ctf *ctf = zalloc(sizeof(*ctf));
181 if (ctf != NULL) {
182 ctf->filename = strdup(filename);
183 if (ctf->filename == NULL)
184 goto out_delete;
186 if (elf != NULL) {
187 ctf->in_fd = -1;
188 ctf->elf = elf;
189 } else {
191 ctf->in_fd = open(filename, O_RDONLY);
192 if (ctf->in_fd < 0)
193 goto out_delete_filename;
195 if (elf_version(EV_CURRENT) == EV_NONE) {
196 fprintf(stderr, "%s: cannot set libelf version.\n",
197 __func__);
198 goto out_close;
201 ctf->elf = elf_begin(ctf->in_fd, ELF_C_READ_MMAP, NULL);
202 if (!ctf->elf) {
203 fprintf(stderr, "%s: cannot read %s ELF file.\n",
204 __func__, filename);
205 goto out_close;
209 if (gelf_getehdr(ctf->elf, &ctf->ehdr) == NULL) {
210 if (ctf__verbose)
211 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
212 goto out_elf_end;
215 switch (ctf->ehdr.e_ident[EI_CLASS]) {
216 case ELFCLASS32: ctf->wordsize = 4; break;
217 case ELFCLASS64: ctf->wordsize = 8; break;
218 default: ctf->wordsize = 0; break;
222 return ctf;
223 out_elf_end:
224 if (elf == NULL)
225 elf_end(ctf->elf);
226 out_close:
227 if (elf == NULL)
228 close(ctf->in_fd);
229 out_delete_filename:
230 zfree(&ctf->filename);
231 out_delete:
232 free(ctf);
233 return NULL;
236 void ctf__delete(struct ctf *ctf)
238 if (ctf != NULL) {
239 if (ctf->in_fd != -1) {
240 elf_end(ctf->elf);
241 close(ctf->in_fd);
243 __gobuffer__delete(&ctf->objects);
244 __gobuffer__delete(&ctf->types);
245 __gobuffer__delete(&ctf->funcs);
246 elf_symtab__delete(ctf->symtab);
247 zfree(&ctf->filename);
248 zfree(&ctf->buf);
249 free(ctf);
253 char *ctf__string(struct ctf *ctf, uint32_t ref)
255 struct ctf_header *hp = ctf->buf;
256 uint32_t off = CTF_REF_OFFSET(ref);
257 char *name;
259 if (CTF_REF_TBL_ID(ref) != CTF_STR_TBL_ID_0)
260 return "(external ref)";
262 if (off >= ctf__get32(ctf, &hp->ctf_str_len))
263 return "(ref out-of-bounds)";
265 if ((off + ctf__get32(ctf, &hp->ctf_str_off)) >= ctf->size)
266 return "(string table truncated)";
268 name = ((char *)(hp + 1) + ctf__get32(ctf, &hp->ctf_str_off) + off);
270 return name[0] == '\0' ? NULL : name;
273 void *ctf__get_buffer(struct ctf *ctf)
275 return ctf->buf;
278 size_t ctf__get_size(struct ctf *ctf)
280 return ctf->size;
283 int ctf__load_symtab(struct ctf *ctf)
285 ctf->symtab = elf_symtab__new(".symtab", ctf->elf);
286 return ctf->symtab == NULL ? -1 : 0;
289 void ctf__set_strings(struct ctf *ctf, struct strings *strings)
291 ctf->strings = strings;
294 uint32_t ctf__add_base_type(struct ctf *ctf, uint32_t name, uint16_t size)
296 struct ctf_full_type t;
298 t.base.ctf_name = name;
299 t.base.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_INT, 0, 0);
300 t.base.ctf_size = size;
301 t.ctf_size_high = CTF_TYPE_INT_ENCODE(0, 0, size);
303 gobuffer__add(&ctf->types, &t, sizeof(t) - sizeof(uint32_t));
304 return ++ctf->type_index;
307 uint32_t ctf__add_short_type(struct ctf *ctf, uint16_t kind, uint16_t type, uint32_t name)
309 struct ctf_short_type t;
311 t.ctf_name = name;
312 t.ctf_info = CTF_INFO_ENCODE(kind, 0, 0);
313 t.ctf_type = type;
315 gobuffer__add(&ctf->types, &t, sizeof(t));
316 return ++ctf->type_index;
319 uint32_t ctf__add_fwd_decl(struct ctf *ctf, uint32_t name)
321 return ctf__add_short_type(ctf, CTF_TYPE_KIND_FWD, 0, name);
324 uint32_t ctf__add_array(struct ctf *ctf, uint16_t type, uint16_t index_type, uint32_t nelems)
326 struct {
327 struct ctf_short_type t;
328 struct ctf_array a;
329 } array;
331 array.t.ctf_name = 0;
332 array.t.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_ARR, 0, 0);
333 array.t.ctf_size = 0;
334 array.a.ctf_array_type = type;
335 array.a.ctf_array_index_type = index_type;
336 array.a.ctf_array_nelems = nelems;
338 gobuffer__add(&ctf->types, &array, sizeof(array));
339 return ++ctf->type_index;
342 void ctf__add_short_member(struct ctf *ctf, uint32_t name, uint16_t type,
343 uint16_t offset, int64_t *position)
345 struct ctf_short_member m = {
346 .ctf_member_name = name,
347 .ctf_member_type = type,
348 .ctf_member_offset = offset,
351 memcpy(gobuffer__ptr(&ctf->types, *position), &m, sizeof(m));
352 *position += sizeof(m);
355 void ctf__add_full_member(struct ctf *ctf, uint32_t name, uint16_t type,
356 uint64_t offset, int64_t *position)
358 struct ctf_full_member m = {
359 .ctf_member_name = name,
360 .ctf_member_type = type,
361 .ctf_member_offset_high = offset >> 32,
362 .ctf_member_offset_low = offset & 0xffffffffl,
365 memcpy(gobuffer__ptr(&ctf->types, *position), &m, sizeof(m));
366 *position += sizeof(m);
369 uint32_t ctf__add_struct(struct ctf *ctf, uint16_t kind, uint32_t name,
370 uint64_t size, uint16_t nr_members, int64_t *position)
372 const bool is_short = size < CTF_SHORT_MEMBER_LIMIT;
373 uint32_t members_len = ((is_short ? sizeof(struct ctf_short_member) :
374 sizeof(struct ctf_full_member)) *
375 nr_members);
376 struct ctf_full_type t;
377 int len;
379 t.base.ctf_name = name;
380 t.base.ctf_info = CTF_INFO_ENCODE(kind, nr_members, 0);
381 if (size < 0xffff) {
382 len = sizeof(t.base);
383 t.base.ctf_size = size;
384 } else {
385 len = sizeof(t);
386 t.base.ctf_size = 0xffff;
387 t.ctf_size_high = size >> 32;
388 t.ctf_size_low = size & 0xffffffff;
391 gobuffer__add(&ctf->types, &t, len);
392 *position = gobuffer__allocate(&ctf->types, members_len);
393 return ++ctf->type_index;
396 void ctf__add_parameter(struct ctf *ctf, uint16_t type, int64_t *position)
398 uint16_t *parm = gobuffer__ptr(&ctf->types, *position);
400 *parm = type;
401 *position += sizeof(*parm);
404 uint32_t ctf__add_function_type(struct ctf *ctf, uint16_t type, uint16_t nr_parms,
405 bool varargs, int64_t *position)
407 struct ctf_short_type t;
408 int len = sizeof(uint16_t) * (nr_parms + !!varargs);
411 * Round up to next multiple of 4 to maintain 32-bit alignment.
413 if (len & 0x2)
414 len += 0x2;
416 t.ctf_name = 0;
417 t.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_FUNC,
418 nr_parms + !!varargs, 0);
419 t.ctf_type = type;
421 gobuffer__add(&ctf->types, &t, sizeof(t));
422 *position = gobuffer__allocate(&ctf->types, len);
423 if (varargs) {
424 unsigned int pos = *position + (nr_parms * sizeof(uint16_t));
425 uint16_t *end_of_args = gobuffer__ptr(&ctf->types, pos);
426 *end_of_args = 0;
429 return ++ctf->type_index;
432 uint32_t ctf__add_enumeration_type(struct ctf *ctf, uint32_t name, uint16_t size,
433 uint16_t nr_entries, int64_t *position)
435 struct ctf_short_type e;
437 e.ctf_name = name;
438 e.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_ENUM, nr_entries, 0);
439 e.ctf_size = size;
441 gobuffer__add(&ctf->types, &e, sizeof(e));
442 *position = gobuffer__allocate(&ctf->types,
443 nr_entries * sizeof(struct ctf_enum));
444 return ++ctf->type_index;
447 void ctf__add_enumerator(struct ctf *ctf, uint32_t name, uint32_t value,
448 int64_t *position)
450 struct ctf_enum m = {
451 .ctf_enum_name = name,
452 .ctf_enum_val = value,
455 memcpy(gobuffer__ptr(&ctf->types, *position), &m, sizeof(m));
456 *position += sizeof(m);
459 void ctf__add_function_parameter(struct ctf *ctf, uint16_t type,
460 int64_t *position)
462 uint16_t *parm = gobuffer__ptr(&ctf->funcs, *position);
464 *parm = type;
465 *position += sizeof(*parm);
468 int ctf__add_function(struct ctf *ctf, uint16_t type, uint16_t nr_parms,
469 bool varargs, int64_t *position)
471 struct ctf_short_type func;
472 int len = sizeof(uint16_t) * (nr_parms + !!varargs);
475 * Round up to next multiple of 4 to maintain 32-bit alignment.
477 if (len & 0x2)
478 len += 0x2;
480 func.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_FUNC,
481 nr_parms + !!varargs, 0);
482 func.ctf_type = type;
485 * We don't store the name for the function, it comes from the
486 * symtab.
488 gobuffer__add(&ctf->funcs, &func.ctf_info,
489 sizeof(func) - sizeof(func.ctf_name));
490 *position = gobuffer__allocate(&ctf->funcs, len);
491 if (varargs) {
492 unsigned int pos = *position + (nr_parms * sizeof(uint16_t));
493 uint16_t *end_of_args = gobuffer__ptr(&ctf->funcs, pos);
494 *end_of_args = 0;
497 return 0;
500 int ctf__add_object(struct ctf *ctf, uint16_t type)
502 return gobuffer__add(&ctf->objects, &type,
503 sizeof(type)) >= 0 ? 0 : -ENOMEM;
506 #if 0
507 static const void *ctf__compress(void *orig_buf, unsigned int *size)
509 z_stream z = {
510 .zalloc = Z_NULL,
511 .zfree = Z_NULL,
512 .opaque = Z_NULL,
513 .avail_in = *size,
514 .next_in = (Bytef *)orig_buf,
516 void *bf = NULL;
517 unsigned int bf_size = 0;
519 if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
520 goto out;
522 #define _GOBUFFER__ZCHUNK 16384 * 1024
524 do {
525 const unsigned int new_bf_size = bf_size + _GOBUFFER__ZCHUNK;
526 void *nbf = realloc(bf, new_bf_size);
528 if (nbf == NULL)
529 goto out_close_and_free;
531 bf = nbf;
532 z.avail_out = _GOBUFFER__ZCHUNK;
533 z.next_out = (Bytef *)bf + bf_size;
534 bf_size = new_bf_size;
535 if (deflate(&z, Z_FULL_FLUSH) == Z_STREAM_ERROR)
536 goto out_close_and_free;
537 #if 0
538 fprintf(stderr,
539 "%s: size=%d, bf_size=%d, total_out=%ld, total_in=%ld\n",
540 __func__, *size, bf_size, z.total_out, z.total_in);
541 #endif
542 } while (z.total_in != *size);
544 if (deflate(&z, Z_FINISH) == Z_STREAM_ERROR)
545 goto out_close_and_free;
547 deflateEnd(&z);
548 *size = z.total_out;
549 out:
550 return bf;
552 out_close_and_free:
553 deflateEnd(&z);
554 free(bf);
555 bf = NULL;
556 goto out;
559 int ctf__encode(struct ctf *ctf, uint8_t flags)
561 struct ctf_header *hdr;
562 unsigned int size;
563 void *bf = NULL;
564 int err = -1;
566 /* Empty file, nothing to do, so... done! */
567 if (gobuffer__size(&ctf->types) == 0)
568 return 0;
570 size = (gobuffer__size(&ctf->types) +
571 gobuffer__size(&ctf->objects) +
572 gobuffer__size(&ctf->funcs) +
573 strings__size(ctf->strings));
575 ctf->size = sizeof(*hdr) + size;
576 ctf->buf = malloc(ctf->size);
578 if (ctf->buf == NULL) {
579 fprintf(stderr, "%s: malloc failed!\n", __func__);
580 return -ENOMEM;
583 hdr = ctf->buf;
584 memset(hdr, 0, sizeof(*hdr));
585 hdr->ctf_magic = CTF_MAGIC;
586 hdr->ctf_version = 2;
587 hdr->ctf_flags = flags;
589 uint32_t offset = 0;
590 hdr->ctf_object_off = offset;
591 offset += gobuffer__size(&ctf->objects);
592 hdr->ctf_func_off = offset;
593 offset += gobuffer__size(&ctf->funcs);
594 hdr->ctf_type_off = offset;
595 offset += gobuffer__size(&ctf->types);
596 hdr->ctf_str_off = offset;
597 hdr->ctf_str_len = strings__size(ctf->strings);
599 void *payload = ctf->buf + sizeof(*hdr);
600 gobuffer__copy(&ctf->objects, payload + hdr->ctf_object_off);
601 gobuffer__copy(&ctf->funcs, payload + hdr->ctf_func_off);
602 gobuffer__copy(&ctf->types, payload + hdr->ctf_type_off);
603 strings__copy(ctf->strings, payload + hdr->ctf_str_off);
605 *(char *)(ctf->buf + sizeof(*hdr) + hdr->ctf_str_off) = '\0';
606 if (flags & CTF_FLAGS_COMPR) {
607 bf = (void *)ctf__compress(ctf->buf + sizeof(*hdr), &size);
608 if (bf == NULL) {
609 printf("%s: ctf__compress failed!\n", __func__);
610 return -ENOMEM;
612 void *new_bf = malloc(sizeof(*hdr) + size);
613 if (new_bf == NULL)
614 return -ENOMEM;
615 memcpy(new_bf, hdr, sizeof(*hdr));
616 memcpy(new_bf + sizeof(*hdr), bf, size);
617 free(bf);
618 bf = new_bf;
619 size += sizeof(*hdr);
620 } else {
621 bf = ctf->buf;
622 size = ctf->size;
624 #if 0
625 printf("\n\ntypes:\n entries: %d\n size: %u"
626 "\nstrings:\n size: %u\ncompressed size: %d\n",
627 ctf->type_index,
628 gobuffer__size(&ctf->types),
629 strings__size(ctf->strings), size);
630 #endif
631 int fd = open(ctf->filename, O_RDWR);
632 if (fd < 0) {
633 fprintf(stderr, "Cannot open %s\n", ctf->filename);
634 return -1;
637 if (elf_version(EV_CURRENT) == EV_NONE) {
638 fprintf(stderr, "Cannot set libelf version.\n");
639 goto out_close;
642 Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
643 if (elf == NULL) {
644 fprintf(stderr, "Cannot update ELF file.\n");
645 goto out_close;
648 elf_flagelf(elf, ELF_C_SET, ELF_F_DIRTY);
650 GElf_Ehdr ehdr_mem;
651 GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
652 if (ehdr == NULL) {
653 fprintf(stderr, "%s: elf_getehdr failed.\n", __func__);
654 goto out_close;
658 * First we look if there was already a .SUNW_ctf section to overwrite.
660 Elf_Data *data = NULL;
661 size_t strndx;
662 GElf_Shdr shdr_mem;
663 GElf_Shdr *shdr;
664 Elf_Scn *scn = NULL;
666 elf_getshdrstrndx(elf, &strndx);
668 while ((scn = elf_nextscn(elf, scn)) != NULL) {
669 shdr = gelf_getshdr(scn, &shdr_mem);
670 if (shdr == NULL)
671 continue;
672 char *secname = elf_strptr(elf, strndx, shdr->sh_name);
673 if (strcmp(secname, ".SUNW_ctf") == 0) {
674 data = elf_getdata(scn, data);
675 goto out_update;
678 /* FIXME
679 * OK, if we have the section, that is ok, we can just replace the
680 * data, if not, I made a mistake on the small amount of boilerplate
681 * below, probably .relA.ted to relocations...
683 #if 0
684 /* Now we look if the ".SUNW_ctf" string is in the strings table */
685 scn = elf_getscn(elf, strndx);
686 shdr = gelf_getshdr(scn, &shdr_mem);
688 data = elf_getdata(scn, data);
690 fprintf(stderr, "Looking for the string\n");
691 size_t ctf_name_offset = 1; /* First byte is '\0' */
692 while (ctf_name_offset < data->d_size) {
693 const char *cur_str = data->d_buf + ctf_name_offset;
695 fprintf(stderr, "*-> %s\n", cur_str);
696 if (strcmp(cur_str, ".SUNW_ctf") == 0)
697 goto found_SUNW_ctf_str;
699 ctf_name_offset += strlen(cur_str) + 1;
702 /* Add the section name */
703 const size_t ctf_name_len = strlen(".SUNW_ctf") + 1;
704 char *new_strings_table = malloc(data->d_size + ctf_name_len);
705 if (new_strings_table == NULL)
706 goto out_close;
708 memcpy(new_strings_table, data->d_buf, data->d_size);
709 strcpy(new_strings_table + data->d_size, ".SUNW_ctf");
710 ctf_name_offset = data->d_size;
711 data->d_size += ctf_name_len;
712 data->d_buf = new_strings_table;
713 elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
714 elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
716 Elf_Scn *newscn;
717 found_SUNW_ctf_str:
718 newscn = elf_newscn(elf);
719 if (newscn == NULL)
720 goto out_close;
722 data = elf_newdata(newscn);
723 if (data == NULL)
724 goto out_close;
726 shdr = gelf_getshdr(newscn, &shdr_mem);
727 shdr->sh_name = ctf_name_offset;
728 shdr->sh_type = SHT_PROGBITS;
729 gelf_update_shdr(newscn, &shdr_mem);
730 elf_flagshdr(newscn, ELF_C_SET, ELF_F_DIRTY);
731 #else
732 char pathname[PATH_MAX];
733 snprintf(pathname, sizeof(pathname), "%s.SUNW_ctf", ctf->filename);
734 fd = creat(pathname, S_IRUSR | S_IWUSR);
735 if (fd == -1) {
736 fprintf(stderr, "%s: open(%s) failed!\n", __func__, pathname);
737 goto out_close;
739 if (write(fd, bf, size) != size)
740 goto out_close;
742 if (close(fd) < 0)
743 goto out_unlink;
745 char cmd[PATH_MAX * 2];
746 snprintf(cmd, sizeof(cmd), "objcopy --add-section .SUNW_ctf=%s %s",
747 pathname, ctf->filename);
748 if (system(cmd) == 0)
749 err = 0;
750 out_unlink:
751 unlink(pathname);
752 return err;
753 #endif
754 out_update:
755 data->d_buf = bf;
756 data->d_size = size;
757 elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
759 if (elf_update(elf, ELF_C_NULL) < 0)
760 goto out_close;
761 if (elf_update(elf, ELF_C_WRITE) < 0)
762 goto out_close;
764 elf_end(elf);
765 err = 0;
766 out_close:
767 if (bf != ctf->buf)
768 free(bf);
769 close(fd);
770 return err;
772 #endif