2009-03-19 16:16:07 +01:00
|
|
|
/*
|
|
|
|
Copyright (C) 2009 Red Hat Inc.
|
|
|
|
Copyright (C) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
|
|
|
|
|
|
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,
|
2009-03-20 00:10:33 +01:00
|
|
|
ftype->unspec_parms, &position);
|
2009-03-19 16:16:07 +01:00
|
|
|
|
|
|
|
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,
|
2009-03-20 16:51:30 +01:00
|
|
|
etype->size, etype->nr_members,
|
|
|
|
&position);
|
2009-03-19 16:16:07 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2009-03-24 22:12:11 +01:00
|
|
|
struct ctf *ctf = ctf__new(self->filename);
|
2009-03-19 16:16:07 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|