Blame dwarf_loader.c

Packit b92951
/*
Packit b92951
  SPDX-License-Identifier: GPL-2.0-only
Packit b92951
Packit b92951
  Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
Packit b92951
*/
Packit b92951
Packit b92951
#include <assert.h>
Packit b92951
#include <dirent.h>
Packit b92951
#include <dwarf.h>
Packit b92951
#include <elfutils/libdwfl.h>
Packit b92951
#include <errno.h>
Packit b92951
#include <fcntl.h>
Packit b92951
#include <fnmatch.h>
Packit b92951
#include <libelf.h>
Packit b92951
#include <obstack.h>
Packit b92951
#include <search.h>
Packit b92951
#include <stdio.h>
Packit b92951
#include <stdlib.h>
Packit b92951
#include <string.h>
Packit b92951
#include <unistd.h>
Packit b92951
Packit b92951
#include "config.h"
Packit b92951
#include "list.h"
Packit b92951
#include "dwarves.h"
Packit b92951
#include "dutil.h"
Packit b92951
#include "strings.h"
Packit b92951
#include "hash.h"
Packit b92951
Packit b92951
struct strings *strings;
Packit b92951
Packit b92951
#ifndef DW_AT_GNU_vector
Packit b92951
#define DW_AT_GNU_vector 0x2107
Packit b92951
#endif
Packit b92951
Packit b92951
#ifndef DW_TAG_GNU_call_site
Packit b92951
#define DW_TAG_GNU_call_site 0x4109
Packit b92951
#define DW_TAG_GNU_call_site_parameter 0x410a
Packit b92951
#endif
Packit b92951
Packit b92951
#define hashtags__fn(key) hash_64(key, HASHTAGS__BITS)
Packit b92951
Packit b92951
bool no_bitfield_type_recode = true;
Packit b92951
Packit b92951
static void __tag__print_not_supported(uint32_t tag, const char *func)
Packit b92951
{
Packit b92951
	static bool dwarf_tags_warned[DW_TAG_GNU_call_site_parameter + 64];
Packit b92951
Packit b92951
	if (tag < sizeof(dwarf_tags_warned)) {
Packit b92951
		if (dwarf_tags_warned[tag])
Packit b92951
			return;
Packit b92951
		dwarf_tags_warned[tag] = true;
Packit b92951
	}
Packit b92951
Packit b92951
	fprintf(stderr, "%s: tag not supported %#x (%s)!\n", func,
Packit b92951
		tag, dwarf_tag_name(tag));
Packit b92951
}
Packit b92951
Packit b92951
#define tag__print_not_supported(tag) \
Packit b92951
	__tag__print_not_supported(tag, __func__)
Packit b92951
Packit b92951
struct dwarf_off_ref {
Packit b92951
	unsigned int	from_types : 1;
Packit b92951
	Dwarf_Off	off;
Packit b92951
};
Packit b92951
Packit b92951
typedef struct dwarf_off_ref dwarf_off_ref;
Packit b92951
Packit b92951
struct dwarf_tag {
Packit b92951
	struct hlist_node hash_node;
Packit b92951
	dwarf_off_ref	 type;
Packit b92951
	Dwarf_Off	 id;
Packit b92951
	union {
Packit b92951
		dwarf_off_ref abstract_origin;
Packit b92951
		dwarf_off_ref containing_type;
Packit b92951
	};
Packit b92951
	struct tag	 *tag;
Packit b92951
	uint32_t         small_id;
Packit b92951
	strings_t        decl_file;
Packit b92951
	uint16_t         decl_line;
Packit b92951
};
Packit b92951
Packit b92951
static dwarf_off_ref dwarf_tag__spec(struct dwarf_tag *dtag)
Packit b92951
{
Packit b92951
	return *(dwarf_off_ref *)(dtag + 1);
Packit b92951
}
Packit b92951
Packit b92951
static void dwarf_tag__set_spec(struct dwarf_tag *dtag, dwarf_off_ref spec)
Packit b92951
{
Packit b92951
	*(dwarf_off_ref *)(dtag + 1) = spec;
Packit b92951
}
Packit b92951
Packit b92951
#define HASHTAGS__BITS 8
Packit b92951
#define HASHTAGS__SIZE (1UL << HASHTAGS__BITS)
Packit b92951
Packit b92951
#define obstack_chunk_alloc malloc
Packit b92951
#define obstack_chunk_free free
Packit b92951
Packit b92951
static void *obstack_zalloc(struct obstack *obstack, size_t size)
Packit b92951
{
Packit b92951
	void *o = obstack_alloc(obstack, size);
Packit b92951
Packit b92951
	if (o)
Packit b92951
		memset(o, 0, size);
Packit b92951
	return o;
Packit b92951
}
Packit b92951
Packit b92951
struct dwarf_cu {
Packit b92951
	struct hlist_head hash_tags[HASHTAGS__SIZE];
Packit b92951
	struct hlist_head hash_types[HASHTAGS__SIZE];
Packit b92951
	struct obstack obstack;
Packit b92951
	struct cu *cu;
Packit b92951
	struct dwarf_cu *type_unit;
Packit b92951
};
Packit b92951
Packit b92951
static void dwarf_cu__init(struct dwarf_cu *dcu)
Packit b92951
{
Packit b92951
	unsigned int i;
Packit b92951
	for (i = 0; i < HASHTAGS__SIZE; ++i) {
Packit b92951
		INIT_HLIST_HEAD(&dcu->hash_tags[i]);
Packit b92951
		INIT_HLIST_HEAD(&dcu->hash_types[i]);
Packit b92951
	}
Packit b92951
	obstack_init(&dcu->obstack);
Packit b92951
	dcu->type_unit = NULL;
Packit b92951
}
Packit b92951
Packit b92951
static void hashtags__hash(struct hlist_head *hashtable,
Packit b92951
			   struct dwarf_tag *dtag)
Packit b92951
{
Packit b92951
	struct hlist_head *head = hashtable + hashtags__fn(dtag->id);
Packit b92951
	hlist_add_head(&dtag->hash_node, head);
Packit b92951
}
Packit b92951
Packit b92951
static struct dwarf_tag *hashtags__find(const struct hlist_head *hashtable,
Packit b92951
					const Dwarf_Off id)
Packit b92951
{
Packit b92951
	if (id == 0)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	struct dwarf_tag *tpos;
Packit b92951
	struct hlist_node *pos;
Packit b92951
	uint16_t bucket = hashtags__fn(id);
Packit b92951
	const struct hlist_head *head = hashtable + bucket;
Packit b92951
Packit b92951
	hlist_for_each_entry(tpos, pos, head, hash_node) {
Packit b92951
		if (tpos->id == id)
Packit b92951
			return tpos;
Packit b92951
	}
Packit b92951
Packit b92951
	return NULL;
Packit b92951
}
Packit b92951
Packit b92951
static void cu__hash(struct cu *cu, struct tag *tag)
Packit b92951
{
Packit b92951
	struct dwarf_cu *dcu = cu->priv;
Packit b92951
	struct hlist_head *hashtable = tag__is_tag_type(tag) ?
Packit b92951
							dcu->hash_types :
Packit b92951
							dcu->hash_tags;
Packit b92951
	hashtags__hash(hashtable, tag->priv);
Packit b92951
}
Packit b92951
Packit b92951
static struct dwarf_tag *dwarf_cu__find_tag_by_ref(const struct dwarf_cu *cu,
Packit b92951
						   const struct dwarf_off_ref *ref)
Packit b92951
{
Packit b92951
	if (cu == NULL)
Packit b92951
		return NULL;
Packit b92951
	if (ref->from_types) {
Packit b92951
		return NULL;
Packit b92951
	}
Packit b92951
	return hashtags__find(cu->hash_tags, ref->off);
Packit b92951
}
Packit b92951
Packit b92951
static struct dwarf_tag *dwarf_cu__find_type_by_ref(const struct dwarf_cu *dcu,
Packit b92951
						    const struct dwarf_off_ref *ref)
Packit b92951
{
Packit b92951
	if (dcu == NULL)
Packit b92951
		return NULL;
Packit b92951
	if (ref->from_types) {
Packit b92951
		dcu = dcu->type_unit;
Packit b92951
		if (dcu == NULL) {
Packit b92951
			return NULL;
Packit b92951
		}
Packit b92951
	}
Packit b92951
	return hashtags__find(dcu->hash_types, ref->off);
Packit b92951
}
Packit b92951
Packit b92951
extern struct strings *strings;
Packit b92951
Packit b92951
static void *memdup(const void *src, size_t len, struct cu *cu)
Packit b92951
{
Packit b92951
	void *s = obstack_alloc(&cu->obstack, len);
Packit b92951
	if (s != NULL)
Packit b92951
		memcpy(s, src, len);
Packit b92951
	return s;
Packit b92951
}
Packit b92951
Packit b92951
/* Number decoding macros.  See 7.6 Variable Length Data.  */
Packit b92951
Packit b92951
#define get_uleb128_step(var, addr, nth, break)			\
Packit b92951
	__b = *(addr)++;					\
Packit b92951
	var |= (uintmax_t) (__b & 0x7f) << (nth * 7);		\
Packit b92951
	if ((__b & 0x80) == 0)					\
Packit b92951
		break
Packit b92951
Packit b92951
#define get_uleb128_rest_return(var, i, addrp)			\
Packit b92951
	do {							\
Packit b92951
		for (; i < 10; ++i) {				\
Packit b92951
			get_uleb128_step(var, *addrp, i,	\
Packit b92951
					  return var);		\
Packit b92951
	}							\
Packit b92951
	/* Other implementations set VALUE to UINT_MAX in this	\
Packit b92951
	  case. So we better do this as well.  */		\
Packit b92951
	return UINT64_MAX;					\
Packit b92951
  } while (0)
Packit b92951
Packit b92951
static uint64_t __libdw_get_uleb128(uint64_t acc, uint32_t i,
Packit b92951
				    const uint8_t **addrp)
Packit b92951
{
Packit b92951
	uint8_t __b;
Packit b92951
	get_uleb128_rest_return (acc, i, addrp);
Packit b92951
}
Packit b92951
Packit b92951
#define get_uleb128(var, addr)					\
Packit b92951
	do {							\
Packit b92951
		uint8_t __b;				\
Packit b92951
		var = 0;					\
Packit b92951
		get_uleb128_step(var, addr, 0, break);		\
Packit b92951
		var = __libdw_get_uleb128 (var, 1, &(addr));	\
Packit b92951
	} while (0)
Packit b92951
Packit b92951
static uint64_t attr_numeric(Dwarf_Die *die, uint32_t name)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
	uint32_t form;
Packit b92951
Packit b92951
	if (dwarf_attr(die, name, &attr) == NULL)
Packit b92951
		return 0;
Packit b92951
Packit b92951
	form = dwarf_whatform(&attr);
Packit b92951
Packit b92951
	switch (form) {
Packit b92951
	case DW_FORM_addr: {
Packit b92951
		Dwarf_Addr addr;
Packit b92951
		if (dwarf_formaddr(&attr, &addr) == 0)
Packit b92951
			return addr;
Packit b92951
	}
Packit b92951
		break;
Packit b92951
	case DW_FORM_data1:
Packit b92951
	case DW_FORM_data2:
Packit b92951
	case DW_FORM_data4:
Packit b92951
	case DW_FORM_data8:
Packit b92951
	case DW_FORM_sdata:
Packit b92951
	case DW_FORM_udata: {
Packit b92951
		Dwarf_Word value;
Packit b92951
		if (dwarf_formudata(&attr, &value) == 0)
Packit b92951
			return value;
Packit b92951
	}
Packit b92951
		break;
Packit b92951
	case DW_FORM_flag:
Packit b92951
	case DW_FORM_flag_present: {
Packit b92951
		bool value;
Packit b92951
		if (dwarf_formflag(&attr, &value) == 0)
Packit b92951
			return value;
Packit b92951
	}
Packit b92951
		break;
Packit b92951
	default:
Packit b92951
		fprintf(stderr, "DW_AT_<0x%x>=0x%x\n", name, form);
Packit b92951
		break;
Packit b92951
	}
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static uint64_t dwarf_expr(const uint8_t *expr, uint32_t len __unused)
Packit b92951
{
Packit b92951
	/* Common case: offset from start of the class */
Packit b92951
	if (expr[0] == DW_OP_plus_uconst ||
Packit b92951
	    expr[0] == DW_OP_constu) {
Packit b92951
		uint64_t result;
Packit b92951
		++expr;
Packit b92951
		get_uleb128(result, expr);
Packit b92951
		return result;
Packit b92951
	}
Packit b92951
Packit b92951
	fprintf(stderr, "%s: unhandled %#x DW_OP_ operation\n",
Packit b92951
		__func__, *expr);
Packit b92951
	return UINT64_MAX;
Packit b92951
}
Packit b92951
Packit b92951
static Dwarf_Off attr_offset(Dwarf_Die *die, const uint32_t name)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
	Dwarf_Block block;
Packit b92951
Packit b92951
	if (dwarf_attr(die, name, &attr) == NULL)
Packit b92951
		return 0;
Packit b92951
Packit b92951
	switch (dwarf_whatform(&attr)) {
Packit b92951
	case DW_FORM_data1:
Packit b92951
	case DW_FORM_data2:
Packit b92951
	case DW_FORM_data4:
Packit b92951
	case DW_FORM_data8:
Packit b92951
	case DW_FORM_sdata:
Packit b92951
	case DW_FORM_udata: {
Packit b92951
		Dwarf_Word value;
Packit b92951
		if (dwarf_formudata(&attr, &value) == 0)
Packit b92951
			return value;
Packit b92951
		break;
Packit b92951
	}
Packit b92951
	default:
Packit b92951
		if (dwarf_formblock(&attr, &block) == 0)
Packit b92951
			return dwarf_expr(block.data, block.length);
Packit b92951
	}
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static const char *attr_string(Dwarf_Die *die, uint32_t name)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
	if (dwarf_attr(die, name, &attr) != NULL)
