dwarves/ctf_encoder.c
Arnaldo Carvalho de Melo 2fd3936a9d ctf: combine the structs ctf_state and ctf
Moving more CTF only stuff out of the dwarves land and into something that can
be more easily stolen by other projects not interested in funny named stuff
such as pahole.

This also will help with encoding, as we will normally be recoding data from
DWARF, so the ELF file will be available and we will just add a new section to
it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-03-24 18:12:11 -03:00

221 lines
5.4 KiB
C

/*
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,
ftype->unspec_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->size, 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);
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;
}