|
Packit |
b92951 |
/* ctfdump.c: CTF dumper.
|
|
Packit |
b92951 |
*
|
|
Packit |
b92951 |
* Copyright (C) 2008 David S. Miller <davem@davemloft.net>
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
#include <sys/types.h>
|
|
Packit |
b92951 |
#include <sys/stat.h>
|
|
Packit |
b92951 |
#include <errno.h>
|
|
Packit |
b92951 |
#include <fcntl.h>
|
|
Packit |
b92951 |
#include <stdio.h>
|
|
Packit |
b92951 |
#include <unistd.h>
|
|
Packit |
b92951 |
#include <stdlib.h>
|
|
Packit |
b92951 |
#include <stddef.h>
|
|
Packit |
b92951 |
#include <malloc.h>
|
|
Packit |
b92951 |
#include <string.h>
|
|
Packit |
b92951 |
#include <limits.h>
|
|
Packit |
b92951 |
#include <libgen.h>
|
|
Packit |
b92951 |
#include <zlib.h>
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
#include <gelf.h>
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
#include "libctf.h"
|
|
Packit |
b92951 |
#include "ctf.h"
|
|
Packit |
b92951 |
#include "dutil.h"
|
|
Packit |
b92951 |
#include "dwarves.h"
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
/*
|
|
Packit |
b92951 |
* FIXME: We should just get the table from the CTF ELF section
|
|
Packit |
b92951 |
* and use it directly
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
extern struct strings *strings;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static void *tag__alloc(const size_t size)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct tag *tag = zalloc(size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (tag != NULL)
|
|
Packit |
b92951 |
tag->top_level = 1;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return tag;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int ctf__load_ftype(struct ctf *ctf, struct ftype *proto, uint16_t tag,
|
|
Packit |
b92951 |
uint16_t type, uint16_t vlen, uint16_t *args, long id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
proto->tag.tag = tag;
|
|
Packit |
b92951 |
proto->tag.type = type;
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&proto->parms);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
int i;
|
|
Packit |
b92951 |
for (i = 0; i < vlen; i++) {
|
|
Packit |
b92951 |
uint16_t type = ctf__get16(ctf, &args[i]);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (type == 0)
|
|
Packit |
b92951 |
proto->unspec_parms = 1;
|
|
Packit |
b92951 |
else {
|
|
Packit |
b92951 |
struct parameter *p = tag__alloc(sizeof(*p));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (p == NULL)
|
|
Packit |
b92951 |
goto out_free_parameters;
|
|
Packit |
b92951 |
p->tag.tag = DW_TAG_formal_parameter;
|
|
Packit |
b92951 |
p->tag.type = ctf__get16(ctf, &args[i]);
|
|
Packit |
b92951 |
ftype__add_parameter(proto, p);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
vlen *= sizeof(*args);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
/* Round up to next multiple of 4 to maintain
|
|
Packit |
b92951 |
* 32-bit alignment.
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
if (vlen & 0x2)
|
|
Packit |
b92951 |
vlen += 0x2;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (id < 0) {
|
|
Packit |
b92951 |
uint32_t type_id;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu__add_tag(ctf->priv, &proto->tag, &type_id);
|
|
Packit |
b92951 |
} else {
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &proto->tag, id);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return vlen;
|
|
Packit |
b92951 |
out_free_parameters:
|
|
Packit |
b92951 |
ftype__delete(proto, ctf->priv);
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct function *function__new(uint16_t **ptr, GElf_Sym *sym,
|
|
Packit |
b92951 |
struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct function *func = tag__alloc(sizeof(*func));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (func != NULL) {
|
|
Packit |
b92951 |
func->lexblock.ip.addr = elf_sym__value(sym);
|
|
Packit |
b92951 |
func->lexblock.size = elf_sym__size(sym);
|
|
Packit |
b92951 |
func->name = sym->st_name;
|
|
Packit |
b92951 |
func->vtable_entry = -1;
|
|
Packit |
b92951 |
func->external = elf_sym__bind(sym) == STB_GLOBAL;
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&func->vtable_node);
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&func->tool_node);
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&func->lexblock.tags);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
uint16_t val = ctf__get16(ctf, *ptr);
|
|
Packit |
b92951 |
uint16_t tag = CTF_GET_KIND(val);
|
|
Packit |
b92951 |
uint16_t vlen = CTF_GET_VLEN(val);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
++*ptr;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (tag != CTF_TYPE_KIND_FUNC) {
|
|
Packit |
b92951 |
fprintf(stderr,
|
|
Packit |
b92951 |
"%s: Expected function type, got %u\n",
|
|
Packit |
b92951 |
__func__, tag);
|
|
Packit |
b92951 |
goto out_delete;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
uint16_t type = ctf__get16(ctf, *ptr);
|
|
Packit |
b92951 |
long id = -1; /* FIXME: not needed for funcs... */
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
++*ptr;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (ctf__load_ftype(ctf, &func->proto, DW_TAG_subprogram,
|
|
Packit |
b92951 |
type, vlen, *ptr, id) < 0)
|
|
Packit |
b92951 |
return NULL;
|
|
Packit |
b92951 |
/*
|
|
Packit |
b92951 |
* Round up to next multiple of 4 to maintain 32-bit alignment.
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
if (vlen & 0x1)
|
|
Packit |
b92951 |
++vlen;
|
|
Packit |
b92951 |
*ptr += vlen;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return func;
|
|
Packit |
b92951 |
out_delete:
|
|
Packit |
b92951 |
free(func);
|
|
Packit |
b92951 |
return NULL;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int ctf__load_funcs(struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_header *hp = ctf__get_buffer(ctf);
|
|
Packit |
b92951 |
uint16_t *func_ptr = (ctf__get_buffer(ctf) + sizeof(*hp) +
|
|
Packit |
b92951 |
ctf__get32(ctf, &hp->ctf_func_off));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
GElf_Sym sym;
|
|
Packit |
b92951 |
uint32_t idx;
|
|
Packit |
b92951 |
ctf__for_each_symtab_function(ctf, idx, sym)
|
|
Packit |
b92951 |
if (function__new(&func_ptr, &sym, ctf) == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct base_type *base_type__new(strings_t name, uint32_t attrs,
|
|
Packit |
b92951 |
uint8_t float_type, size_t size)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct base_type *bt = tag__alloc(sizeof(*bt));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (bt != NULL) {
|
|
Packit |
b92951 |
bt->name = name;
|
|
Packit |
b92951 |
bt->bit_size = size;
|
|
Packit |
b92951 |
bt->is_signed = attrs & CTF_TYPE_INT_SIGNED;
|
|
Packit |
b92951 |
bt->is_bool = attrs & CTF_TYPE_INT_BOOL;
|
|
Packit |
b92951 |
bt->is_varargs = attrs & CTF_TYPE_INT_VARARGS;
|
|
Packit |
b92951 |
bt->name_has_encoding = false;
|
|
Packit |
b92951 |
bt->float_type = float_type;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
return bt;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static void type__init(struct type *type, uint16_t tag,
|
|
Packit |
b92951 |
strings_t name, size_t size)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&type->node);
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&type->namespace.tags);
|
|
Packit |
b92951 |
type->size = size;
|
|
Packit |
b92951 |
type->namespace.tag.tag = tag;
|
|
Packit |
b92951 |
type->namespace.name = name;
|
|
Packit |
b92951 |
type->namespace.sname = 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct type *type__new(uint16_t tag, strings_t name, size_t size)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct type *type = tag__alloc(sizeof(*type));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (type != NULL)
|
|
Packit |
b92951 |
type__init(type, tag, name, size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return type;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct class *class__new(strings_t name, size_t size)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct class *class = tag__alloc(sizeof(*class));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (class != NULL) {
|
|
Packit |
b92951 |
type__init(&class->type, DW_TAG_structure_type, name, size);
|
|
Packit |
b92951 |
INIT_LIST_HEAD(&class->vtable);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return class;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_base_type(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
struct ctf_full_type *tp, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
uint32_t *enc = ptr;
|
|
Packit |
b92951 |
uint32_t eval = ctf__get32(ctf, enc);
|
|
Packit |
b92951 |
uint32_t attrs = CTF_TYPE_INT_ATTRS(eval);
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
struct base_type *base = base_type__new(name, attrs, 0,
|
|
Packit |
b92951 |
CTF_TYPE_INT_BITS(eval));
|
|
Packit |
b92951 |
if (base == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
base->tag.tag = DW_TAG_base_type;
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &base->tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return sizeof(*enc);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_base_type_float(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
uint32_t *enc = ptr, eval = ctf__get32(ctf, enc);
|
|
Packit |
b92951 |
struct base_type *base = base_type__new(name, 0, eval,
|
|
Packit |
b92951 |
CTF_TYPE_FP_BITS(eval));
|
|
Packit |
b92951 |
if (base == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
base->tag.tag = DW_TAG_base_type;
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &base->tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return sizeof(*enc);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_array(struct ctf *ctf, void *ptr, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_array *ap = ptr;
|
|
Packit |
b92951 |
struct array_type *array = tag__alloc(sizeof(*array));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (array == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
/* FIXME: where to get the number of dimensions?
|
|
Packit |
b92951 |
* it it flattened? */
|
|
Packit |
b92951 |
array->dimensions = 1;
|
|
Packit |
b92951 |
array->nr_entries = malloc(sizeof(uint32_t));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (array->nr_entries == NULL) {
|
|
Packit |
b92951 |
free(array);
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
array->nr_entries[0] = ctf__get32(ctf, &ap->ctf_array_nelems);
|
|
Packit |
b92951 |
array->tag.tag = DW_TAG_array_type;
|
|
Packit |
b92951 |
array->tag.type = ctf__get16(ctf, &ap->ctf_array_type);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &array->tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return sizeof(*ap);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_subroutine_type(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
uint16_t *args = ptr;
|
|
Packit |
b92951 |
unsigned int type = ctf__get16(ctf, &tp->base.ctf_type);
|
|
Packit |
b92951 |
struct ftype *proto = tag__alloc(sizeof(*proto));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (proto == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
vlen = ctf__load_ftype(ctf, proto, DW_TAG_subroutine_type,
|
|
Packit |
b92951 |
type, vlen, args, id);
|
|
Packit |
b92951 |
return vlen < 0 ? -ENOMEM : vlen;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_full_members(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct type *class)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_full_member *mp = ptr;
|
|
Packit |
b92951 |
int i;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
for (i = 0; i < vlen; i++) {
|
|
Packit |
b92951 |
struct class_member *member = zalloc(sizeof(*member));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (member == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
member->tag.tag = DW_TAG_member;
|
|
Packit |
b92951 |
member->tag.type = ctf__get16(ctf, &mp[i].ctf_member_type);
|
|
Packit |
b92951 |
member->name = ctf__get32(ctf, &mp[i].ctf_member_name);
|
|
Packit |
b92951 |
member->bit_offset = (ctf__get32(ctf, &mp[i].ctf_member_offset_high) << 16) |
|
|
Packit |
b92951 |
ctf__get32(ctf, &mp[i].ctf_member_offset_low);
|
|
Packit |
b92951 |
/* sizes and offsets will be corrected at class__fixup_ctf_bitfields */
|
|
Packit |
b92951 |
type__add_member(class, member);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return sizeof(*mp);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_short_members(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct type *class)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_short_member *mp = ptr;
|
|
Packit |
b92951 |
int i;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
for (i = 0; i < vlen; i++) {
|
|
Packit |
b92951 |
struct class_member *member = zalloc(sizeof(*member));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (member == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
member->tag.tag = DW_TAG_member;
|
|
Packit |
b92951 |
member->tag.type = ctf__get16(ctf, &mp[i].ctf_member_type);
|
|
Packit |
b92951 |
member->name = ctf__get32(ctf, &mp[i].ctf_member_name);
|
|
Packit |
b92951 |
member->bit_offset = ctf__get16(ctf, &mp[i].ctf_member_offset);
|
|
Packit |
b92951 |
/* sizes and offsets will be corrected at class__fixup_ctf_bitfields */
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
type__add_member(class, member);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return sizeof(*mp);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_class(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint64_t size, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
int member_size;
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
struct class *class = class__new(name, size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (size >= CTF_SHORT_MEMBER_LIMIT) {
|
|
Packit |
b92951 |
member_size = create_full_members(ctf, ptr, vlen, &class->type);
|
|
Packit |
b92951 |
} else {
|
|
Packit |
b92951 |
member_size = create_short_members(ctf, ptr, vlen, &class->type);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (member_size < 0)
|
|
Packit |
b92951 |
goto out_free;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &class->type.namespace.tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return (vlen * member_size);
|
|
Packit |
b92951 |
out_free:
|
|
Packit |
b92951 |
class__delete(class, ctf->priv);
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_union(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint64_t size, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
int member_size;
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
struct type *un = type__new(DW_TAG_union_type, name, size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (size >= CTF_SHORT_MEMBER_LIMIT) {
|
|
Packit |
b92951 |
member_size = create_full_members(ctf, ptr, vlen, un);
|
|
Packit |
b92951 |
} else {
|
|
Packit |
b92951 |
member_size = create_short_members(ctf, ptr, vlen, un);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (member_size < 0)
|
|
Packit |
b92951 |
goto out_free;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &un->namespace.tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return (vlen * member_size);
|
|
Packit |
b92951 |
out_free:
|
|
Packit |
b92951 |
type__delete(un, ctf->priv);
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct enumerator *enumerator__new(strings_t name, uint32_t value)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct enumerator *en = tag__alloc(sizeof(*en));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (en != NULL) {
|
|
Packit |
b92951 |
en->name = name;
|
|
Packit |
b92951 |
en->value = value;
|
|
Packit |
b92951 |
en->tag.tag = DW_TAG_enumerator;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return en;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_enumeration(struct ctf *ctf, void *ptr,
|
|
Packit |
b92951 |
int vlen, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint16_t size, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_enum *ep = ptr;
|
|
Packit |
b92951 |
uint16_t i;
|
|
Packit |
b92951 |
struct type *enumeration = type__new(DW_TAG_enumeration_type,
|
|
Packit |
b92951 |
ctf__get32(ctf,
|
|
Packit |
b92951 |
&tp->base.ctf_name),
|
|
Packit |
b92951 |
size ?: (sizeof(int) * 8));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (enumeration == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
for (i = 0; i < vlen; i++) {
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &ep[i].ctf_enum_name);
|
|
Packit |
b92951 |
uint32_t value = ctf__get32(ctf, &ep[i].ctf_enum_val);
|
|
Packit |
b92951 |
struct enumerator *enumerator = enumerator__new(name, value);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (enumerator == NULL)
|
|
Packit |
b92951 |
goto out_free;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
enumeration__add(enumeration, enumerator);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &enumeration->namespace.tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return (vlen * sizeof(*ep));
|
|
Packit |
b92951 |
out_free:
|
|
Packit |
b92951 |
enumeration__delete(enumeration, ctf->priv);
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_forward_decl(struct ctf *ctf, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint64_t size, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
struct class *fwd = class__new(name, size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (fwd == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
fwd->type.declaration = 1;
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &fwd->type.namespace.tag, id);
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_typedef(struct ctf *ctf, struct ctf_full_type *tp,
|
|
Packit |
b92951 |
uint64_t size, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
strings_t name = ctf__get32(ctf, &tp->base.ctf_name);
|
|
Packit |
b92951 |
unsigned int type_id = ctf__get16(ctf, &tp->base.ctf_type);
|
|
Packit |
b92951 |
struct type *type = type__new(DW_TAG_typedef, name, size);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (type == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
type->namespace.tag.type = type_id;
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, &type->namespace.tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int create_new_tag(struct ctf *ctf, int type,
|
|
Packit |
b92951 |
struct ctf_full_type *tp, uint32_t id)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
unsigned int type_id = ctf__get16(ctf, &tp->base.ctf_type);
|
|
Packit |
b92951 |
struct tag *tag = zalloc(sizeof(*tag));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (tag == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
switch (type) {
|
|
Packit |
b92951 |
case CTF_TYPE_KIND_CONST: tag->tag = DW_TAG_const_type; break;
|
|
Packit |
b92951 |
case CTF_TYPE_KIND_PTR: tag->tag = DW_TAG_pointer_type; break;
|
|
Packit |
b92951 |
case CTF_TYPE_KIND_RESTRICT: tag->tag = DW_TAG_restrict_type; break;
|
|
Packit |
b92951 |
case CTF_TYPE_KIND_VOLATILE: tag->tag = DW_TAG_volatile_type; break;
|
|
Packit |
b92951 |
default:
|
|
Packit |
b92951 |
free(tag);
|
|
Packit |
b92951 |
printf("%s: unknown type %d\n\n", __func__, type);
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
tag->type = type_id;
|
|
Packit |
b92951 |
cu__add_tag_with_id(ctf->priv, tag, id);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int ctf__load_types(struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
void *ctf_buffer = ctf__get_buffer(ctf);
|
|
Packit |
b92951 |
struct ctf_header *hp = ctf_buffer;
|
|
Packit |
b92951 |
void *ctf_contents = ctf_buffer + sizeof(*hp),
|
|
Packit |
b92951 |
*type_section = (ctf_contents + ctf__get32(ctf, &hp->ctf_type_off)),
|
|
Packit |
b92951 |
*strings_section = (ctf_contents + ctf__get32(ctf, &hp->ctf_str_off));
|
|
Packit |
b92951 |
struct ctf_full_type *type_ptr = type_section,
|
|
Packit |
b92951 |
*end = strings_section;
|
|
Packit |
b92951 |
uint32_t type_index = 0x0001;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (hp->ctf_parent_name || hp->ctf_parent_label)
|
|
Packit |
b92951 |
type_index += 0x8000;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
while (type_ptr < end) {
|
|
Packit |
b92951 |
uint16_t val = ctf__get16(ctf, &type_ptr->base.ctf_info);
|
|
Packit |
b92951 |
uint16_t type = CTF_GET_KIND(val);
|
|
Packit |
b92951 |
int vlen = CTF_GET_VLEN(val);
|
|
Packit |
b92951 |
void *ptr = type_ptr;
|
|
Packit |
b92951 |
uint16_t base_size = ctf__get16(ctf, &type_ptr->base.ctf_size);
|
|
Packit |
b92951 |
uint64_t size = base_size;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (base_size == 0xffff) {
|
|
Packit |
b92951 |
size = ctf__get32(ctf, &type_ptr->ctf_size_high);
|
|
Packit |
b92951 |
size <<= 32;
|
|
Packit |
b92951 |
size |= ctf__get32(ctf, &type_ptr->ctf_size_low);
|
|
Packit |
b92951 |
ptr += sizeof(struct ctf_full_type);
|
|
Packit |
b92951 |
} else
|
|
Packit |
b92951 |
ptr += sizeof(struct ctf_short_type);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (type == CTF_TYPE_KIND_INT) {
|
|
Packit |
b92951 |
vlen = create_new_base_type(ctf, ptr, type_ptr, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_FLT) {
|
|
Packit |
b92951 |
vlen = create_new_base_type_float(ctf, ptr, type_ptr, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_ARR) {
|
|
Packit |
b92951 |
vlen = create_new_array(ctf, ptr, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_FUNC) {
|
|
Packit |
b92951 |
vlen = create_new_subroutine_type(ctf, ptr, vlen, type_ptr, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_STR) {
|
|
Packit |
b92951 |
vlen = create_new_class(ctf, ptr,
|
|
Packit |
b92951 |
vlen, type_ptr, size, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_UNION) {
|
|
Packit |
b92951 |
vlen = create_new_union(ctf, ptr,
|
|
Packit |
b92951 |
vlen, type_ptr, size, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_ENUM) {
|
|
Packit |
b92951 |
vlen = create_new_enumeration(ctf, ptr, vlen, type_ptr,
|
|
Packit |
b92951 |
size, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_FWD) {
|
|
Packit |
b92951 |
vlen = create_new_forward_decl(ctf, type_ptr, size, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_TYPDEF) {
|
|
Packit |
b92951 |
vlen = create_new_typedef(ctf, type_ptr, size, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_VOLATILE ||
|
|
Packit |
b92951 |
type == CTF_TYPE_KIND_PTR ||
|
|
Packit |
b92951 |
type == CTF_TYPE_KIND_CONST ||
|
|
Packit |
b92951 |
type == CTF_TYPE_KIND_RESTRICT) {
|
|
Packit |
b92951 |
vlen = create_new_tag(ctf, type, type_ptr, type_index);
|
|
Packit |
b92951 |
} else if (type == CTF_TYPE_KIND_UNKN) {
|
|
Packit |
b92951 |
cu__table_nullify_type_entry(ctf->priv, type_index);
|
|
Packit |
b92951 |
fprintf(stderr,
|
|
Packit |
b92951 |
"CTF: idx: %d, off: %zd, root: %s Unknown\n",
|
|
Packit |
b92951 |
type_index, ((void *)type_ptr) - type_section,
|
|
Packit |
b92951 |
CTF_ISROOT(val) ? "yes" : "no");
|
|
Packit |
b92951 |
vlen = 0;
|
|
Packit |
b92951 |
} else
|
|
Packit |
b92951 |
return -EINVAL;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (vlen < 0)
|
|
Packit |
b92951 |
return vlen;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
type_ptr = ptr + vlen;
|
|
Packit |
b92951 |
type_index++;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static struct variable *variable__new(uint16_t type, GElf_Sym *sym,
|
|
Packit |
b92951 |
struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct variable *var = tag__alloc(sizeof(*var));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (var != NULL) {
|
|
Packit |
b92951 |
var->scope = VSCOPE_GLOBAL;
|
|
Packit |
b92951 |
var->ip.addr = elf_sym__value(sym);
|
|
Packit |
b92951 |
var->name = sym->st_name;
|
|
Packit |
b92951 |
var->external = elf_sym__bind(sym) == STB_GLOBAL;
|
|
Packit |
b92951 |
var->ip.tag.tag = DW_TAG_variable;
|
|
Packit |
b92951 |
var->ip.tag.type = type;
|
|
Packit |
b92951 |
uint32_t id; /* FIXME: not needed for variables... */
|
|
Packit |
b92951 |
cu__add_tag(ctf->priv, &var->ip.tag, &id;;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return var;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int ctf__load_objects(struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf_header *hp = ctf__get_buffer(ctf);
|
|
Packit |
b92951 |
uint16_t *objp = (ctf__get_buffer(ctf) + sizeof(*hp) +
|
|
Packit |
b92951 |
ctf__get32(ctf, &hp->ctf_object_off));
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
GElf_Sym sym;
|
|
Packit |
b92951 |
uint32_t idx;
|
|
Packit |
b92951 |
ctf__for_each_symtab_object(ctf, idx, sym) {
|
|
Packit |
b92951 |
const uint16_t type = *objp;
|
|
Packit |
b92951 |
/*
|
|
Packit |
b92951 |
* Discard void objects, probably was an object
|
|
Packit |
b92951 |
* we didn't found DWARF info for when encoding.
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
if (type && variable__new(type, &sym, ctf) == NULL)
|
|
Packit |
b92951 |
return -ENOMEM;
|
|
Packit |
b92951 |
++objp;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int ctf__load_sections(struct ctf *ctf)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
int err = ctf__load_symtab(ctf);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (err != 0)
|
|
Packit |
b92951 |
goto out;
|
|
Packit |
b92951 |
err = ctf__load_funcs(ctf);
|
|
Packit |
b92951 |
if (err == 0)
|
|
Packit |
b92951 |
err = ctf__load_types(ctf);
|
|
Packit |
b92951 |
if (err == 0)
|
|
Packit |
b92951 |
err = ctf__load_objects(ctf);
|
|
Packit |
b92951 |
out:
|
|
Packit |
b92951 |
return err;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int class__fixup_ctf_bitfields(struct tag *tag, struct cu *cu)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct class_member *pos;
|
|
Packit |
b92951 |
struct type *tag_type = tag__type(tag);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
type__for_each_data_member(tag_type, pos) {
|
|
Packit |
b92951 |
struct tag *type = tag__strip_typedefs_and_modifiers(&pos->tag, cu);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (type == NULL) /* FIXME: C++ CTF... */
|
|
Packit |
b92951 |
continue;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
pos->bitfield_offset = 0;
|
|
Packit |
b92951 |
pos->bitfield_size = 0;
|
|
Packit |
b92951 |
pos->byte_offset = pos->bit_offset / 8;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
uint16_t type_bit_size;
|
|
Packit |
b92951 |
size_t integral_bit_size;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
switch (type->tag) {
|
|
Packit |
b92951 |
case DW_TAG_enumeration_type:
|
|
Packit |
b92951 |
type_bit_size = tag__type(type)->size;
|
|
Packit |
b92951 |
/* Best we can do to check if this is a packed enum */
|
|
Packit |
b92951 |
if (is_power_of_2(type_bit_size))
|
|
Packit |
b92951 |
integral_bit_size = roundup(type_bit_size, 8);
|
|
Packit |
b92951 |
else
|
|
Packit |
b92951 |
integral_bit_size = sizeof(int) * 8;
|
|
Packit |
b92951 |
break;
|
|
Packit |
b92951 |
case DW_TAG_base_type: {
|
|
Packit |
b92951 |
struct base_type *bt = tag__base_type(type);
|
|
Packit |
b92951 |
char name[256];
|
|
Packit |
b92951 |
type_bit_size = bt->bit_size;
|
|
Packit |
b92951 |
integral_bit_size = base_type__name_to_size(bt, cu);
|
|
Packit |
b92951 |
if (integral_bit_size == 0)
|
|
Packit |
b92951 |
fprintf(stderr, "%s: unknown base type name \"%s\"!\n",
|
|
Packit |
b92951 |
__func__, base_type__name(bt, cu, name,
|
|
Packit |
b92951 |
sizeof(name)));
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
break;
|
|
Packit |
b92951 |
default:
|
|
Packit |
b92951 |
pos->byte_size = tag__size(type, cu);
|
|
Packit |
b92951 |
pos->bit_size = pos->byte_size * 8;
|
|
Packit |
b92951 |
continue;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
/*
|
|
Packit |
b92951 |
* XXX: integral_bit_size can be zero if base_type__name_to_size doesn't
|
|
Packit |
b92951 |
* know about the base_type name, so one has to add there when
|
|
Packit |
b92951 |
* such base_type isn't found. pahole will put zero on the
|
|
Packit |
b92951 |
* struct output so it should be easy to spot the name when
|
|
Packit |
b92951 |
* such unlikely thing happens.
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
pos->byte_size = integral_bit_size / 8;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (integral_bit_size == 0 || type_bit_size == integral_bit_size) {
|
|
Packit |
b92951 |
pos->bit_size = integral_bit_size;
|
|
Packit |
b92951 |
continue;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
pos->bitfield_offset = pos->bit_offset % integral_bit_size;
|
|
Packit |
b92951 |
pos->bitfield_size = type_bit_size;
|
|
Packit |
b92951 |
pos->bit_size = type_bit_size;
|
|
Packit |
b92951 |
pos->byte_offset = (((pos->bit_offset / integral_bit_size) *
|
|
Packit |
b92951 |
integral_bit_size) / 8);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static int cu__fixup_ctf_bitfields(struct cu *cu)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
int err = 0;
|
|
Packit |
b92951 |
struct tag *pos;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
list_for_each_entry(pos, &cu->tags, node)
|
|
Packit |
b92951 |
if (tag__is_struct(pos) || tag__is_union(pos)) {
|
|
Packit |
b92951 |
err = class__fixup_ctf_bitfields(pos, cu);
|
|
Packit |
b92951 |
if (err)
|
|
Packit |
b92951 |
break;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return err;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static const char *ctf__function_name(struct function *func,
|
|
Packit |
b92951 |
const struct cu *cu)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf *ctf = cu->priv;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return ctf->symtab->symstrs->d_buf + func->name;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static const char *ctf__variable_name(const struct variable *var,
|
|
Packit |
b92951 |
const struct cu *cu)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
struct ctf *ctf = cu->priv;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
return ctf->symtab->symstrs->d_buf + var->name;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static void ctf__cu_delete(struct cu *cu)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
ctf__delete(cu->priv);
|
|
Packit |
b92951 |
cu->priv = NULL;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
static const char *ctf__strings_ptr(const struct cu *cu, strings_t s)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
return ctf__string(cu->priv, s);
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
struct debug_fmt_ops ctf__ops;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
int ctf__load_file(struct cus *cus, struct conf_load *conf,
|
|
Packit |
b92951 |
const char *filename)
|
|
Packit |
b92951 |
{
|
|
Packit |
b92951 |
int err;
|
|
Packit |
b92951 |
struct ctf *state = ctf__new(filename, NULL);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (state == NULL)
|
|
Packit |
b92951 |
return -1;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
struct cu *cu = cu__new(filename, state->wordsize, NULL, 0, filename);
|
|
Packit |
b92951 |
if (cu == NULL)
|
|
Packit |
b92951 |
return -1;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cu->language = LANG_C;
|
|
Packit |
b92951 |
cu->uses_global_strings = false;
|
|
Packit |
b92951 |
cu->little_endian = state->ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
|
|
Packit |
b92951 |
cu->dfops = &ctf__ops;
|
|
Packit |
b92951 |
cu->priv = state;
|
|
Packit |
b92951 |
state->priv = cu;
|
|
Packit |
b92951 |
if (ctf__load(state) != 0)
|
|
Packit |
b92951 |
return -1;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
err = ctf__load_sections(state);
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
if (err != 0) {
|
|
Packit |
b92951 |
cu__delete(cu);
|
|
Packit |
b92951 |
return err;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
err = cu__fixup_ctf_bitfields(cu);
|
|
Packit |
b92951 |
/*
|
|
Packit |
b92951 |
* The app stole this cu, possibly deleting it,
|
|
Packit |
b92951 |
* so forget about it
|
|
Packit |
b92951 |
*/
|
|
Packit |
b92951 |
if (conf && conf->steal && conf->steal(cu, conf))
|
|
Packit |
b92951 |
return 0;
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
cus__add(cus, cu);
|
|
Packit |
b92951 |
return err;
|
|
Packit |
b92951 |
}
|
|
Packit |
b92951 |
|
|
Packit |
b92951 |
struct debug_fmt_ops ctf__ops = {
|
|
Packit |
b92951 |
.name = "ctf",
|
|
Packit |
b92951 |
.function__name = ctf__function_name,
|
|
Packit |
b92951 |
.load_file = ctf__load_file,
|
|
Packit |
b92951 |
.variable__name = ctf__variable_name,
|
|
Packit |
b92951 |
.strings__ptr = ctf__strings_ptr,
|
|
Packit |
b92951 |
.cu__delete = ctf__cu_delete,
|
|
Packit |
b92951 |
};
|