Packit b92951
		return dwarf_formstring(&attr);
Packit b92951
	return NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct dwarf_off_ref attr_type(Dwarf_Die *die, uint32_t attr_name)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
	struct dwarf_off_ref ref;
Packit b92951
	if (dwarf_attr(die, attr_name, &attr) != NULL) {
Packit b92951
		Dwarf_Die type_die;
Packit b92951
		if (dwarf_formref_die(&attr, &type_die) != NULL) {
Packit b92951
			ref.from_types = attr.form == DW_FORM_ref_sig8;
Packit b92951
			ref.off = dwarf_dieoffset(&type_die);
Packit b92951
			return ref;
Packit b92951
		}
Packit b92951
	}
Packit b92951
	memset(&ref, 0, sizeof(ref));
Packit b92951
	return ref;
Packit b92951
}
Packit b92951
Packit b92951
static int attr_location(Dwarf_Die *die, Dwarf_Op **expr, size_t *exprlen)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
	if (dwarf_attr(die, DW_AT_location, &attr) != NULL) {
Packit b92951
		if (dwarf_getlocation(&attr, expr, exprlen) == 0)
Packit b92951
			return 0;
Packit b92951
	}
Packit b92951
Packit b92951
	return 1;
Packit b92951
}
Packit b92951
Packit b92951
static void *__tag__alloc(struct dwarf_cu *dcu, size_t size, bool spec)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = obstack_zalloc(&dcu->obstack,
Packit b92951
						(sizeof(*dtag) +
Packit b92951
						 (spec ? sizeof(dwarf_off_ref) : 0)));
Packit b92951
	if (dtag == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	struct tag *tag = obstack_zalloc(&dcu->cu->obstack, size);
Packit b92951
Packit b92951
	if (tag == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	dtag->tag = tag;
Packit b92951
	tag->priv = dtag;
Packit b92951
	tag->type = 0;
Packit b92951
	tag->top_level = 0;
Packit b92951
Packit b92951
	return tag;
Packit b92951
}
Packit b92951
Packit b92951
static void *tag__alloc(struct cu *cu, size_t size)
Packit b92951
{
Packit b92951
	return __tag__alloc(cu->priv, size, false);
Packit b92951
}
Packit b92951
Packit b92951
static void *tag__alloc_with_spec(struct cu *cu, size_t size)
Packit b92951
{
Packit b92951
	return __tag__alloc(cu->priv, size, true);
Packit b92951
}
Packit b92951
Packit b92951
static void tag__init(struct tag *tag, struct cu *cu, Dwarf_Die *die)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
Packit b92951
	tag->tag = dwarf_tag(die);
Packit b92951
Packit b92951
	dtag->id  = dwarf_dieoffset(die);
Packit b92951
Packit b92951
	if (tag->tag == DW_TAG_imported_module ||
Packit b92951
	    tag->tag == DW_TAG_imported_declaration)
Packit b92951
		dtag->type = attr_type(die, DW_AT_import);
Packit b92951
	else
Packit b92951
		dtag->type = attr_type(die, DW_AT_type);
Packit b92951
Packit b92951
	dtag->abstract_origin = attr_type(die, DW_AT_abstract_origin);
Packit b92951
	tag->recursivity_level = 0;
Packit b92951
Packit b92951
	if (cu->extra_dbg_info) {
Packit b92951
		int32_t decl_line;
Packit b92951
		const char *decl_file = dwarf_decl_file(die);
Packit b92951
		static const char *last_decl_file;
Packit b92951
		static uint32_t last_decl_file_idx;
Packit b92951
Packit b92951
		if (decl_file != last_decl_file) {
Packit b92951
			last_decl_file_idx = strings__add(strings, decl_file);
Packit b92951
			last_decl_file = decl_file;
Packit b92951
		}
Packit b92951
Packit b92951
		dtag->decl_file = last_decl_file_idx;
Packit b92951
		dwarf_decl_line(die, &decl_line);
Packit b92951
		dtag->decl_line = decl_line;
Packit b92951
	}
Packit b92951
Packit b92951
	INIT_LIST_HEAD(&tag->node);
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *tag__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct tag *tag = tag__alloc(cu, sizeof(*tag));
Packit b92951
Packit b92951
	if (tag != NULL)
Packit b92951
		tag__init(tag, cu, die);
Packit b92951
Packit b92951
	return tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct ptr_to_member_type *ptr_to_member_type__new(Dwarf_Die *die,
Packit b92951
							  struct cu *cu)
Packit b92951
{
Packit b92951
	struct ptr_to_member_type *ptr = tag__alloc(cu, sizeof(*ptr));
Packit b92951
Packit b92951
	if (ptr != NULL) {
Packit b92951
		tag__init(&ptr->tag, cu, die);
Packit b92951
		struct dwarf_tag *dtag = ptr->tag.priv;
Packit b92951
		dtag->containing_type = attr_type(die, DW_AT_containing_type);
Packit b92951
	}
Packit b92951
Packit b92951
	return ptr;
Packit b92951
}
Packit b92951
Packit b92951
static struct base_type *base_type__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct base_type *bt = tag__alloc(cu, sizeof(*bt));
Packit b92951
Packit b92951
	if (bt != NULL) {
Packit b92951
		tag__init(&bt->tag, cu, die);
Packit b92951
		bt->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		bt->bit_size = attr_numeric(die, DW_AT_byte_size) * 8;
Packit b92951
		uint64_t encoding = attr_numeric(die, DW_AT_encoding);
Packit b92951
		bt->is_bool = encoding == DW_ATE_boolean;
Packit b92951
		bt->is_signed = encoding == DW_ATE_signed;
Packit b92951
		bt->is_varargs = false;
Packit b92951
		bt->name_has_encoding = true;
Packit b92951
	}
Packit b92951
Packit b92951
	return bt;
Packit b92951
}
Packit b92951
Packit b92951
static struct array_type *array_type__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct array_type *at = tag__alloc(cu, sizeof(*at));
Packit b92951
Packit b92951
	if (at != NULL) {
Packit b92951
		tag__init(&at->tag, cu, die);
Packit b92951
		at->dimensions = 0;
Packit b92951
		at->nr_entries = NULL;
Packit b92951
		at->is_vector	 = dwarf_hasattr(die, DW_AT_GNU_vector);
Packit b92951
	}
Packit b92951
Packit b92951
	return at;
Packit b92951
}
Packit b92951
Packit b92951
static void namespace__init(struct namespace *namespace, Dwarf_Die *die,
Packit b92951
			    struct cu *cu)
Packit b92951
{
Packit b92951
	tag__init(&namespace->tag, cu, die);
Packit b92951
	INIT_LIST_HEAD(&namespace->tags);
Packit b92951
	namespace->sname = 0;
Packit b92951
	namespace->name  = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
	namespace->nr_tags = 0;
Packit b92951
	namespace->shared_tags = 0;
Packit b92951
}
Packit b92951
Packit b92951
static struct namespace *namespace__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct namespace *namespace = tag__alloc(cu, sizeof(*namespace));
Packit b92951
Packit b92951
	if (namespace != NULL)
Packit b92951
		namespace__init(namespace, die, cu);
Packit b92951
Packit b92951
	return namespace;
Packit b92951
}
Packit b92951
Packit b92951
static void type__init(struct type *type, Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	namespace__init(&type->namespace, die, cu);
Packit b92951
	INIT_LIST_HEAD(&type->node);
Packit b92951
	type->size		 = attr_numeric(die, DW_AT_byte_size);
Packit b92951
	type->alignment		 = attr_numeric(die, DW_AT_alignment);
Packit b92951
	type->declaration	 = attr_numeric(die, DW_AT_declaration);
Packit b92951
	dwarf_tag__set_spec(type->namespace.tag.priv,
Packit b92951
			    attr_type(die, DW_AT_specification));
Packit b92951
	type->definition_emitted = 0;
Packit b92951
	type->fwd_decl_emitted	 = 0;
Packit b92951
	type->resized		 = 0;
Packit b92951
	type->nr_members	 = 0;
Packit b92951
	type->nr_static_members	 = 0;
Packit b92951
}
Packit b92951
Packit b92951
static struct type *type__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct type *type = tag__alloc_with_spec(cu, sizeof(*type));
Packit b92951
Packit b92951
	if (type != NULL)
Packit b92951
		type__init(type, die, cu);
Packit b92951
Packit b92951
	return type;
Packit b92951
}
Packit b92951
Packit b92951
static struct enumerator *enumerator__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct enumerator *enumerator = tag__alloc(cu, sizeof(*enumerator));
Packit b92951
Packit b92951
	if (enumerator != NULL) {
Packit b92951
		tag__init(&enumerator->tag, cu, die);
Packit b92951
		enumerator->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		enumerator->value = attr_numeric(die, DW_AT_const_value);
Packit b92951
	}
Packit b92951
Packit b92951
	return enumerator;
Packit b92951
}
Packit b92951
Packit b92951
static enum vscope dwarf__location(Dwarf_Die *die, uint64_t *addr, struct location *location)
Packit b92951
{
Packit b92951
	enum vscope scope = VSCOPE_UNKNOWN;
Packit b92951
Packit b92951
	if (attr_location(die, &location->expr, &location->exprlen) != 0)
Packit b92951
		scope = VSCOPE_OPTIMIZED;
Packit b92951
	else if (location->exprlen != 0) {
Packit b92951
		Dwarf_Op *expr = location->expr;
Packit b92951
		switch (expr->atom) {
Packit b92951
		case DW_OP_addr:
Packit b92951
			scope = VSCOPE_GLOBAL;
Packit b92951
			*addr = expr[0].number;
Packit b92951
			break;
Packit b92951
		case DW_OP_reg1 ... DW_OP_reg31:
Packit b92951
		case DW_OP_breg0 ... DW_OP_breg31:
Packit b92951
			scope = VSCOPE_REGISTER;	break;
Packit b92951
		case DW_OP_fbreg:
Packit b92951
			scope = VSCOPE_LOCAL;	break;
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	return scope;
Packit b92951
}
Packit b92951
Packit b92951
enum vscope variable__scope(const struct variable *var)
Packit b92951
{
Packit b92951
	return var->scope;
Packit b92951
}
Packit b92951
Packit b92951
const char *variable__scope_str(const struct variable *var)
Packit b92951
{
Packit b92951
	switch (var->scope) {
Packit b92951
	case VSCOPE_LOCAL:	return "local";
Packit b92951
	case VSCOPE_GLOBAL:	return "global";
Packit b92951
	case VSCOPE_REGISTER:	return "register";
Packit b92951
	case VSCOPE_OPTIMIZED:	return "optimized";
Packit b92951
	default: break;
Packit b92951
	};
Packit b92951
Packit b92951
	return "unknown";
Packit b92951
}
Packit b92951
Packit b92951
static struct variable *variable__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct variable *var = tag__alloc(cu, sizeof(*var));
Packit b92951
Packit b92951
	if (var != NULL) {
Packit b92951
		tag__init(&var->ip.tag, cu, die);
Packit b92951
		var->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		/* variable is visible outside of its enclosing cu */
Packit b92951
		var->external = dwarf_hasattr(die, DW_AT_external);
Packit b92951
		/* non-defining declaration of an object */
Packit b92951
		var->declaration = dwarf_hasattr(die, DW_AT_declaration);
Packit b92951
		var->scope = VSCOPE_UNKNOWN;
Packit b92951
		var->ip.addr = 0;
Packit b92951
		if (!var->declaration && cu->has_addr_info)
Packit b92951
			var->scope = dwarf__location(die, &var->ip.addr, &var->location);
Packit b92951
	}
Packit b92951
Packit b92951
	return var;
Packit b92951
}
Packit b92951
Packit b92951
static int tag__recode_dwarf_bitfield(struct tag *tag, struct cu *cu, uint16_t bit_size)
Packit b92951
{
Packit b92951
	int id;
Packit b92951
	type_id_t short_id;
Packit b92951
	struct tag *recoded;
Packit b92951
	/* in all the cases the name is at the same offset */
Packit b92951
	strings_t name = tag__namespace(tag)->name;
Packit b92951
Packit b92951
	switch (tag->tag) {
Packit b92951
	case DW_TAG_typedef: {
Packit b92951
		const struct dwarf_tag *dtag = tag->priv;
Packit b92951
		struct dwarf_tag *dtype = dwarf_cu__find_type_by_ref(cu->priv,
Packit b92951
								     &dtag->type);
Packit b92951
		struct tag *type = dtype->tag;
Packit b92951
Packit b92951
		id = tag__recode_dwarf_bitfield(type, cu, bit_size);
Packit b92951
		if (id < 0)
Packit b92951
			return id;
Packit b92951
Packit b92951
		struct type *new_typedef = obstack_zalloc(&cu->obstack,
Packit b92951
							  sizeof(*new_typedef));
Packit b92951
		if (new_typedef == NULL)
Packit b92951
			return -ENOMEM;
Packit b92951
Packit b92951
		recoded = (struct tag *)new_typedef;
Packit b92951
		recoded->tag = DW_TAG_typedef;
Packit b92951
		recoded->type = id;
Packit b92951
		new_typedef->namespace.name = tag__namespace(tag)->name;
Packit b92951
	}
Packit b92951
		break;
Packit b92951
Packit b92951
	case DW_TAG_const_type:
Packit b92951
	case DW_TAG_volatile_type: {
Packit b92951
		const struct dwarf_tag *dtag = tag->priv;
Packit b92951
		struct dwarf_tag *dtype = dwarf_cu__find_type_by_ref(cu->priv, &dtag->type);
Packit b92951
		struct tag *type = dtype->tag;
Packit b92951
Packit b92951
		id = tag__recode_dwarf_bitfield(type, cu, bit_size);
Packit b92951
		if (id == tag->type)
Packit b92951
			return id;
Packit b92951
Packit b92951
		recoded = obstack_zalloc(&cu->obstack, sizeof(*recoded));
Packit b92951
		if (recoded == NULL)
Packit b92951
			return -ENOMEM;
Packit b92951
Packit b92951
		recoded->tag = DW_TAG_volatile_type;
Packit b92951
		recoded->type = id;
Packit b92951
	}
Packit b92951
		break;
Packit b92951
Packit b92951
	case DW_TAG_base_type:
Packit b92951
		/*
Packit b92951
		 * Here we must search on the final, core cu, not on
Packit b92951
		 * the dwarf_cu as in dwarf there are no such things
Packit b92951
		 * as base_types of less than 8 bits, etc.
Packit b92951
		 */
Packit b92951
		recoded = cu__find_base_type_by_sname_and_size(cu, name, bit_size, &short_id);
Packit b92951
		if (recoded != NULL)
Packit b92951
			return short_id;
Packit b92951
Packit b92951
		struct base_type *new_bt = obstack_zalloc(&cu->obstack,
Packit b92951
							  sizeof(*new_bt));
Packit b92951
		if (new_bt == NULL)
Packit b92951
			return -ENOMEM;
Packit b92951
Packit b92951
		recoded = (struct tag *)new_bt;
Packit b92951
		recoded->tag = DW_TAG_base_type;
Packit b92951
		recoded->top_level = 1;
Packit b92951
		new_bt->name = name;
Packit b92951
		new_bt->bit_size = bit_size;
Packit b92951
		break;
Packit b92951
Packit b92951
	case DW_TAG_enumeration_type:
Packit b92951
		/*
Packit b92951
		 * Here we must search on the final, core cu, not on
Packit b92951
		 * the dwarf_cu as in dwarf there are no such things
Packit b92951
		 * as enumeration_types of less than 8 bits, etc.
Packit b92951
		 */
Packit b92951
		recoded = cu__find_enumeration_by_sname_and_size(cu, name, bit_size, &short_id);
Packit b92951
		if (recoded != NULL)
Packit b92951
			return short_id;
Packit b92951
Packit b92951
		struct type *alias = tag__type(tag);
Packit b92951
		struct type *new_enum = obstack_zalloc(&cu->obstack, sizeof(*new_enum));
Packit b92951
		if (new_enum == NULL)
Packit b92951
			return -ENOMEM;
Packit b92951
Packit b92951
		recoded = (struct tag *)new_enum;
Packit b92951
		recoded->tag = DW_TAG_enumeration_type;
Packit b92951
		recoded->top_level = 1;
Packit b92951
		new_enum->nr_members = alias->nr_members;
Packit b92951
		/*
Packit b92951
		 * Share the tags
Packit b92951
		 */
Packit b92951
		new_enum->namespace.tags.next = &alias->namespace.tags;
Packit b92951
		new_enum->namespace.shared_tags = 1;
Packit b92951
		new_enum->namespace.name = name;
Packit b92951
		new_enum->size = bit_size;
Packit b92951
		break;
Packit b92951
	default:
Packit b92951
		fprintf(stderr, "%s: tag=%s, name=%s, bit_size=%d\n",
Packit b92951
			__func__, dwarf_tag_name(tag->tag),
Packit b92951
			strings__ptr(strings, name), bit_size);
Packit b92951
		return -EINVAL;
Packit b92951
	}
Packit b92951
Packit b92951
	uint32_t new_id;
Packit b92951
	if (cu__add_tag(cu, recoded, &new_id) == 0)
Packit b92951
		return new_id;
Packit b92951
Packit b92951
	obstack_free(&cu->obstack, recoded);
Packit b92951
	return -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
int class_member__dwarf_recode_bitfield(struct class_member *member,
Packit b92951
					struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = member->tag.priv;
Packit b92951
	struct dwarf_tag *type = dwarf_cu__find_type_by_ref(cu->priv, &dtag->type);
Packit b92951
	int recoded_type_id;
Packit b92951
Packit b92951
	if (type == NULL)
Packit b92951
		return -ENOENT;
Packit b92951
Packit b92951
	recoded_type_id = tag__recode_dwarf_bitfield(type->tag, cu, member->bitfield_size);
Packit b92951
	if (recoded_type_id < 0)
Packit b92951
		return recoded_type_id;
Packit b92951
Packit b92951
	member->tag.type = recoded_type_id;
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static struct class_member *class_member__new(Dwarf_Die *die, struct cu *cu,
Packit b92951
					      bool in_union)
Packit b92951
{
Packit b92951
	struct class_member *member = tag__alloc(cu, sizeof(*member));
Packit b92951
Packit b92951
	if (member != NULL) {
Packit b92951
		tag__init(&member->tag, cu, die);
Packit b92951
		member->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		member->is_static   = !in_union && !dwarf_hasattr(die, DW_AT_data_member_location);
Packit b92951
		member->const_value = attr_numeric(die, DW_AT_const_value);
Packit b92951
		member->alignment = attr_numeric(die, DW_AT_alignment);
Packit b92951
		member->byte_offset = attr_offset(die, DW_AT_data_member_location);
Packit b92951
		/*
Packit b92951
		 * Bit offset calculated here is valid only for byte-aligned
Packit b92951
		 * fields. For bitfields on little-endian archs we need to
Packit b92951
		 * adjust them taking into account byte size of the field,
Packit b92951
		 * which might not be yet known. So we'll re-calculate bit
Packit b92951
		 * offset later, in class_member__cache_byte_size.
Packit b92951
		 */
Packit b92951
		member->bit_offset = member->byte_offset * 8;
Packit b92951
		/*
Packit b92951
		 * If DW_AT_byte_size is not present, byte size will be
Packit b92951
		 * determined later in class_member__cache_byte_size using
Packit b92951
		 * base integer/enum type
Packit b92951
		 */
Packit b92951
		member->byte_size = attr_numeric(die, DW_AT_byte_size);
Packit b92951
		member->bitfield_offset = attr_numeric(die, DW_AT_bit_offset);
Packit b92951
		member->bitfield_size = attr_numeric(die, DW_AT_bit_size);
Packit b92951
		member->bit_hole = 0;
Packit b92951
		member->bitfield_end = 0;
Packit b92951
		member->visited = 0;
Packit b92951
		member->accessibility = attr_numeric(die, DW_AT_accessibility);
Packit b92951
		member->virtuality    = attr_numeric(die, DW_AT_virtuality);
Packit b92951
		member->hole = 0;
Packit b92951
	}
Packit b92951
Packit b92951
	return member;
Packit b92951
}
Packit b92951
Packit b92951
static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct parameter *parm = tag__alloc(cu, sizeof(*parm));
Packit b92951
Packit b92951
	if (parm != NULL) {
Packit b92951
		tag__init(&parm->tag, cu, die);
Packit b92951
		parm->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
	}
Packit b92951
Packit b92951
	return parm;
Packit b92951
}
Packit b92951
Packit b92951
static struct inline_expansion *inline_expansion__new(Dwarf_Die *die,
Packit b92951
						      struct cu *cu)
Packit b92951
{
Packit b92951
	struct inline_expansion *exp = tag__alloc(cu, sizeof(*exp));
Packit b92951
Packit b92951
	if (exp != NULL) {
Packit b92951
		struct dwarf_tag *dtag = exp->ip.tag.priv;
Packit b92951
Packit b92951
		tag__init(&exp->ip.tag, cu, die);
Packit b92951
		dtag->decl_file =
Packit b92951
			strings__add(strings, attr_string(die, DW_AT_call_file));
Packit b92951
		dtag->decl_line = attr_numeric(die, DW_AT_call_line);
Packit b92951
		dtag->type = attr_type(die, DW_AT_abstract_origin);
Packit b92951
		exp->ip.addr = 0;
Packit b92951
		exp->high_pc = 0;
Packit b92951
Packit b92951
		if (!cu->has_addr_info)
Packit b92951
			goto out;
Packit b92951
Packit b92951
		if (dwarf_lowpc(die, &exp->ip.addr))
Packit b92951
			exp->ip.addr = 0;
Packit b92951
		if (dwarf_lowpc(die, &exp->high_pc))
Packit b92951
			exp->high_pc = 0;
Packit b92951
Packit b92951
		exp->size = exp->high_pc - exp->ip.addr;
Packit b92951
		if (exp->size == 0) {
Packit b92951
			Dwarf_Addr base, start;
Packit b92951
			ptrdiff_t offset = 0;
Packit b92951
Packit b92951
			while (1) {
Packit b92951
				offset = dwarf_ranges(die, offset, &base, &start,
Packit b92951
						      &exp->high_pc);
Packit b92951
				start = (unsigned long)start;
Packit b92951
				exp->high_pc = (unsigned long)exp->high_pc;
Packit b92951
				if (offset <= 0)
Packit b92951
					break;
Packit b92951
				exp->size += exp->high_pc - start;
Packit b92951
				if (exp->ip.addr == 0)
Packit b92951
					exp->ip.addr = start;
Packit b92951
			}
Packit b92951
		}
Packit b92951
	}
Packit b92951
out:
Packit b92951
	return exp;
Packit b92951
}
Packit b92951
Packit b92951
static struct label *label__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct label *label = tag__alloc(cu, sizeof(*label));
Packit b92951
Packit b92951
	if (label != NULL) {
Packit b92951
		tag__init(&label->ip.tag, cu, die);
Packit b92951
		label->name = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		if (!cu->has_addr_info || dwarf_lowpc(die, &label->ip.addr))
Packit b92951
			label->ip.addr = 0;
Packit b92951
	}
Packit b92951
Packit b92951
	return label;
Packit b92951
}
Packit b92951
Packit b92951
static struct class *class__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct class *class = tag__alloc_with_spec(cu, sizeof(*class));
Packit b92951
Packit b92951
	if (class != NULL) {
Packit b92951
		type__init(&class->type, die, cu);
Packit b92951
		INIT_LIST_HEAD(&class->vtable);
Packit b92951
		class->nr_vtable_entries =
Packit b92951
		  class->nr_holes =
Packit b92951
		  class->nr_bit_holes =
Packit b92951
		  class->padding =
Packit b92951
		  class->bit_padding = 0;
Packit b92951
		class->priv = NULL;
Packit b92951
	}
Packit b92951
Packit b92951
	return class;
Packit b92951
}
Packit b92951
Packit b92951
static void lexblock__init(struct lexblock *block, struct cu *cu,
Packit b92951
			   Dwarf_Die *die)
Packit b92951
{
Packit b92951
	Dwarf_Off high_pc;
Packit b92951
Packit b92951
	if (!cu->has_addr_info || dwarf_lowpc(die, &block->ip.addr)) {
Packit b92951
		block->ip.addr = 0;
Packit b92951
		block->size = 0;
Packit b92951
	} else if (dwarf_highpc(die, &high_pc))
Packit b92951
		block->size = 0;
Packit b92951
	else
Packit b92951
		block->size = high_pc - block->ip.addr;
Packit b92951
Packit b92951
	INIT_LIST_HEAD(&block->tags);
Packit b92951
Packit b92951
	block->size_inline_expansions =
Packit b92951
	block->nr_inline_expansions =
Packit b92951
		block->nr_labels =
Packit b92951
		block->nr_lexblocks =
Packit b92951
		block->nr_variables = 0;
Packit b92951
}
Packit b92951
Packit b92951
static struct lexblock *lexblock__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct lexblock *block = tag__alloc(cu, sizeof(*block));
Packit b92951
Packit b92951
	if (block != NULL) {
Packit b92951
		tag__init(&block->ip.tag, cu, die);
Packit b92951
		lexblock__init(block, cu, die);
Packit b92951
	}
Packit b92951
Packit b92951
	return block;
Packit b92951
}
Packit b92951
Packit b92951
static void ftype__init(struct ftype *ftype, Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	const uint16_t tag = dwarf_tag(die);
Packit b92951
	assert(tag == DW_TAG_subprogram || tag == DW_TAG_subroutine_type);
Packit b92951
Packit b92951
	tag__init(&ftype->tag, cu, die);
Packit b92951
	INIT_LIST_HEAD(&ftype->parms);
Packit b92951
	ftype->nr_parms	    = 0;
Packit b92951
	ftype->unspec_parms = 0;
Packit b92951
}
Packit b92951
Packit b92951
static struct ftype *ftype__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct ftype *ftype = tag__alloc(cu, sizeof(*ftype));
Packit b92951
Packit b92951
	if (ftype != NULL)
Packit b92951
		ftype__init(ftype, die, cu);
Packit b92951
Packit b92951
	return ftype;
Packit b92951
}
Packit b92951
Packit b92951
static struct function *function__new(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct function *func = tag__alloc_with_spec(cu, sizeof(*func));
Packit b92951
Packit b92951
	if (func != NULL) {
Packit b92951
		ftype__init(&func->proto, die, cu);
Packit b92951
		lexblock__init(&func->lexblock, cu, die);
Packit b92951
		func->name	      = strings__add(strings, attr_string(die, DW_AT_name));
Packit b92951
		func->linkage_name    = strings__add(strings, attr_string(die, DW_AT_MIPS_linkage_name));
Packit b92951
		func->inlined	      = attr_numeric(die, DW_AT_inline);
Packit b92951
		func->declaration     = dwarf_hasattr(die, DW_AT_declaration);
Packit b92951
		func->external	      = dwarf_hasattr(die, DW_AT_external);
Packit b92951
		func->abstract_origin = dwarf_hasattr(die, DW_AT_abstract_origin);
Packit b92951
		dwarf_tag__set_spec(func->proto.tag.priv,
Packit b92951
				    attr_type(die, DW_AT_specification));
Packit b92951
		func->accessibility   = attr_numeric(die, DW_AT_accessibility);
Packit b92951
		func->virtuality      = attr_numeric(die, DW_AT_virtuality);
Packit b92951
		INIT_LIST_HEAD(&func->vtable_node);
Packit b92951
		INIT_LIST_HEAD(&func->tool_node);
Packit b92951
		func->vtable_entry    = -1;
Packit b92951
		if (dwarf_hasattr(die, DW_AT_vtable_elem_location))
Packit b92951
			func->vtable_entry = attr_offset(die, DW_AT_vtable_elem_location);
Packit b92951
		func->cu_total_size_inline_expansions = 0;
Packit b92951
		func->cu_total_nr_inline_expansions = 0;
Packit b92951
		func->priv = NULL;
Packit b92951
	}
Packit b92951
Packit b92951
	return func;
Packit b92951
}
Packit b92951
Packit b92951
static uint64_t attr_upper_bound(Dwarf_Die *die)
Packit b92951
{
Packit b92951
	Dwarf_Attribute attr;
Packit b92951
Packit b92951
	if (dwarf_attr(die, DW_AT_upper_bound, &attr) != NULL) {
Packit b92951
		Dwarf_Word num;
Packit b92951
Packit b92951
		if (dwarf_formudata(&attr, &num) == 0) {
Packit b92951
			return (uintmax_t)num + 1;
Packit b92951
		}
Packit b92951
	} else if (dwarf_attr(die, DW_AT_count, &attr) != NULL) {
Packit b92951
		Dwarf_Word num;
Packit b92951
Packit b92951
		if (dwarf_formudata(&attr, &num) == 0) {
Packit b92951
			return (uintmax_t)num;
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static void __cu__tag_not_handled(Dwarf_Die *die, const char *fn)
Packit b92951
{
Packit b92951
	uint32_t tag = dwarf_tag(die);
Packit b92951
Packit b92951
	fprintf(stderr, "%s: DW_TAG_%s (%#x) @ <%#llx> not handled!\n",
Packit b92951
		fn, dwarf_tag_name(tag), tag,
Packit b92951
		(unsigned long long)dwarf_dieoffset(die));
Packit b92951
}
Packit b92951
Packit b92951
static struct tag unsupported_tag;
Packit b92951
Packit b92951
#define cu__tag_not_handled(die) __cu__tag_not_handled(die, __FUNCTION__)
Packit b92951
Packit b92951
static struct tag *__die__process_tag(Dwarf_Die *die, struct cu *cu,
Packit b92951
				      int toplevel, const char *fn);
Packit b92951
Packit b92951
#define die__process_tag(die, cu, toplevel) \
Packit b92951
	__die__process_tag(die, cu, toplevel, __FUNCTION__)
Packit b92951
Packit b92951
static struct tag *die__create_new_tag(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct tag *tag = tag__new(die, cu);
Packit b92951
Packit b92951
	if (tag != NULL) {
Packit b92951
		if (dwarf_haschildren(die))
Packit b92951
			fprintf(stderr, "%s: %s WITH children!\n", __func__,
Packit b92951
				dwarf_tag_name(tag->tag));
Packit b92951
	}
Packit b92951
Packit b92951
	return tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_ptr_to_member_type(Dwarf_Die *die,
Packit b92951
						      struct cu *cu)
Packit b92951
{
Packit b92951
	struct ptr_to_member_type *ptr = ptr_to_member_type__new(die, cu);
Packit b92951
Packit b92951
	return ptr ? &ptr->tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_class(Dwarf_Die *die,
Packit b92951
			      struct type *class, struct cu *cu);
Packit b92951
Packit b92951
static struct tag *die__create_new_class(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct class *class = class__new(die, cu);
Packit b92951
Packit b92951
	if (class != NULL &&
Packit b92951
	    dwarf_haschildren(die) != 0 &&
Packit b92951
	    dwarf_child(die, &child) == 0) {
Packit b92951
		if (die__process_class(&child, &class->type, cu) != 0) {
Packit b92951
			class__delete(class, cu);
Packit b92951
			class = NULL;
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	return class ? &class->type.namespace.tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_namespace(Dwarf_Die *die, struct namespace *namespace,
Packit b92951
				  struct cu *cu);
Packit b92951
Packit b92951
static struct tag *die__create_new_namespace(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct namespace *namespace = namespace__new(die, cu);
Packit b92951
Packit b92951
	if (namespace != NULL &&
Packit b92951
	    dwarf_haschildren(die) != 0 &&
Packit b92951
	    dwarf_child(die, &child) == 0) {
Packit b92951
		if (die__process_namespace(&child, namespace, cu) != 0) {
Packit b92951
			namespace__delete(namespace, cu);
Packit b92951
			namespace = NULL;
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	return namespace ? &namespace->tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_union(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct type *utype = type__new(die, cu);
Packit b92951
Packit b92951
	if (utype != NULL &&
Packit b92951
	    dwarf_haschildren(die) != 0 &&
Packit b92951
	    dwarf_child(die, &child) == 0) {
Packit b92951
		if (die__process_class(&child, utype, cu) != 0) {
Packit b92951
			type__delete(utype, cu);
Packit b92951
			utype = NULL;
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	return utype ? &utype->namespace.tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_base_type(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct base_type *base = base_type__new(die, cu);
Packit b92951
Packit b92951
	if (base == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (dwarf_haschildren(die))
Packit b92951
		fprintf(stderr, "%s: DW_TAG_base_type WITH children!\n",
Packit b92951
			__func__);
Packit b92951
Packit b92951
	return &base->tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_typedef(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct type *tdef = type__new(die, cu);
Packit b92951
Packit b92951
	if (tdef == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (dwarf_haschildren(die)) {
Packit b92951
		struct dwarf_tag *dtag = tdef->namespace.tag.priv;
Packit b92951
		fprintf(stderr, "%s: DW_TAG_typedef %llx WITH children!\n",
Packit b92951
			__func__, (unsigned long long)dtag->id);
Packit b92951
	}
Packit b92951
Packit b92951
	return &tdef->namespace.tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_array(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	/* "64 dimensions will be enough for everybody." acme, 2006 */
Packit b92951
	const uint8_t max_dimensions = 64;
Packit b92951
	uint32_t nr_entries[max_dimensions];
Packit b92951
	struct array_type *array = array_type__new(die, cu);
Packit b92951
Packit b92951
	if (array == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
Packit b92951
		return &array->tag;
Packit b92951
Packit b92951
	die = &chil;;
Packit b92951
	do {
Packit b92951
		if (dwarf_tag(die) == DW_TAG_subrange_type) {
Packit b92951
			nr_entries[array->dimensions++] = attr_upper_bound(die);
Packit b92951
			if (array->dimensions == max_dimensions) {
Packit b92951
				fprintf(stderr, "%s: only %u dimensions are "
Packit b92951
						"supported!\n",
Packit b92951
					__FUNCTION__, max_dimensions);
Packit b92951
				break;
Packit b92951
			}
Packit b92951
		} else
Packit b92951
			cu__tag_not_handled(die);
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	array->nr_entries = memdup(nr_entries,
Packit b92951
				   array->dimensions * sizeof(uint32_t), cu);
Packit b92951
	if (array->nr_entries == NULL)
Packit b92951
		goto out_free;
Packit b92951
Packit b92951
	return &array->tag;
Packit b92951
out_free:
Packit b92951
	obstack_free(&cu->obstack, array);
Packit b92951
	return NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_parameter(Dwarf_Die *die,
Packit b92951
					     struct ftype *ftype,
Packit b92951
					     struct lexblock *lexblock,
Packit b92951
					     struct cu *cu)
Packit b92951
{
Packit b92951
	struct parameter *parm = parameter__new(die, cu);
Packit b92951
Packit b92951
	if (parm == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (ftype != NULL)
Packit b92951
		ftype__add_parameter(ftype, parm);
Packit b92951
	else {
Packit b92951
		/*
Packit b92951
		 * DW_TAG_formal_parameters on a non DW_TAG_subprogram nor
Packit b92951
		 * DW_TAG_subroutine_type tag happens sometimes, likely due to
Packit b92951
		 * compiler optimizing away a inline expansion (at least this
Packit b92951
		 * was observed in some cases, such as in the Linux kernel
Packit b92951
		 * current_kernel_time function circa 2.6.20-rc5), keep it in
Packit b92951
		 * the lexblock tag list because it can be referenced as an
Packit b92951
		 * DW_AT_abstract_origin in another DW_TAG_formal_parameter.
Packit b92951
		*/
Packit b92951
		lexblock__add_tag(lexblock, &parm->tag);
Packit b92951
	}
Packit b92951
Packit b92951
	return &parm->tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_label(Dwarf_Die *die,
Packit b92951
					 struct lexblock *lexblock,
Packit b92951
					 struct cu *cu)
Packit b92951
{
Packit b92951
	struct label *label = label__new(die, cu);
Packit b92951
Packit b92951
	if (label == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	lexblock__add_label(lexblock, label);
Packit b92951
	return &label->ip.tag;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_variable(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct variable *var = variable__new(die, cu);
Packit b92951
Packit b92951
	return var ? &var->ip.tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_subroutine_type(Dwarf_Die *die,
Packit b92951
						   struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct ftype *ftype = ftype__new(die, cu);
Packit b92951
	struct tag *tag;
Packit b92951
Packit b92951
	if (ftype == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
Packit b92951
		goto out;
Packit b92951
Packit b92951
	die = &chil;;
Packit b92951
	do {
Packit b92951
		uint32_t id;
Packit b92951
Packit b92951
		switch (dwarf_tag(die)) {
Packit b92951
		case DW_TAG_formal_parameter:
Packit b92951
			tag = die__create_new_parameter(die, ftype, NULL, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_unspecified_parameters:
Packit b92951
			ftype->unspec_parms = 1;
Packit b92951
			continue;
Packit b92951
		default:
Packit b92951
			tag = die__process_tag(die, cu, 0);
Packit b92951
			if (tag == NULL)
Packit b92951
				goto out_delete;
Packit b92951
Packit b92951
			if (cu__add_tag(cu, tag, &id) < 0)
Packit b92951
				goto out_delete_tag;
Packit b92951
Packit b92951
			goto hash;
Packit b92951
		}
Packit b92951
Packit b92951
		if (tag == NULL)
Packit b92951
			goto out_delete;
Packit b92951
Packit b92951
		if (cu__table_add_tag(cu, tag, &id) < 0)
Packit b92951
			goto out_delete_tag;
Packit b92951
hash:
Packit b92951
		cu__hash(cu, tag);
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
		dtag->small_id = id;
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
out:
Packit b92951
	return &ftype->tag;
Packit b92951
out_delete_tag:
Packit b92951
	tag__delete(tag, cu);
Packit b92951
out_delete:
Packit b92951
	ftype__delete(ftype, cu);
Packit b92951
	return NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_enumeration(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct type *enumeration = type__new(die, cu);
Packit b92951
Packit b92951
	if (enumeration == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (enumeration->size == 0)
Packit b92951
		enumeration->size = sizeof(int) * 8;
Packit b92951
	else
Packit b92951
		enumeration->size *= 8;
Packit b92951
Packit b92951
	if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0) {
Packit b92951
		/* Seen on libQtCore.so.4.3.4.debug,
Packit b92951
		 * class QAbstractFileEngineIterator, enum EntryInfoType */
Packit b92951
		goto out;
Packit b92951
	}
Packit b92951
Packit b92951
	die = &chil;;
Packit b92951
	do {
Packit b92951
		struct enumerator *enumerator;
Packit b92951
Packit b92951
		if (dwarf_tag(die) != DW_TAG_enumerator) {
Packit b92951
			cu__tag_not_handled(die);
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
		enumerator = enumerator__new(die, cu);
Packit b92951
		if (enumerator == NULL)
Packit b92951
			goto out_delete;
Packit b92951
Packit b92951
		enumeration__add(enumeration, enumerator);
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
out:
Packit b92951
	return &enumeration->namespace.tag;
Packit b92951
out_delete:
Packit b92951
	enumeration__delete(enumeration, cu);
Packit b92951
	return NULL;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_class(Dwarf_Die *die, struct type *class,
Packit b92951
			      struct cu *cu)
Packit b92951
{
Packit b92951
	const bool is_union = tag__is_union(&class->namespace.tag);
Packit b92951
Packit b92951
	do {
Packit b92951
		switch (dwarf_tag(die)) {
Packit b92951
#ifdef STB_GNU_UNIQUE
Packit b92951
		case DW_TAG_GNU_formal_parameter_pack:
Packit b92951
		case DW_TAG_GNU_template_parameter_pack:
Packit b92951
		case DW_TAG_GNU_template_template_param:
Packit b92951
#endif
Packit b92951
		case DW_TAG_template_type_parameter:
Packit b92951
		case DW_TAG_template_value_parameter:
Packit b92951
			/*
Packit b92951
			 * FIXME: probably we'll have to attach this as a list of
Packit b92951
			 * template parameters to use at class__fprintf time...
Packit b92951
			 *
Packit b92951
			 * See:
Packit b92951
			 * https://gcc.gnu.org/wiki/TemplateParmsDwarf
Packit b92951
			 */
Packit b92951
			tag__print_not_supported(dwarf_tag(die));
Packit b92951
			continue;
Packit b92951
		case DW_TAG_inheritance:
Packit b92951
		case DW_TAG_member: {
Packit b92951
			struct class_member *member = class_member__new(die, cu, is_union);
Packit b92951
Packit b92951
			if (member == NULL)
Packit b92951
				return -ENOMEM;
Packit b92951
Packit b92951
			if (cu__is_c_plus_plus(cu)) {
Packit b92951
				uint32_t id;
Packit b92951
Packit b92951
				if (cu__table_add_tag(cu, &member->tag, &id) < 0) {
Packit b92951
					class_member__delete(member, cu);
Packit b92951
					return -ENOMEM;
Packit b92951
				}
Packit b92951
Packit b92951
				struct dwarf_tag *dtag = member->tag.priv;
Packit b92951
				dtag->small_id = id;
Packit b92951
			}
Packit b92951
Packit b92951
			type__add_member(class, member);
Packit b92951
			cu__hash(cu, &member->tag);
Packit b92951
		}
Packit b92951
			continue;
Packit b92951
		default: {
Packit b92951
			struct tag *tag = die__process_tag(die, cu, 0);
Packit b92951
Packit b92951
			if (tag == NULL)
Packit b92951
				return -ENOMEM;
Packit b92951
Packit b92951
			uint32_t id;
Packit b92951
Packit b92951
			if (cu__table_add_tag(cu, tag, &id) < 0) {
Packit b92951
				tag__delete(tag, cu);
Packit b92951
				return -ENOMEM;
Packit b92951
			}
Packit b92951
Packit b92951
			struct dwarf_tag *dtag = tag->priv;
Packit b92951
			dtag->small_id = id;
Packit b92951
Packit b92951
			namespace__add_tag(&class->namespace, tag);
Packit b92951
			cu__hash(cu, tag);
Packit b92951
			if (tag__is_function(tag)) {
Packit b92951
				struct function *fself = tag__function(tag);
Packit b92951
Packit b92951
				if (fself->vtable_entry != -1)
Packit b92951
					class__add_vtable_entry(type__class(class), fself);
Packit b92951
			}
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
		}
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_namespace(Dwarf_Die *die, struct namespace *namespace,
Packit b92951
				  struct cu *cu)
Packit b92951
{
Packit b92951
	struct tag *tag;
Packit b92951
	do {
Packit b92951
		tag = die__process_tag(die, cu, 0);
Packit b92951
		if (tag == NULL)
Packit b92951
			goto out_enomem;
Packit b92951
Packit b92951
		uint32_t id;
Packit b92951
		if (cu__table_add_tag(cu, tag, &id) < 0)
Packit b92951
			goto out_delete_tag;
Packit b92951
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
		dtag->small_id = id;
Packit b92951
Packit b92951
		namespace__add_tag(namespace, tag);
Packit b92951
		cu__hash(cu, tag);
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	return 0;
Packit b92951
out_delete_tag:
Packit b92951
	tag__delete(tag, cu);
Packit b92951
out_enomem:
Packit b92951
	return -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
Packit b92951
				  struct lexblock *lexblock, struct cu *cu);
Packit b92951
Packit b92951
static int die__create_new_lexblock(Dwarf_Die *die,
Packit b92951
				    struct cu *cu, struct lexblock *father)
Packit b92951
{
Packit b92951
	struct lexblock *lexblock = lexblock__new(die, cu);
Packit b92951
Packit b92951
	if (lexblock != NULL) {
Packit b92951
		if (die__process_function(die, NULL, lexblock, cu) != 0)
Packit b92951
			goto out_delete;
Packit b92951
	}
Packit b92951
	if (father != NULL)
Packit b92951
		lexblock__add_lexblock(father, lexblock);
Packit b92951
	return 0;
Packit b92951
out_delete:
Packit b92951
	lexblock__delete(lexblock, cu);
Packit b92951
	return -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
Packit b92951
						    struct lexblock *lexblock,
Packit b92951
						    struct cu *cu);
Packit b92951
Packit b92951
static int die__process_inline_expansion(Dwarf_Die *die, struct lexblock *lexblock, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct tag *tag;
Packit b92951
Packit b92951
	if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
Packit b92951
		return 0;
Packit b92951
Packit b92951
	die = &chil;;
Packit b92951
	do {
Packit b92951
		uint32_t id;
Packit b92951
Packit b92951
		switch (dwarf_tag(die)) {
Packit b92951
		case DW_TAG_GNU_call_site:
Packit b92951
		case DW_TAG_GNU_call_site_parameter:
Packit b92951
			/*
Packit b92951
 			 * FIXME: read http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open
Packit b92951
 			 * and write proper support.
Packit b92951
			 *
Packit b92951
			 * From a quick read there is not much we can use in
Packit b92951
			 * the existing dwarves tools, so just stop warning the user,
Packit b92951
			 * developers will find these notes if wanting to use in a
Packit b92951
			 * new tool.
Packit b92951
			 */
Packit b92951
			continue;
Packit b92951
		case DW_TAG_lexical_block:
Packit b92951
			if (die__create_new_lexblock(die, cu, lexblock) != 0)
Packit b92951
				goto out_enomem;
Packit b92951
			continue;
Packit b92951
		case DW_TAG_formal_parameter:
Packit b92951
			/*
Packit b92951
			 * FIXME:
Packit b92951
			 * So far DW_TAG_inline_routine had just an
Packit b92951
			 * abstract origin, but starting with
Packit b92951
			 * /usr/lib/openoffice.org/basis3.0/program/libdbalx.so
Packit b92951
			 * I realized it really has to be handled as a
Packit b92951
			 * DW_TAG_function... Lets just get the types
Packit b92951
			 * for 1.8, then fix this properly.
Packit b92951
			 *
Packit b92951
			 * cu__tag_not_handled(die);
Packit b92951
			 */
Packit b92951
			continue;
Packit b92951
		case DW_TAG_inlined_subroutine:
Packit b92951
			tag = die__create_new_inline_expansion(die, lexblock, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_label:
Packit b92951
			tag = die__create_new_label(die, lexblock, cu);
Packit b92951
			break;
Packit b92951
		default:
Packit b92951
			tag = die__process_tag(die, cu, 0);
Packit b92951
			if (tag == NULL)
Packit b92951
				goto out_enomem;
Packit b92951
Packit b92951
			if (tag == &unsupported_tag)
Packit b92951
				continue;
Packit b92951
Packit b92951
			if (cu__add_tag(cu, tag, &id) < 0)
Packit b92951
				goto out_delete_tag;
Packit b92951
			goto hash;
Packit b92951
		}
Packit b92951
Packit b92951
		if (tag == NULL)
Packit b92951
			goto out_enomem;
Packit b92951
Packit b92951
		if (cu__table_add_tag(cu, tag, &id) < 0)
Packit b92951
			goto out_delete_tag;
Packit b92951
hash:
Packit b92951
		cu__hash(cu, tag);
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
		dtag->small_id = id;
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	return 0;
Packit b92951
out_delete_tag:
Packit b92951
	tag__delete(tag, cu);
Packit b92951
out_enomem:
Packit b92951
	return -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
Packit b92951
						    struct lexblock *lexblock,
Packit b92951
						    struct cu *cu)
Packit b92951
{
Packit b92951
	struct inline_expansion *exp = inline_expansion__new(die, cu);
Packit b92951
Packit b92951
	if (exp == NULL)
Packit b92951
		return NULL;
Packit b92951
Packit b92951
	if (die__process_inline_expansion(die, lexblock, cu) != 0) {
Packit b92951
		obstack_free(&cu->obstack, exp);
Packit b92951
		return NULL;
Packit b92951
	}
Packit b92951
Packit b92951
	if (lexblock != NULL)
Packit b92951
		lexblock__add_inline_expansion(lexblock, exp);
Packit b92951
	return &exp->ip.tag;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
Packit b92951
				 struct lexblock *lexblock, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	struct tag *tag;
Packit b92951
Packit b92951
	if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
Packit b92951
		return 0;
Packit b92951
Packit b92951
	die = &chil;;
Packit b92951
	do {
Packit b92951
		uint32_t id;
Packit b92951
Packit b92951
		switch (dwarf_tag(die)) {
Packit b92951
		case DW_TAG_GNU_call_site:
Packit b92951
		case DW_TAG_GNU_call_site_parameter:
Packit b92951
			/*
Packit b92951
			 * XXX: read http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open
Packit b92951
			 * and write proper support.
Packit b92951
			 *
Packit b92951
			 * From a quick read there is not much we can use in
Packit b92951
			 * the existing dwarves tools, so just stop warning the user,
Packit b92951
			 * developers will find these notes if wanting to use in a
Packit b92951
			 * new tool.
Packit b92951
			 */
Packit b92951
			continue;
Packit b92951
		case DW_TAG_dwarf_procedure:
Packit b92951
			/*
Packit b92951
			 * Ignore it, just scope expressions, that we have no use for (so far).
Packit b92951
			 */
Packit b92951
			continue;
Packit b92951
#ifdef STB_GNU_UNIQUE
Packit b92951
		case DW_TAG_GNU_formal_parameter_pack:
Packit b92951
		case DW_TAG_GNU_template_parameter_pack:
Packit b92951
		case DW_TAG_GNU_template_template_param:
Packit b92951
#endif
Packit b92951
		case DW_TAG_template_type_parameter:
Packit b92951
		case DW_TAG_template_value_parameter:
Packit b92951
			/* FIXME: probably we'll have to attach this as a list of
Packit b92951
 			 * template parameters to use at class__fprintf time... 
Packit b92951
 			 * See die__process_class */
Packit b92951
			tag__print_not_supported(dwarf_tag(die));
Packit b92951
			continue;
Packit b92951
		case DW_TAG_formal_parameter:
Packit b92951
			tag = die__create_new_parameter(die, ftype, lexblock, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_variable:
Packit b92951
			tag = die__create_new_variable(die, cu);
Packit b92951
			if (tag == NULL)
Packit b92951
				goto out_enomem;
Packit b92951
			lexblock__add_variable(lexblock, tag__variable(tag));
Packit b92951
			break;
Packit b92951
		case DW_TAG_unspecified_parameters:
Packit b92951
			if (ftype != NULL)
Packit b92951
				ftype->unspec_parms = 1;
Packit b92951
			continue;
Packit b92951
		case DW_TAG_label:
Packit b92951
			tag = die__create_new_label(die, lexblock, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_inlined_subroutine:
Packit b92951
			tag = die__create_new_inline_expansion(die, lexblock, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_lexical_block:
Packit b92951
			if (die__create_new_lexblock(die, cu, lexblock) != 0)
Packit b92951
				goto out_enomem;
Packit b92951
			continue;
Packit b92951
		default:
Packit b92951
			tag = die__process_tag(die, cu, 0);
Packit b92951
Packit b92951
			if (tag == NULL)
Packit b92951
				goto out_enomem;
Packit b92951
Packit b92951
			if (tag == &unsupported_tag)
Packit b92951
				continue;
Packit b92951
Packit b92951
			if (cu__add_tag(cu, tag, &id) < 0)
Packit b92951
				goto out_delete_tag;
Packit b92951
Packit b92951
			goto hash;
Packit b92951
		}
Packit b92951
Packit b92951
		if (tag == NULL)
Packit b92951
			goto out_enomem;
Packit b92951
Packit b92951
		if (cu__table_add_tag(cu, tag, &id) < 0)
Packit b92951
			goto out_delete_tag;
Packit b92951
hash:
Packit b92951
		cu__hash(cu, tag);
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
		dtag->small_id = id;
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	return 0;
Packit b92951
out_delete_tag:
Packit b92951
	tag__delete(tag, cu);
Packit b92951
out_enomem:
Packit b92951
	return -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *die__create_new_function(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	struct function *function = function__new(die, cu);
Packit b92951
Packit b92951
	if (function != NULL &&
Packit b92951
	    die__process_function(die, &function->proto,
Packit b92951
				  &function->lexblock, cu) != 0) {
Packit b92951
		function__delete(function, cu);
Packit b92951
		function = NULL;
Packit b92951
	}
Packit b92951
Packit b92951
	return function ? &function->proto.tag : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static struct tag *__die__process_tag(Dwarf_Die *die, struct cu *cu,
Packit b92951
				      int top_level, const char *fn)
Packit b92951
{
Packit b92951
	struct tag *tag;
Packit b92951
Packit b92951
	switch (dwarf_tag(die)) {
Packit b92951
	case DW_TAG_array_type:
Packit b92951
		tag = die__create_new_array(die, cu);		break;
Packit b92951
	case DW_TAG_base_type:
Packit b92951
		tag = die__create_new_base_type(die, cu);	break;
Packit b92951
	case DW_TAG_const_type:
Packit b92951
	case DW_TAG_imported_declaration:
Packit b92951
	case DW_TAG_imported_module:
Packit b92951
	case DW_TAG_pointer_type:
Packit b92951
	case DW_TAG_reference_type:
Packit b92951
	case DW_TAG_restrict_type:
Packit b92951
	case DW_TAG_unspecified_type:
Packit b92951
	case DW_TAG_volatile_type:
Packit b92951
		tag = die__create_new_tag(die, cu);		break;
Packit b92951
	case DW_TAG_ptr_to_member_type:
Packit b92951
		tag = die__create_new_ptr_to_member_type(die, cu); break;
Packit b92951
	case DW_TAG_enumeration_type:
Packit b92951
		tag = die__create_new_enumeration(die, cu);	break;
Packit b92951
	case DW_TAG_namespace:
Packit b92951
		tag = die__create_new_namespace(die, cu);	break;
Packit b92951
	case DW_TAG_class_type:
Packit b92951
	case DW_TAG_interface_type:
Packit b92951
	case DW_TAG_structure_type:
Packit b92951
		tag = die__create_new_class(die, cu);		break;
Packit b92951
	case DW_TAG_subprogram:
Packit b92951
		tag = die__create_new_function(die, cu);	break;
Packit b92951
	case DW_TAG_subroutine_type:
Packit b92951
		tag = die__create_new_subroutine_type(die, cu);	break;
Packit b92951
	case DW_TAG_rvalue_reference_type:
Packit b92951
	case DW_TAG_typedef:
Packit b92951
		tag = die__create_new_typedef(die, cu);		break;
Packit b92951
	case DW_TAG_union_type:
Packit b92951
		tag = die__create_new_union(die, cu);		break;
Packit b92951
	case DW_TAG_variable:
Packit b92951
		tag = die__create_new_variable(die, cu);	break;
Packit b92951
	default:
Packit b92951
		__cu__tag_not_handled(die, fn);
Packit b92951
		/* fall thru */
Packit b92951
	case DW_TAG_dwarf_procedure:
Packit b92951
		/*
Packit b92951
		 * Ignore it, just scope expressions, that we have no use for (so far).
Packit b92951
		 */
Packit b92951
		tag = &unsupported_tag;
Packit b92951
		break;
Packit b92951
	}
Packit b92951
Packit b92951
	if (tag != NULL)
Packit b92951
		tag->top_level = top_level;
Packit b92951
Packit b92951
	return tag;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_unit(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	do {
Packit b92951
		struct tag *tag = die__process_tag(die, cu, 1);
Packit b92951
		if (tag == NULL)
Packit b92951
			return -ENOMEM;
Packit b92951
Packit b92951
		if (tag == &unsupported_tag)
Packit b92951
			continue;
Packit b92951
Packit b92951
		uint32_t id;
Packit b92951
		cu__add_tag(cu, tag, &id;;
Packit b92951
		cu__hash(cu, tag);
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
		dtag->small_id = id;
Packit b92951
	} while (dwarf_siblingof(die, die) == 0);
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static void __tag__print_type_not_found(struct tag *tag, const char *func)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	fprintf(stderr, "%s: couldn't find %#llx type for %#llx (%s)!\n", func,
Packit b92951
		(unsigned long long)dtag->type.off, (unsigned long long)dtag->id,
Packit b92951
		dwarf_tag_name(tag->tag));
Packit b92951
}
Packit b92951
Packit b92951
#define tag__print_type_not_found(tag) \
Packit b92951
	__tag__print_type_not_found(tag, __func__)
Packit b92951
Packit b92951
static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu);
Packit b92951
Packit b92951
static int namespace__recode_dwarf_types(struct tag *tag, struct cu *cu)
Packit b92951
{
Packit b92951
	struct tag *pos;
Packit b92951
	struct dwarf_cu *dcu = cu->priv;
Packit b92951
	struct namespace *ns = tag__namespace(tag);
Packit b92951
Packit b92951
	namespace__for_each_tag(ns, pos) {
Packit b92951
		struct dwarf_tag *dtype;
Packit b92951
		struct dwarf_tag *dpos = pos->priv;
Packit b92951
Packit b92951
		if (tag__has_namespace(pos)) {
Packit b92951
			if (namespace__recode_dwarf_types(pos, cu))
Packit b92951
				return -1;
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
Packit b92951
		switch (pos->tag) {
Packit b92951
		case DW_TAG_member: {
Packit b92951
			struct class_member *member = tag__class_member(pos);
Packit b92951
			/*
Packit b92951
			 * We may need to recode the type, possibly creating a
Packit b92951
			 * suitably sized new base_type
Packit b92951
			 */
Packit b92951
			if (member->bitfield_size != 0 && !no_bitfield_type_recode) {
Packit b92951
				if (class_member__dwarf_recode_bitfield(member, cu))
Packit b92951
					return -1;
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
		}
Packit b92951
			break;
Packit b92951
		case DW_TAG_subroutine_type:
Packit b92951
		case DW_TAG_subprogram:
Packit b92951
			ftype__recode_dwarf_types(pos, cu);
Packit b92951
			break;
Packit b92951
		case DW_TAG_imported_module:
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu, &dpos->type);
Packit b92951
			goto check_type;
Packit b92951
		/* Can be for both types and non types */
Packit b92951
		case DW_TAG_imported_declaration:
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu, &dpos->type);
Packit b92951
			if (dtype != NULL)
Packit b92951
				goto next;
Packit b92951
			goto find_type;
Packit b92951
		}
Packit b92951
Packit b92951
		if (dpos->type.off == 0) /* void */
Packit b92951
			continue;
Packit b92951
find_type:
Packit b92951
		dtype = dwarf_cu__find_type_by_ref(dcu, &dpos->type);
Packit b92951
check_type:
Packit b92951
		if (dtype == NULL) {
Packit b92951
			tag__print_type_not_found(pos);
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
next:
Packit b92951
		pos->type = dtype->small_id;
Packit b92951
	}
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static void type__recode_dwarf_specification(struct tag *tag, struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtype;
Packit b92951
	struct type *t = tag__type(tag);
Packit b92951
	dwarf_off_ref specification = dwarf_tag__spec(tag->priv);
Packit b92951
Packit b92951
	if (t->namespace.name != 0 || specification.off == 0)
Packit b92951
		return;
Packit b92951
Packit b92951
	dtype = dwarf_cu__find_type_by_ref(cu->priv, &specification);
Packit b92951
	if (dtype != NULL)
Packit b92951
		t->namespace.name = tag__namespace(dtype->tag)->name;
Packit b92951
	else {
Packit b92951
		struct dwarf_tag *dtag = tag->priv;
Packit b92951
Packit b92951
		fprintf(stderr,
Packit b92951
			"%s: couldn't find name for "
Packit b92951
			"class %#llx, specification=%#llx\n", __func__,
Packit b92951
			(unsigned long long)dtag->id,
Packit b92951
			(unsigned long long)specification.off);
Packit b92951
	}
Packit b92951
}
Packit b92951
Packit b92951
static void __tag__print_abstract_origin_not_found(struct tag *tag,
Packit b92951
						   const char *func)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	fprintf(stderr,
Packit b92951
		"%s: couldn't find %#llx abstract_origin for %#llx (%s)!\n",
Packit b92951
		func, (unsigned long long)dtag->abstract_origin.off,
Packit b92951
		(unsigned long long)dtag->id,
Packit b92951
		dwarf_tag_name(tag->tag));
Packit b92951
}
Packit b92951
Packit b92951
#define tag__print_abstract_origin_not_found(tag ) \
Packit b92951
	__tag__print_abstract_origin_not_found(tag, __func__)
Packit b92951
Packit b92951
static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu)
Packit b92951
{
Packit b92951
	struct parameter *pos;
Packit b92951
	struct dwarf_cu *dcu = cu->priv;
Packit b92951
	struct ftype *type = tag__ftype(tag);
Packit b92951
Packit b92951
	ftype__for_each_parameter(type, pos) {
Packit b92951
		struct dwarf_tag *dpos = pos->tag.priv;
Packit b92951
		struct dwarf_tag *dtype;
Packit b92951
Packit b92951
		if (dpos->type.off == 0) {
Packit b92951
			if (dpos->abstract_origin.off == 0) {
Packit b92951
				/* Function without parameters */
Packit b92951
				pos->tag.type = 0;
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu, &dpos->abstract_origin);
Packit b92951
			if (dtype == NULL) {
Packit b92951
				tag__print_abstract_origin_not_found(&pos->tag);
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
			pos->name = tag__parameter(dtype->tag)->name;
Packit b92951
			pos->tag.type = dtype->tag->type;
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
Packit b92951
		dtype = dwarf_cu__find_type_by_ref(dcu, &dpos->type);
Packit b92951
		if (dtype == NULL) {
Packit b92951
			tag__print_type_not_found(&pos->tag);
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
		pos->tag.type = dtype->small_id;
Packit b92951
	}
Packit b92951
}
Packit b92951
Packit b92951
static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu)
Packit b92951
{
Packit b92951
	struct tag *pos;
Packit b92951
	struct dwarf_cu *dcu = cu->priv;
Packit b92951
Packit b92951
	list_for_each_entry(pos, &tag->tags, node) {
Packit b92951
		struct dwarf_tag *dpos = pos->priv;
Packit b92951
		struct dwarf_tag *dtype;
Packit b92951
Packit b92951
		switch (pos->tag) {
Packit b92951
		case DW_TAG_lexical_block:
Packit b92951
			lexblock__recode_dwarf_types(tag__lexblock(pos), cu);
Packit b92951
			continue;
Packit b92951
		case DW_TAG_inlined_subroutine:
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu, &dpos->type);
Packit b92951
			if (dtype == NULL) {
Packit b92951
				tag__print_type_not_found(pos);
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
			ftype__recode_dwarf_types(dtype->tag, cu);
Packit b92951
			continue;
Packit b92951
Packit b92951
		case DW_TAG_formal_parameter:
Packit b92951
			if (dpos->type.off != 0)
Packit b92951
				break;
Packit b92951
Packit b92951
			struct parameter *fp = tag__parameter(pos);
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu,
Packit b92951
							  &dpos->abstract_origin);
Packit b92951
			if (dtype == NULL) {
Packit b92951
				tag__print_abstract_origin_not_found(pos);
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
			fp->name = tag__parameter(dtype->tag)->name;
Packit b92951
			pos->type = dtype->tag->type;
Packit b92951
			continue;
Packit b92951
Packit b92951
		case DW_TAG_variable:
Packit b92951
			if (dpos->type.off != 0)
Packit b92951
				break;
Packit b92951
Packit b92951
			struct variable *var = tag__variable(pos);
Packit b92951
Packit b92951
			if (dpos->abstract_origin.off == 0) {
Packit b92951
				/*
Packit b92951
				 * DW_TAG_variable completely empty was
Packit b92951
				 * found on libQtGui.so.4.3.4.debug
Packit b92951
				 * <3><d6ea1>: Abbrev Number: 164 (DW_TAG_variable)
Packit b92951
				 */
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu,
Packit b92951
							  &dpos->abstract_origin);
Packit b92951
			if (dtype == NULL) {
Packit b92951
				tag__print_abstract_origin_not_found(pos);
Packit b92951
				continue;
Packit b92951
			}
Packit b92951
			var->name = tag__variable(dtype->tag)->name;
Packit b92951
			pos->type = dtype->tag->type;
Packit b92951
			continue;
Packit b92951
Packit b92951
		case DW_TAG_label: {
Packit b92951
			struct label *l = tag__label(pos);
Packit b92951
Packit b92951
			if (dpos->abstract_origin.off == 0)
Packit b92951
				continue;
Packit b92951
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(dcu, &dpos->abstract_origin);
Packit b92951
			if (dtype != NULL)
Packit b92951
				l->name = tag__label(dtype->tag)->name;
Packit b92951
			else
Packit b92951
				tag__print_abstract_origin_not_found(pos);
Packit b92951
		}
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
Packit b92951
		dtype = dwarf_cu__find_type_by_ref(dcu, &dpos->type);
Packit b92951
		if (dtype == NULL) {
Packit b92951
			tag__print_type_not_found(pos);
Packit b92951
			continue;
Packit b92951
		}
Packit b92951
		pos->type = dtype->small_id;
Packit b92951
	}
Packit b92951
}
Packit b92951
Packit b92951
static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	struct dwarf_tag *dtype;
Packit b92951
Packit b92951
	/* Check if this is an already recoded bitfield */
Packit b92951
	if (dtag == NULL)
Packit b92951
		return 0;
Packit b92951
Packit b92951
	if (tag__is_type(tag))
Packit b92951
		type__recode_dwarf_specification(tag, cu);
Packit b92951
Packit b92951
	if (tag__has_namespace(tag))
Packit b92951
		return namespace__recode_dwarf_types(tag, cu);
Packit b92951
Packit b92951
	switch (tag->tag) {
Packit b92951
	case DW_TAG_subprogram: {
Packit b92951
		struct function *fn = tag__function(tag);
Packit b92951
Packit b92951
		if (fn->name == 0)  {
Packit b92951
			dwarf_off_ref specification = dwarf_tag__spec(dtag);
Packit b92951
			if (dtag->abstract_origin.off == 0 &&
Packit b92951
			    specification.off == 0) {
Packit b92951
				/*
Packit b92951
				 * Found on libQtGui.so.4.3.4.debug
Packit b92951
				 *  <3><1423de>: Abbrev Number: 209 (DW_TAG_subprogram)
Packit b92951
				 *      <1423e0>   DW_AT_declaration : 1
Packit b92951
				 */
Packit b92951
				return 0;
Packit b92951
			}
Packit b92951
			dtype = dwarf_cu__find_tag_by_ref(cu->priv, &dtag->abstract_origin);
Packit b92951
			if (dtype == NULL)
Packit b92951
				dtype = dwarf_cu__find_tag_by_ref(cu->priv, &specification);
Packit b92951
			if (dtype != NULL)
Packit b92951
				fn->name = tag__function(dtype->tag)->name;
Packit b92951
			else {
Packit b92951
				fprintf(stderr,
Packit b92951
					"%s: couldn't find name for "
Packit b92951
					"function %#llx, abstract_origin=%#llx,"
Packit b92951
					" specification=%#llx\n", __func__,
Packit b92951
					(unsigned long long)dtag->id,
Packit b92951
					(unsigned long long)dtag->abstract_origin.off,
Packit b92951
					(unsigned long long)specification.off);
Packit b92951
			}
Packit b92951
		}
Packit b92951
		lexblock__recode_dwarf_types(&fn->lexblock, cu);
Packit b92951
	}
Packit b92951
		/* Fall thru */
Packit b92951
Packit b92951
	case DW_TAG_subroutine_type:
Packit b92951
		ftype__recode_dwarf_types(tag, cu);
Packit b92951
		/* Fall thru, for the function return type */
Packit b92951
		break;
Packit b92951
Packit b92951
	case DW_TAG_lexical_block:
Packit b92951
		lexblock__recode_dwarf_types(tag__lexblock(tag), cu);
Packit b92951
		return 0;
Packit b92951
Packit b92951
	case DW_TAG_ptr_to_member_type: {
Packit b92951
		struct ptr_to_member_type *pt = tag__ptr_to_member_type(tag);
Packit b92951
Packit b92951
		dtype = dwarf_cu__find_type_by_ref(cu->priv, &dtag->containing_type);
Packit b92951
		if (dtype != NULL)
Packit b92951
			pt->containing_type = dtype->small_id;
Packit b92951
		else {
Packit b92951
			fprintf(stderr,
Packit b92951
				"%s: couldn't find type for "
Packit b92951
				"containing_type %#llx, containing_type=%#llx\n",
Packit b92951
				__func__,
Packit b92951
				(unsigned long long)dtag->id,
Packit b92951
				(unsigned long long)dtag->containing_type.off);
Packit b92951
		}
Packit b92951
	}
Packit b92951
		break;
Packit b92951
Packit b92951
	case DW_TAG_namespace:
Packit b92951
		return namespace__recode_dwarf_types(tag, cu);
Packit b92951
	/* Damn, DW_TAG_inlined_subroutine is an special case
Packit b92951
           as dwarf_tag->id is in fact an abtract origin, i.e. must be
Packit b92951
	   looked up in the tags_table, not in the types_table.
Packit b92951
	   The others also point to routines, so are in tags_table */
Packit b92951
	case DW_TAG_inlined_subroutine:
Packit b92951
	case DW_TAG_imported_module:
Packit b92951
		dtype = dwarf_cu__find_tag_by_ref(cu->priv, &dtag->type);
Packit b92951
		goto check_type;
Packit b92951
	/* Can be for both types and non types */
Packit b92951
	case DW_TAG_imported_declaration:
Packit b92951
		dtype = dwarf_cu__find_tag_by_ref(cu->priv, &dtag->type);
Packit b92951
		if (dtype != NULL)
Packit b92951
			goto out;
Packit b92951
		goto find_type;
Packit b92951
	}
Packit b92951
Packit b92951
	if (dtag->type.off == 0) {
Packit b92951
		tag->type = 0; /* void */
Packit b92951
		return 0;
Packit b92951
	}
Packit b92951
Packit b92951
find_type:
Packit b92951
	dtype = dwarf_cu__find_type_by_ref(cu->priv, &dtag->type);
Packit b92951
check_type:
Packit b92951
	if (dtype == NULL) {
Packit b92951
		tag__print_type_not_found(tag);
Packit b92951
		return 0;
Packit b92951
	}
Packit b92951
out:
Packit b92951
	tag->type = dtype->small_id;
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int cu__recode_dwarf_types_table(struct cu *cu,
Packit b92951
					struct ptr_table *pt,
Packit b92951
					uint32_t i)
Packit b92951
{
Packit b92951
	for (; i < pt->nr_entries; ++i) {
Packit b92951
		struct tag *tag = pt->entries[i];
Packit b92951
Packit b92951
		if (tag != NULL) /* void, see cu__new */
Packit b92951
			if (tag__recode_dwarf_type(tag, cu))
Packit b92951
				return -1;
Packit b92951
	}
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int cu__recode_dwarf_types(struct cu *cu)
Packit b92951
{
Packit b92951
	if (cu__recode_dwarf_types_table(cu, &cu->types_table, 1) ||
Packit b92951
	    cu__recode_dwarf_types_table(cu, &cu->tags_table, 0) ||
Packit b92951
	    cu__recode_dwarf_types_table(cu, &cu->functions_table, 0))
Packit b92951
		return -1;
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static const char *dwarf_tag__decl_file(const struct tag *tag,
Packit b92951
					const struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	return cu->extra_dbg_info ?
Packit b92951
			strings__ptr(strings, dtag->decl_file) : NULL;
Packit b92951
}
Packit b92951
Packit b92951
static uint32_t dwarf_tag__decl_line(const struct tag *tag,
Packit b92951
				     const struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	return cu->extra_dbg_info ? dtag->decl_line : 0;
Packit b92951
}
Packit b92951
Packit b92951
static unsigned long long dwarf_tag__orig_id(const struct tag *tag,
Packit b92951
					       const struct cu *cu)
Packit b92951
{
Packit b92951
	struct dwarf_tag *dtag = tag->priv;
Packit b92951
	return cu->extra_dbg_info ? dtag->id : 0;
Packit b92951
}
Packit b92951
Packit b92951
static const char *dwarf__strings_ptr(const struct cu *cu __unused,
Packit b92951
				      strings_t s)
Packit b92951
{
Packit b92951
	return strings__ptr(strings, s);
Packit b92951
}
Packit b92951
Packit b92951
struct debug_fmt_ops dwarf__ops;
Packit b92951
Packit b92951
static int die__process(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	Dwarf_Die child;
Packit b92951
	const uint16_t tag = dwarf_tag(die);
Packit b92951
Packit b92951
	if (tag != DW_TAG_compile_unit && tag != DW_TAG_type_unit && tag != DW_TAG_partial_unit) {
Packit b92951
		fprintf(stderr, "%s: DW_TAG_compile_unit, DW_TAG_type_unit or DW_TAG_partial_unit expected got %s!\n",
Packit b92951
			__FUNCTION__, dwarf_tag_name(tag));
Packit b92951
		return -EINVAL;
Packit b92951
	}
Packit b92951
Packit b92951
	cu->language = attr_numeric(die, DW_AT_language);
Packit b92951
Packit b92951
	if (dwarf_child(die, &child) == 0) {
Packit b92951
		int err = die__process_unit(&child, cu);
Packit b92951
		if (err)
Packit b92951
			return err;
Packit b92951
	}
Packit b92951
Packit b92951
	if (dwarf_siblingof(die, die) == 0)
Packit b92951
		fprintf(stderr, "%s: got %s unexpected tag after "
Packit b92951
				"DW_TAG_compile_unit!\n",
Packit b92951
			__FUNCTION__, dwarf_tag_name(tag));
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int die__process_and_recode(Dwarf_Die *die, struct cu *cu)
Packit b92951
{
Packit b92951
	int ret = die__process(die, cu);
Packit b92951
	if (ret != 0)
Packit b92951
		return ret;
Packit b92951
	return cu__recode_dwarf_types(cu);
Packit b92951
}
Packit b92951
Packit b92951
static int class_member__cache_byte_size(struct tag *tag, struct cu *cu,
Packit b92951
					 void *cookie)
Packit b92951
{
Packit b92951
	struct class_member *member = tag__class_member(tag);
Packit b92951
	struct conf_load *conf_load = cookie;
Packit b92951
Packit b92951
	if (tag__is_class_member(tag)) {
Packit b92951
		if (member->is_static)
Packit b92951
			return 0;
Packit b92951
	} else if (tag->tag != DW_TAG_inheritance) {
Packit b92951
		return 0;
Packit b92951
	}
Packit b92951
Packit b92951
	if (member->bitfield_size == 0) {
Packit b92951
		member->byte_size = tag__size(tag, cu);
Packit b92951
		member->bit_size = member->byte_size * 8;
Packit b92951
		return 0;
Packit b92951
	}
Packit b92951
Packit b92951
	/*
Packit b92951
	 * Try to figure out byte size, if it's not directly provided in DWARF
Packit b92951
	 */
Packit b92951
	if (member->byte_size == 0) {
Packit b92951
		struct tag *type = tag__strip_typedefs_and_modifiers(&member->tag, cu);
Packit b92951
		member->byte_size = tag__size(type, cu);
Packit b92951
		if (member->byte_size == 0) {
Packit b92951
			int bit_size;
Packit b92951
			if (tag__is_enumeration(type)) {
Packit b92951
				bit_size = tag__type(type)->size;
Packit b92951
			} else {
Packit b92951
				struct base_type *bt = tag__base_type(type);
Packit b92951
				bit_size = bt->bit_size ? bt->bit_size : base_type__name_to_size(bt, cu);
Packit b92951
			}
Packit b92951
			member->byte_size = (bit_size + 7) / 8 * 8;
Packit b92951
		}
Packit b92951
	}
Packit b92951
	member->bit_size = member->byte_size * 8;
Packit b92951
Packit b92951
	/*
Packit b92951
	 * XXX: after all the attemps to determine byte size, we might still
Packit b92951
	 * be unsuccessful, because base_type__name_to_size doesn't know about
Packit b92951
	 * the base_type name, so one has to add there when such base_type
Packit b92951
	 * isn't found. pahole will put zero on the struct output so it should
Packit b92951
	 * be easy to spot the name when such unlikely thing happens.
Packit b92951
	 */
Packit b92951
	if (member->byte_size == 0) {
Packit b92951
		member->bitfield_offset = 0;
Packit b92951
		return 0;
Packit b92951
	}
Packit b92951
Packit b92951
	/*
Packit b92951
	 * For little-endian architectures, DWARF data emitted by gcc/clang
Packit b92951
	 * specifies bitfield offset as an offset from the highest-order bit
Packit b92951
	 * of an underlying integral type (e.g., int) to a highest-order bit
Packit b92951
	 * of a bitfield. E.g., for bitfield taking first 5 bits of int-backed
Packit b92951
	 * bitfield, bit offset will be 27 (sizeof(int) - 0 offset - 5 bit
Packit b92951
	 * size), which is very counter-intuitive and isn't a natural
Packit b92951
	 * extension of byte offset, which on little-endian points to
Packit b92951
	 * lowest-order byte. So here we re-adjust bitfield offset to be an
Packit b92951
	 * offset from lowest-order bit of underlying integral type to
Packit b92951
	 * a lowest-order bit of a bitfield. This makes bitfield offset
Packit b92951
	 * a natural extension of byte offset for bitfields and is uniform
Packit b92951
	 * with how big-endian bit offsets work.
Packit b92951
	 */
Packit b92951
	if (cu->little_endian) {
Packit b92951
		member->bitfield_offset = member->bit_size - member->bitfield_offset - member->bitfield_size;
Packit b92951
	}
Packit b92951
	member->bit_offset = member->byte_offset * 8 + member->bitfield_offset;
Packit b92951
Packit b92951
	/* make sure bitfield offset is non-negative */
Packit b92951
	if (member->bitfield_offset < 0) {
Packit b92951
		member->bitfield_offset += member->bit_size;
Packit b92951
		member->byte_offset -= member->byte_size;
Packit b92951
		member->bit_offset = member->byte_offset * 8 + member->bitfield_offset;
Packit b92951
	}
Packit b92951
	/* align on underlying base type natural alignment boundary */
Packit b92951
	member->bitfield_offset += (member->byte_offset % member->byte_size) * 8;
Packit b92951
	member->byte_offset = member->bit_offset / member->bit_size * member->bit_size / 8;
Packit b92951
	if (member->bitfield_offset >= member->bit_size) {
Packit b92951
		member->bitfield_offset -= member->bit_size;
Packit b92951
		member->byte_offset += member->byte_size;
Packit b92951
	}
Packit b92951
Packit b92951
	if (conf_load && conf_load->fixup_silly_bitfields &&
Packit b92951
	    member->byte_size == 8 * member->bitfield_size) {
Packit b92951
		member->bitfield_size = 0;
Packit b92951
		member->bitfield_offset = 0;
Packit b92951
	}
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int finalize_cu(struct cus *cus, struct cu *cu, struct dwarf_cu *dcu,
Packit b92951
		       struct conf_load *conf)
Packit b92951
{
Packit b92951
	base_type_name_to_size_table__init(strings);
Packit b92951
	cu__for_all_tags(cu, class_member__cache_byte_size, conf);
Packit b92951
	if (conf && conf->steal) {
Packit b92951
		return conf->steal(cu, conf);
Packit b92951
	}
Packit b92951
	return LSK__KEEPIT;
Packit b92951
}
Packit b92951
Packit b92951
static int finalize_cu_immediately(struct cus *cus, struct cu *cu,
Packit b92951
				   struct dwarf_cu *dcu,
Packit b92951
				   struct conf_load *conf)
Packit b92951
{
Packit b92951
	int lsk = finalize_cu(cus, cu, dcu, conf);
Packit b92951
	switch (lsk) {
Packit b92951
	case LSK__DELETE:
Packit b92951
		cu__delete(cu);
Packit b92951
		break;
Packit b92951
	case LSK__STOP_LOADING:
Packit b92951
		break;
Packit b92951
	case LSK__KEEPIT:
Packit b92951
		if (!cu->extra_dbg_info)
Packit b92951
			obstack_free(&dcu->obstack, NULL);
Packit b92951
		cus__add(cus, cu);
Packit b92951
		break;
Packit b92951
	}
Packit b92951
	return lsk;
Packit b92951
}
Packit b92951
Packit b92951
static int cus__load_debug_types(struct cus *cus, struct conf_load *conf,
Packit b92951
				 Dwfl_Module *mod, Dwarf *dw, Elf *elf,
Packit b92951
				 const char *filename,
Packit b92951
				 const unsigned char *build_id,
Packit b92951
				 int build_id_len,
Packit b92951
				 struct cu **cup, struct dwarf_cu *dcup)
Packit b92951
{
Packit b92951
	Dwarf_Off off = 0, noff, type_off;
Packit b92951
	size_t cuhl;
Packit b92951
	uint8_t pointer_size, offset_size;
Packit b92951
	uint64_t signature;
Packit b92951
Packit b92951
	*cup = NULL;
Packit b92951
Packit b92951
	while (dwarf_next_unit(dw, off, &noff, &cuhl, NULL, NULL, &pointer_size,
Packit b92951
			       &offset_size, &signature, &type_off)
Packit b92951
		== 0) {
Packit b92951
Packit b92951
		if (*cup == NULL) {
Packit b92951
			struct cu *cu;
Packit b92951
Packit b92951
			cu = cu__new("", pointer_size, build_id,
Packit b92951
				     build_id_len, filename);
Packit b92951
			if (cu == NULL) {
Packit b92951
				return DWARF_CB_ABORT;
Packit b92951
			}
Packit b92951
Packit b92951
			cu->uses_global_strings = true;
Packit b92951
			cu->elf = elf;
Packit b92951
			cu->dwfl = mod;
Packit b92951
			cu->extra_dbg_info = conf ? conf->extra_dbg_info : 0;
Packit b92951
			cu->has_addr_info = conf ? conf->get_addr_info : 0;
Packit b92951
Packit b92951
			GElf_Ehdr ehdr;
Packit b92951
			if (gelf_getehdr(elf, &ehdr) == NULL) {
Packit b92951
				return DWARF_CB_ABORT;
Packit b92951
			}
Packit b92951
			cu->little_endian = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
Packit b92951
Packit b92951
			dwarf_cu__init(dcup);
Packit b92951
			dcup->cu = cu;
Packit b92951
			/* Funny hack.  */
Packit b92951
			dcup->type_unit = dcup;
Packit b92951
			cu->priv = dcup;
Packit b92951
			cu->dfops = &dwarf__ops;
Packit b92951
Packit b92951
			*cup = cu;
Packit b92951
		}
Packit b92951
Packit b92951
		Dwarf_Die die_mem;
Packit b92951
		Dwarf_Die *cu_die = dwarf_offdie_types(dw, off + cuhl,
Packit b92951
						       &die_mem);
Packit b92951
Packit b92951
		if (die__process(cu_die, *cup) != 0)
Packit b92951
			return DWARF_CB_ABORT;
Packit b92951
Packit b92951
		off = noff;
Packit b92951
	}
Packit b92951
Packit b92951
	if (*cup != NULL && cu__recode_dwarf_types(*cup) != 0)
Packit b92951
		return DWARF_CB_ABORT;
Packit b92951
Packit b92951
	return 0;
Packit b92951
}
Packit b92951
Packit b92951
static int cus__load_module(struct cus *cus, struct conf_load *conf,
Packit b92951
			    Dwfl_Module *mod, Dwarf *dw, Elf *elf,
Packit b92951
			    const char *filename)
Packit b92951
{
Packit b92951
	Dwarf_Off off = 0, noff;
Packit b92951
	size_t cuhl;
Packit b92951
	GElf_Addr vaddr;
Packit b92951
	const unsigned char *build_id = NULL;
Packit b92951
	uint8_t pointer_size, offset_size;
Packit b92951
Packit b92951
#ifdef HAVE_DWFL_MODULE_BUILD_ID
Packit b92951
	int build_id_len = dwfl_module_build_id(mod, &build_id, &vaddr);
Packit b92951
#else
Packit b92951
	int build_id_len = 0;
Packit b92951
#endif
Packit b92951
Packit b92951
	struct cu *type_cu;
Packit b92951
	struct dwarf_cu type_dcu;
Packit b92951
	int type_lsk = LSK__KEEPIT;
Packit b92951
Packit b92951
	int res = cus__load_debug_types(cus, conf, mod, dw, elf, filename,
Packit b92951
					build_id, build_id_len,
Packit b92951
					&type_cu, &type_dcu);
Packit b92951
	if (res != 0) {
Packit b92951
		return res;
Packit b92951
	}
Packit b92951
Packit b92951
	if (type_cu != NULL) {
Packit b92951
		type_lsk = finalize_cu(cus, type_cu, &type_dcu, conf);
Packit b92951
		if (type_lsk == LSK__KEEPIT) {
Packit b92951
			cus__add(cus, type_cu);
Packit b92951
		}
Packit b92951
	}
Packit b92951
Packit b92951
	while (dwarf_nextcu(dw, off, &noff, &cuhl, NULL, &pointer_size,
Packit b92951
			    &offset_size) == 0) {
Packit b92951
		Dwarf_Die die_mem;
Packit b92951
		Dwarf_Die *cu_die = dwarf_offdie(dw, off + cuhl, &die_mem);
Packit b92951
Packit b92951
		/*
Packit b92951
		 * DW_AT_name in DW_TAG_compile_unit can be NULL, first
Packit b92951
		 * seen in:
Packit b92951
		 * /usr/libexec/gcc/x86_64-redhat-linux/4.3.2/ecj1.debug
Packit b92951
		 */
Packit b92951
		const char *name = attr_string(cu_die, DW_AT_name);
Packit b92951
		struct cu *cu = cu__new(name ?: "", pointer_size,
Packit b92951
					build_id, build_id_len, filename);
Packit b92951
		if (cu == NULL)
Packit b92951
			return DWARF_CB_ABORT;
Packit b92951
		cu->uses_global_strings = true;
Packit b92951
		cu->elf = elf;
Packit b92951
		cu->dwfl = mod;
Packit b92951
		cu->extra_dbg_info = conf ? conf->extra_dbg_info : 0;
Packit b92951
		cu->has_addr_info = conf ? conf->get_addr_info : 0;
Packit b92951
Packit b92951
		GElf_Ehdr ehdr;
Packit b92951
		if (gelf_getehdr(elf, &ehdr) == NULL) {
Packit b92951
			return DWARF_CB_ABORT;
Packit b92951
		}
Packit b92951
		cu->little_endian = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
Packit b92951
Packit b92951
		struct dwarf_cu dcu;
Packit b92951
Packit b92951
		dwarf_cu__init(&dcu;;
Packit b92951
		dcu.cu = cu;
Packit b92951
		dcu.type_unit = type_cu ? &type_dcu : NULL;
Packit b92951
		cu->priv = &dcu;
Packit b92951
		cu->dfops = &dwarf__ops;
Packit b92951
Packit b92951
		if (die__process_and_recode(cu_die, cu) != 0)
Packit b92951
			return DWARF_CB_ABORT;
Packit b92951
Packit b92951
		if (finalize_cu_immediately(cus, cu, &dcu, conf)
Packit b92951
		    == LSK__STOP_LOADING)
Packit b92951
			return DWARF_CB_ABORT;
Packit b92951
Packit b92951
		off = noff;
Packit b92951
	}
Packit b92951
Packit b92951
	if (type_lsk == LSK__DELETE)
Packit b92951
		cu__delete(type_cu);
Packit b92951
Packit b92951
	return DWARF_CB_OK;
Packit b92951
}
Packit b92951
Packit b92951
struct process_dwflmod_parms {
Packit b92951
	struct cus	 *cus;
Packit b92951
	struct conf_load *conf;
Packit b92951
	const char	 *filename;
Packit b92951
	uint32_t	 nr_dwarf_sections_found;
Packit b92951
};
Packit b92951
Packit b92951
static int cus__process_dwflmod(Dwfl_Module *dwflmod,
Packit b92951
				void **userdata __unused,
Packit b92951
				const char *name __unused,
Packit b92951
				Dwarf_Addr base __unused,
Packit b92951
				void *arg)
Packit b92951
{
Packit b92951
	struct process_dwflmod_parms *parms = arg;
Packit b92951
	struct cus *cus = parms->cus;
Packit b92951
Packit b92951
	GElf_Addr dwflbias;
Packit b92951
	/*
Packit b92951
	 * Does the relocation and saves the elf for later processing
Packit b92951
	 * by the stealer, such as pahole_stealer, so that it don't
Packit b92951
	 * have to create another Elf instance just to do things like
Packit b92951
	 * reading this ELF file symtab to do CTF encoding of the
Packit b92951
	 * DW_TAG_suprogram tags (functions).
Packit b92951
	 */
Packit b92951
	Elf *elf = dwfl_module_getelf(dwflmod, &dwflbias);
Packit b92951
Packit b92951
	Dwarf_Addr dwbias;
Packit b92951
	Dwarf *dw = dwfl_module_getdwarf(dwflmod, &dwbias);
Packit b92951
Packit b92951
	int err = DWARF_CB_OK;
Packit b92951
	if (dw != NULL) {
Packit b92951
		++parms->nr_dwarf_sections_found;
Packit b92951
		err = cus__load_module(cus, parms->conf, dwflmod, dw, elf,
Packit b92951
				       parms->filename);
Packit b92951
	}
Packit b92951
	/*
Packit b92951
	 * XXX We will fall back to try finding other debugging
Packit b92951
	 * formats (CTF), so no point in telling this to the user
Packit b92951
	 * Use for debugging.
Packit b92951
	 * else
Packit b92951
	 *   fprintf(stderr,
Packit b92951
	 *         "%s: can't get debug context descriptor: %s\n",
Packit b92951
	 *	__func__, dwfl_errmsg(-1));
Packit b92951
	 */
Packit b92951
Packit b92951
	return err;
Packit b92951
}
Packit b92951
Packit b92951
static int cus__process_file(struct cus *cus, struct conf_load *conf, int fd,
Packit b92951
			     const char *filename)
Packit b92951
{
Packit b92951
	/* Duplicate an fd for dwfl_report_offline to swallow.  */
Packit b92951
	int dwfl_fd = dup(fd);
Packit b92951
Packit b92951
	if (dwfl_fd < 0)
Packit b92951
		return -1;
Packit b92951
Packit b92951
	/*
Packit b92951
	 * Use libdwfl in a trivial way to open the libdw handle for us.
Packit b92951
	 * This takes care of applying relocations to DWARF data in ET_REL
Packit b92951
	 * files.
Packit b92951
	 */
Packit b92951
Packit b92951
	static const Dwfl_Callbacks callbacks = {
Packit b92951
		.section_address = dwfl_offline_section_address,
Packit b92951
		.find_debuginfo	 = dwfl_standard_find_debuginfo,
Packit b92951
		/* We use this table for core files too.  */
Packit b92951
		.find_elf	 = dwfl_build_id_find_elf,
Packit b92951
	};
Packit b92951
Packit b92951
	Dwfl *dwfl = dwfl_begin(&callbacks);
Packit b92951
Packit b92951
	if (dwfl_report_offline(dwfl, filename, filename, dwfl_fd) == NULL)
Packit b92951
		return -1;
Packit b92951
Packit b92951
	dwfl_report_end(dwfl, NULL, NULL);
Packit b92951
Packit b92951
	struct process_dwflmod_parms parms = {
Packit b92951
		.cus  = cus,
Packit b92951
		.conf = conf,
Packit b92951
		.filename = filename,
Packit b92951
		.nr_dwarf_sections_found = 0,
Packit b92951
	};
Packit b92951
Packit b92951
	/* Process the one or more modules gleaned from this file. */
Packit b92951
	dwfl_getmodules(dwfl, cus__process_dwflmod, &parms, 0);
Packit b92951
	dwfl_end(dwfl);
Packit b92951
	return parms.nr_dwarf_sections_found ? 0 : -1;
Packit b92951
}
Packit b92951
Packit b92951
static int dwarf__load_file(struct cus *cus, struct conf_load *conf,
Packit b92951
			    const char *filename)
Packit b92951
{
Packit b92951
	int fd, err;
Packit b92951
Packit b92951
	elf_version(EV_CURRENT);
Packit b92951
Packit b92951
	fd = open(filename, O_RDONLY);
Packit b92951
Packit b92951
	if (fd == -1)
Packit b92951
		return -1;
Packit b92951
Packit b92951
	err = cus__process_file(cus, conf, fd, filename);
Packit b92951
	close(fd);
Packit b92951
Packit b92951
	return err;
Packit b92951
}
Packit b92951
Packit b92951
static int dwarf__init(void)
Packit b92951
{
Packit b92951
	strings = strings__new();
Packit b92951
	return strings != NULL ? 0 : -ENOMEM;
Packit b92951
}
Packit b92951
Packit b92951
static void dwarf__exit(void)
Packit b92951
{
Packit b92951
	strings__delete(strings);
Packit b92951
	strings = NULL;
Packit b92951
}
Packit b92951
Packit b92951
struct debug_fmt_ops dwarf__ops = {
Packit b92951
	.name		     = "dwarf",
Packit b92951
	.init		     = dwarf__init,
Packit b92951
	.exit		     = dwarf__exit,
Packit b92951
	.load_file	     = dwarf__load_file,
Packit b92951
	.strings__ptr	     = dwarf__strings_ptr,
Packit b92951
	.tag__decl_file	     = dwarf_tag__decl_file,
Packit b92951
	.tag__decl_line	     = dwarf_tag__decl_line,
Packit b92951
	.tag__orig_id	     = dwarf_tag__orig_id,
Packit b92951
	.has_alignment_info  = true,
Packit b92951
};