diff --git a/CMakeLists.txt b/CMakeLists.txt index ca32728..08e24bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ find_package(ZLIB REQUIRED) _set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}${CMAKE_INSTALL_PREFIX}/${__LIB}" "libdir") -set(dwarves_LIB_SRCS dwarves.c gobuffer strings ctf_loader.c libctf.c dwarf_loader.c dutil.c) +set(dwarves_LIB_SRCS dwarves.c gobuffer strings ctf_encoder.c ctf_loader.c libctf.c dwarf_loader.c dutil.c) add_library(dwarves SHARED ${dwarves_LIB_SRCS}) set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1) target_link_libraries(dwarves ${DWARF_LIBRARIES} ${ZLIB_LIBRARIES}) diff --git a/ctf_encoder.c b/ctf_encoder.c new file mode 100644 index 0000000..3763415 --- /dev/null +++ b/ctf_encoder.c @@ -0,0 +1,219 @@ +/* + Copyright (C) 2009 Red Hat Inc. + Copyright (C) 2009 Arnaldo Carvalho de Melo + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. +*/ + +#include "dwarves.h" +#include "libctf.h" +#include "ctf.h" + +static int tag__check_id_drift(const struct tag *self, + uint16_t core_id, uint16_t ctf_id) +{ + if (ctf_id != core_id) { + fprintf(stderr, "%s: %s id drift, core: %u, libctf: %d\n", + __func__, dwarf_tag_name(self->tag), core_id, ctf_id); + return -1; + } + return 0; +} + +static int dwarf_to_ctf_type(uint16_t tag) +{ + switch (tag) { + case DW_TAG_const_type: return CTF_TYPE_KIND_CONST; + case DW_TAG_pointer_type: return CTF_TYPE_KIND_PTR; + case DW_TAG_restrict_type: return CTF_TYPE_KIND_RESTRICT; + case DW_TAG_volatile_type: return CTF_TYPE_KIND_VOLATILE; + case DW_TAG_class_type: + case DW_TAG_structure_type: return CTF_TYPE_KIND_STR; + case DW_TAG_union_type: return CTF_TYPE_KIND_UNION; + } + return 0xffff; +} + +static int base_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + struct base_type *bt = tag__base_type(self); + int ctf_id = ctf__add_base_type(ctf, bt->name, bt->bit_size); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + return 0; +} + +static int pointer_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + int ctf_id = ctf__add_short_type(ctf, dwarf_to_ctf_type(self->tag), + self->type, 0); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + return 0; +} + +static int typedef__encode(struct tag *self, uint16_t core_id, struct ctf *ctf) +{ + int ctf_id = ctf__add_short_type(ctf, CTF_TYPE_KIND_TYPDEF, self->type, + tag__namespace(self)->name); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + return 0; +} + +static int fwd_decl__encode(struct tag *self, uint16_t core_id, struct ctf *ctf) +{ + int ctf_id = ctf__add_fwd_decl(ctf, tag__namespace(self)->name); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + return 0; +} + +static int structure_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + struct type *type = tag__type(self); + int64_t position; + int ctf_id = ctf__add_struct(ctf, dwarf_to_ctf_type(self->tag), + type->namespace.name, type->size, + type->nr_members, &position); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + const bool is_short = type->size < CTF_SHORT_MEMBER_LIMIT; + struct class_member *pos; + type__for_each_member(type, pos) { + if (is_short) + ctf__add_short_member(ctf, pos->name, pos->tag.type, + pos->bit_offset, &position); + else + ctf__add_full_member(ctf, pos->name, pos->tag.type, + pos->bit_offset, &position); + } + + return 0; +} + +static uint32_t array_type__nelems(struct tag *self) +{ + int i; + uint32_t nelem = 1; + struct array_type *array = tag__array_type(self); + + for (i = array->dimensions - 1; i >= 0; --i) + nelem *= array->nr_entries[i]; + + return nelem; +} + +static int array_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + const uint32_t nelems = array_type__nelems(self); + int ctf_id = ctf__add_array(ctf, self->type, 0, nelems); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + return 0; +} + +static int subroutine_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + struct parameter *pos; + int64_t position; + struct ftype *ftype = tag__ftype(self); + int ctf_id = ctf__add_function_type(ctf, self->type, ftype->nr_parms, + &position); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + ftype__for_each_parameter(ftype, pos) + ctf__add_parameter(ctf, pos->tag.type, &position); + + return 0; +} + +static int enumeration_type__encode(struct tag *self, uint16_t core_id, + struct ctf *ctf) +{ + struct type *etype = tag__type(self); + int64_t position; + int ctf_id = ctf__add_enumeration_type(ctf, etype->namespace.name, + etype->nr_members, &position); + + if (ctf_id < 0 || tag__check_id_drift(self, core_id, ctf_id)) + return -1; + + struct enumerator *pos; + type__for_each_enumerator(etype, pos) + ctf__add_enumerator(ctf, pos->name, pos->value, &position); + + return 0; +} + +static void tag__encode_ctf(struct tag *self, uint16_t core_id, struct ctf *ctf) +{ + switch (self->tag) { + case DW_TAG_base_type: + base_type__encode(self, core_id, ctf); + break; + case DW_TAG_const_type: + case DW_TAG_pointer_type: + case DW_TAG_restrict_type: + case DW_TAG_volatile_type: + pointer_type__encode(self, core_id, ctf); + break; + case DW_TAG_typedef: + typedef__encode(self, core_id, ctf); + break; + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + if (tag__type(self)->declaration) + fwd_decl__encode(self, core_id, ctf); + else + structure_type__encode(self, core_id, ctf); + break; + case DW_TAG_array_type: + array_type__encode(self, core_id, ctf); + break; + case DW_TAG_subroutine_type: + subroutine_type__encode(self, core_id, ctf); + break; + case DW_TAG_enumeration_type: + enumeration_type__encode(self, core_id, ctf); + break; + } +} + +int cu__encode_ctf(struct cu *self) +{ + struct ctf *ctf = ctf__new(self->filename, NULL, 0); + + ctf__set_strings(ctf, &strings->gb); + + uint16_t id; + struct tag *pos; + cu__for_each_type(self, id, pos) + tag__encode_ctf(pos, id, ctf); + + ctf__encode(ctf, CTF_FLAGS_COMPR); + + return 0; +} diff --git a/ctf_encoder.h b/ctf_encoder.h new file mode 100644 index 0000000..b06ffbc --- /dev/null +++ b/ctf_encoder.h @@ -0,0 +1,16 @@ +#ifndef _CTF_ENCODER_H_ +#define _CTF_ENCODER_H_ 1 +/* + Copyright (C) 2009 Red Hat Inc. + Copyright (C) 2009 Arnaldo Carvalho de Melo + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. +*/ + +struct cu; + +int cu__encode_ctf(struct cu *self); + +#endif /* _CTF_ENCODER_H_ */ diff --git a/ctf_loader.c b/ctf_loader.c index 522ee72..bb8cf99 100644 --- a/ctf_loader.c +++ b/ctf_loader.c @@ -131,7 +131,7 @@ static void elf_symbol_iterate(struct ctf_state *sp, } #endif -static int parse_elf(struct ctf_state *sp, int *wordsizep) +static int parse_elf(struct ctf_state *sp, const char *filename, int *wordsizep) { GElf_Ehdr ehdr; GElf_Shdr shdr; @@ -153,7 +153,7 @@ static int parse_elf(struct ctf_state *sp, int *wordsizep) return -1; } - sp->ctf = ctf__new(sp->cu->filename, data->d_buf, data->d_size); + sp->ctf = ctf__new(filename, data->d_buf, data->d_size); if (!sp->ctf) { fprintf(stderr, "Cannot initialize CTF state.\n"); return -1; @@ -818,6 +818,8 @@ static int class__fixup_ctf_bitfields(struct tag *self, struct cu *cu) pos->byte_size = integral_bit_size / 8; if (integral_bit_size == 0 || type_bit_size == integral_bit_size) { + if (integral_bit_size == 0) + fprintf(stderr, "boo!\n"); pos->bit_size = integral_bit_size; continue; } @@ -867,13 +869,13 @@ int ctf__load(struct cus *self, struct conf_load *conf, const char *filename) return -1; } + if (parse_elf(&state, filename, &wordsize)) + return -1; + state.cu = cu__new(filename, wordsize, NULL, 0, filename); if (state.cu == NULL) oom("cu__new"); - if (parse_elf(&state, &wordsize)) - return -1; - dump_ctf(&state); elf_end(state.elf); diff --git a/dwarf_loader.c b/dwarf_loader.c index 5a854df..d058c7a 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -551,14 +551,13 @@ static struct class_member *class_member__new(Dwarf_Die *die, struct cu *cu) tag__init(&self->tag, die); self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->byte_offset = attr_offset(die, DW_AT_data_member_location); - self->bit_offset = self->byte_offset * 8 + self->bitfield_offset; /* * Will be cached later, in class_member__cache_byte_size */ self->byte_size = 0; self->bitfield_offset = attr_numeric(die, DW_AT_bit_offset); self->bitfield_size = attr_numeric(die, DW_AT_bit_size); - if (self->bitfield_size != 0) + self->bit_offset = self->byte_offset * 8 + self->bitfield_offset; /* * We may need to recode the type, possibly creating a suitably * sized new base_type @@ -1306,6 +1305,11 @@ static void namespace__recode_dwarf_types(struct tag *self, struct cu *cu) } switch (pos->tag) { + case DW_TAG_member: + /* Check if this is an already recoded bitfield */ + if (pos->type != 0) + continue; + break; case DW_TAG_subroutine_type: case DW_TAG_subprogram: ftype__recode_dwarf_types(pos, cu); @@ -1705,8 +1709,42 @@ static void die__process(Dwarf_Die *die, struct cu *cu) static int class_member__cache_byte_size(struct tag *self, struct cu *cu, void *cookie __unused) { - if (self->tag == DW_TAG_member || self->tag == DW_TAG_inheritance) - tag__class_member(self)->byte_size = tag__size(self, cu); + if (self->tag == DW_TAG_member || self->tag == DW_TAG_inheritance) { + struct class_member *member; + + if (member->bitfield_size != 0) { + struct tag *type = tag__follow_typedef(&member->tag, cu); + uint16_t type_bit_size; + size_t integral_bit_size; + + if (tag__is_enumeration(type)) { + type_bit_size = tag__type(type)->size; + integral_bit_size = sizeof(int) * 8; /* FIXME: always this size? */ + } else { + struct base_type *bt = tag__base_type(type); + type_bit_size = bt->bit_size; + integral_bit_size = base_type__name_to_size(bt, cu); + } + /* + * XXX: integral_bit_size can be zero if base_type__name_to_size doesn't + * know about the base_type name, so one has to add there when + * such base_type isn't found. pahole will put zero on the + * struct output so it should be easy to spot the name when + * such unlikely thing happens. + */ + member->byte_size = integral_bit_size / 8; + + if (integral_bit_size == 0 || type_bit_size == integral_bit_size) { + member->bit_size = integral_bit_size; + return 0; + } + + member->bit_size = type_bit_size; + } else { + member->byte_size = tag__size(self, cu); + member->bit_size = member->byte_size * 8; + } + } return 0; } @@ -1738,6 +1776,7 @@ static int cus__load_module(struct cus *self, struct conf_load *conf, oom("cu__new"); cu->extra_dbg_info = conf ? conf->extra_dbg_info : 0; die__process(cu_die, cu); + base_type_name_to_size_table__init(); cu__for_all_tags(cu, class_member__cache_byte_size, NULL); off = noff; if (conf && conf->steal) { diff --git a/libctf.c b/libctf.c index 6198cff..889fd7b 100644 --- a/libctf.c +++ b/libctf.c @@ -1,18 +1,25 @@ -#include +#include +#include #include #include +#include #include +#include #include #include "libctf.h" #include "ctf.h" #include "dutil.h" +#include "gobuffer.h" struct ctf { - void *buf; - size_t size; - int swapped; + void *buf; + struct gobuffer types; + struct gobuffer *strings; const char *filename; + size_t size; + int swapped; + unsigned int type_index; }; uint16_t ctf__get16(struct ctf *self, uint16_t *p) @@ -169,3 +176,280 @@ size_t ctf__get_size(struct ctf *self) { return self->size; } + +void ctf__set_strings(struct ctf *self, struct gobuffer *strings) +{ + self->strings = strings; +} + +int ctf__add_base_type(struct ctf *self, uint32_t name, uint16_t size) +{ + struct ctf_full_type t; + + t.base.ctf_name = name; + t.base.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_INT, 0, 0); + t.base.ctf_size = size; + t.ctf_size_high = CTF_TYPE_INT_ENCODE(0, 0, size); + + gobuffer__add(&self->types, &t, sizeof(t) - sizeof(uint32_t)); + return ++self->type_index; +} + +int ctf__add_short_type(struct ctf *self, uint16_t kind, uint16_t type, + uint32_t name) +{ + struct ctf_short_type t; + + t.ctf_name = name; + t.ctf_info = CTF_INFO_ENCODE(kind, 0, 0); + t.ctf_type = type; + + gobuffer__add(&self->types, &t, sizeof(t)); + return ++self->type_index; +} + +int ctf__add_fwd_decl(struct ctf *self, uint32_t name) +{ + return ctf__add_short_type(self, CTF_TYPE_KIND_FWD, 0, name); +} + +int ctf__add_array(struct ctf *self, uint16_t type, uint16_t index_type, + uint32_t nelems) +{ + struct { + struct ctf_short_type t; + struct ctf_array a; + } array; + + array.t.ctf_name = 0; + array.t.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_ARR, 0, 0); + array.t.ctf_size = 0; + array.a.ctf_array_type = type; + array.a.ctf_array_index_type = index_type; + array.a.ctf_array_nelems = nelems; + + gobuffer__add(&self->types, &array, sizeof(array)); + return ++self->type_index; +} + +void ctf__add_short_member(struct ctf *self, uint32_t name, uint16_t type, + uint16_t offset, int64_t *position) +{ + struct ctf_short_member m = { + .ctf_member_name = name, + .ctf_member_type = type, + .ctf_member_offset = offset, + }; + + memcpy(gobuffer__ptr(&self->types, *position), &m, sizeof(m)); + *position += sizeof(m); +} + +void ctf__add_full_member(struct ctf *self, uint32_t name, uint16_t type, + uint64_t offset, int64_t *position) +{ + struct ctf_full_member m = { + .ctf_member_name = name, + .ctf_member_type = type, + .ctf_member_offset_high = offset >> 32, + .ctf_member_offset_low = offset & 0xffffffffl, + }; + + memcpy(gobuffer__ptr(&self->types, *position), &m, sizeof(m)); + *position += sizeof(m); +} + +int ctf__add_struct(struct ctf *self, uint16_t kind, uint32_t name, + uint64_t size, uint16_t nr_members, int64_t *position) +{ + const bool is_short = size < CTF_SHORT_MEMBER_LIMIT; + uint32_t members_len = ((is_short ? sizeof(struct ctf_short_member) : + sizeof(struct ctf_full_member)) * + nr_members); + struct ctf_full_type t; + int len; + + t.base.ctf_name = name; + t.base.ctf_info = CTF_INFO_ENCODE(kind, nr_members, 0); + if (size < 0xffff) { + len = sizeof(t.base); + t.base.ctf_size = size; + } else { + len = sizeof(t); + t.base.ctf_size = 0xffff; + t.ctf_size_high = size >> 32; + t.ctf_size_low = size & 0xffffffff; + } + + gobuffer__add(&self->types, &t, len); + *position = gobuffer__allocate(&self->types, members_len); + return ++self->type_index; +} + +void ctf__add_parameter(struct ctf *self, uint16_t type, int64_t *position) +{ + uint16_t *parm = gobuffer__ptr(&self->types, *position); + + *parm = type; + *position += sizeof(*parm); +} + +int ctf__add_function_type(struct ctf *self, uint16_t type, uint16_t nr_parms, + int64_t *position) +{ + struct ctf_short_type t; + int len = sizeof(uint16_t) * nr_parms; + + /* + * Round up to next multiple of 4 to maintain 32-bit alignment. + */ + if (len & 0x2) + len += 0x2; + + t.ctf_name = 0; + t.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_FUNC, nr_parms, 0); + t.ctf_type = type; + + gobuffer__add(&self->types, &t, sizeof(t)); + *position = gobuffer__allocate(&self->types, len); + return ++self->type_index; +} + +int ctf__add_enumeration_type(struct ctf *self, uint32_t name, + uint16_t nr_entries, int64_t *position) +{ + struct ctf_short_type e; + + e.ctf_name = name; + e.ctf_info = CTF_INFO_ENCODE(CTF_TYPE_KIND_ENUM, nr_entries, 0); + e.ctf_size = 0; + + gobuffer__add(&self->types, &e, sizeof(e)); + *position = gobuffer__allocate(&self->types, + nr_entries * sizeof(struct ctf_enum)); + return ++self->type_index; +} + +void ctf__add_enumerator(struct ctf *self, uint32_t name, uint32_t value, + int64_t *position) +{ + struct ctf_enum m = { + .ctf_enum_name = name, + .ctf_enum_val = value, + }; + + memcpy(gobuffer__ptr(&self->types, *position), &m, sizeof(m)); + *position += sizeof(m); +} + +static const void *ctf__compress(void *orig_buf, unsigned int *size) +{ + z_stream z = { + .zalloc = Z_NULL, + .zfree = Z_NULL, + .opaque = Z_NULL, + .avail_in = *size, + .next_in = (Bytef *)orig_buf, + }; + void *bf = NULL; + unsigned int bf_size = 0; + + if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK) + goto out; + +#define _GOBUFFER__ZCHUNK 16384 * 1024 + + do { + const unsigned int new_bf_size = bf_size + _GOBUFFER__ZCHUNK; + void *nbf = realloc(bf, new_bf_size); + + if (nbf == NULL) + goto out_close_and_free; + + bf = nbf; + z.avail_out = _GOBUFFER__ZCHUNK; + z.next_out = (Bytef *)bf + bf_size; + bf_size = new_bf_size; + if (deflate(&z, Z_FULL_FLUSH) == Z_STREAM_ERROR) + goto out_close_and_free; + printf("%s: size=%d, bf_size=%d, total_out=%ld, total_in=%ld\n", __func__, *size, bf_size, z.total_out, z.total_in); + } while (z.total_in != *size); + + if (deflate(&z, Z_FINISH) == Z_STREAM_ERROR) + goto out_close_and_free; + + deflateEnd(&z); + *size = z.total_out; +out: + return bf; + +out_close_and_free: + deflateEnd(&z); + free(bf); + bf = NULL; + goto out; +} + +int ctf__encode(struct ctf *self, uint8_t flags) +{ + struct ctf_header *hdr; + unsigned int size; + const void *bf; + int fd; + + size = gobuffer__size(&self->types) + gobuffer__size(self->strings); + self->size = sizeof(*hdr) + size; + self->buf = malloc(self->size); + + if (self->buf == NULL) { + printf("%s: malloc failed!\n", __func__); + return -ENOMEM; + } + + hdr = self->buf; + memset(hdr, 0, sizeof(*hdr)); + hdr->ctf_magic = CTF_MAGIC; + hdr->ctf_version = 2; + hdr->ctf_flags = flags; + hdr->ctf_type_off = 0; + hdr->ctf_str_off = gobuffer__size(&self->types); + hdr->ctf_str_len = gobuffer__size(self->strings); + + memcpy(self->buf + sizeof(*hdr) + hdr->ctf_type_off, + gobuffer__entries(&self->types), + gobuffer__size(&self->types)); + memcpy(self->buf + sizeof(*hdr) + hdr->ctf_str_off, + gobuffer__entries(self->strings), + gobuffer__size(self->strings)); + + *(char *)(self->buf + sizeof(*hdr) + hdr->ctf_str_off) = '\0'; + if (flags & CTF_FLAGS_COMPR) { + bf = ctf__compress(self->buf + sizeof(*hdr), &size); + if (bf == NULL) { + printf("%s: ctf__compress failed!\n", __func__); + return -ENOMEM; + } + } else { + bf = self->buf; + size = self->size; + } + + printf("\n\ntypes:\n entries: %d\n size: %u" + "\nstrings:\n entries: %u\n size: %u\ncompressed size: %d\n", + self->type_index, + gobuffer__size(&self->types), + gobuffer__nr_entries(self->strings), + gobuffer__size(self->strings), size); + + char pathname[PATH_MAX]; + snprintf(pathname, sizeof(pathname), "%s.SUNW_ctf", self->filename); + fd = creat(pathname, S_IRUSR | S_IWUSR); + if (fd == -1) { + fprintf(stderr, "%s: open(%s) failed!\n", __func__, pathname); + return -1; + } + write(fd, hdr, sizeof(*hdr)); + write(fd, bf, size); + close(fd); + return 0; +} diff --git a/libctf.h b/libctf.h index 2eda20c..9f168fc 100644 --- a/libctf.h +++ b/libctf.h @@ -1,7 +1,9 @@ #ifndef _LIBCTF_H #define _LIBCTF_H +#include #include +#include struct ctf *ctf__new(const char *filename, void *buf, size_t size); void ctf__delete(struct ctf *ctf); @@ -14,4 +16,29 @@ void ctf__put32(struct ctf *self, uint32_t *p, uint32_t val); void *ctf__get_buffer(struct ctf *self); size_t ctf__get_size(struct ctf *self); +int ctf__add_base_type(struct ctf *self, uint32_t name, uint16_t size); +int ctf__add_fwd_decl(struct ctf *self, uint32_t name); +int ctf__add_short_type(struct ctf *self, uint16_t kind, uint16_t type, + uint32_t name); +void ctf__add_short_member(struct ctf *self, uint32_t name, uint16_t type, + uint16_t offset, int64_t *position); +void ctf__add_full_member(struct ctf *self, uint32_t name, uint16_t type, + uint64_t offset, int64_t *position); +int ctf__add_struct(struct ctf *self, uint16_t kind, uint32_t name, + uint64_t size, uint16_t nr_members, int64_t *position); +int ctf__add_array(struct ctf *self, uint16_t type, uint16_t index_type, + uint32_t nelems); +void ctf__add_parameter(struct ctf *self, uint16_t type, int64_t *position); +int ctf__add_function_type(struct ctf *self, uint16_t type, + uint16_t nr_parameters, int64_t *position); +int ctf__add_enumeration_type(struct ctf *self, uint32_t name, + uint16_t nr_entries, int64_t *position); +void ctf__add_enumerator(struct ctf *self, uint32_t name, uint32_t value, + int64_t *position); + +struct gobuffer; + +void ctf__set_strings(struct ctf *self, struct gobuffer *strings); +int ctf__encode(struct ctf *self, uint8_t flags); + #endif /* _LIBCTF_H */ diff --git a/pahole.c b/pahole.c index aa52631..a63b9ff 100644 --- a/pahole.c +++ b/pahole.c @@ -20,6 +20,9 @@ #include "dwarves_reorganize.h" #include "dwarves.h" #include "dutil.h" +#include "ctf_encoder.h" + +static bool ctf_encode; static uint8_t class__include_anonymous; static uint8_t class__include_nested_anonymous; @@ -886,6 +889,11 @@ static const struct argp_option pahole__options[] = { .arg = "WORD_SIZE", .doc = "change the arch word size to WORD_SIZE" }, + { + .name = "ctf_encode", + .key = 'Z', + .doc = "Encode as CTF", + }, { .name = NULL, } @@ -953,6 +961,9 @@ static error_t pahole__options_parser(int key, char *arg, if (!global_verbose) formatter = class_name_formatter; break; + case 'Z': + ctf_encode = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -996,6 +1007,16 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, if (!cu__filter(cu)) goto dump_it; + if (ctf_encode) { + cu__encode_ctf(cu); + /* + * We still have to get the type signature code merged to eliminate + * dups, reference another CTF file, etc, so for now just encode the + * first cu that is let thru by cu__filter. + */ + goto dump_and_stop; + } + if (defined_in) { if (class_sname == 0) class_sname = strings__find(strings, class_name); @@ -1097,7 +1118,7 @@ static enum load_steal_kind pahole_stealer(struct cu *cu, tag__fprintf(class, cu, &conf, stdout); putchar('\n'); } - +dump_and_stop: cu__delete(cu); return LSK__STOP_LOADING; dump_it: