Exemple #1
0
static string typename_for_vaddr_interval(iterator_df<subprogram_die> i_subp, 
	const boost::icl::discrete_interval<Dwarf_Off> interval)
{
	std::ostringstream s_typename;
	if (i_subp.name_here()) s_typename << *i_subp.name_here();
	else s_typename << "0x" << std::hex << i_subp.offset_here() << std::dec;
	s_typename << "_vaddrs_0x" << std::hex << interval.lower() << "_0x" 
		<< interval.upper() << std::dec;

	return s_typename.str();
}
Exemple #2
0
void add_alias_if_absent(const string& s, iterator_df<type_die> concrete_t, master_relation_t& r)
{
	// HACK: don't alias void (we can't use iterators-to-void-type as indexes)
	if (!concrete_t) return;
	
	/* HACK: since in C, "struct X" and "X" are distinct, but we don't distinguish them, 
	 * we also need to ignore this kind of alias here. Be careful about base types though: 
	 * we *do* need their actual-name aliases. */
	if (!concrete_t.is_a<base_type_die>() 
		&& concrete_t.name_here() && s == *name_for_type_die(concrete_t)) return;
	
	r.aliases[concrete_t].insert(s);
}
Exemple #3
0
pair<bool, uniqued_name> add_type_if_absent(iterator_df<type_die> t, master_relation_t& r)
{
	if (t && t != t->get_concrete_type())
	{
		// add the concrete
		auto concrete_t = t->get_concrete_type();
		auto ret = add_concrete_type_if_absent(concrete_t, r);
		// add the alias, if we have a name
		if (t.name_here())
		{
			add_alias_if_absent(*name_for_type_die(t), concrete_t, r);
		}
		return ret;
	}
	else if (t.is_a<base_type_die>())
	{
		/* Base types are a bit like non-concretes. */
		// add the concrete
		auto concrete_t = t->get_concrete_type();
		auto ret = add_concrete_type_if_absent(concrete_t, r);
		// add the alias, if we have a name
		if (t.name_here())
		{
			add_alias_if_absent(*name_for_type_die(t), concrete_t, r);
			/* HACK: for good measure, also ensure that we add the 
			 * canonical C name, if the name we have is in some equivalence class. */
			const char **c_equiv_class = abstract_c_compiler::get_equivalence_class_ptr(
				name_for_type_die(t)->c_str());
			if (c_equiv_class)
			{
				add_alias_if_absent(c_equiv_class[0], concrete_t, r);
			}
		}
		return ret;
	}
	else return add_concrete_type_if_absent(t, r);
}
Exemple #4
0
static inline void _debug_print_dedup(iterator_df<dwarf::core::type_die> type_die, iterator_df<dwarf::core::type_die> dedup_type_iter) {
	 cerr << "Searching type set for";
	 if (type_die.name_here()) {
		  cerr << " '" << *type_die.name_here() << "'";
	 }
	 if (type_die.offset_here()) {
		  cerr << " @" << to_hex(type_die.offset_here());
	 }
	 if (!type_die.name_here() && !type_die.offset_here()) {
		  cerr << " <some anonymous DIE>";
	 }
	 cerr << ", got";
	 if (dedup_type_iter.name_here()) {
		  cerr << " '" << *dedup_type_iter.name_here() << "'";
	 }
	 if (dedup_type_iter.offset_here()) {
		  cerr << " @" << to_hex(dedup_type_iter.offset_here());
	 }
	 if (!dedup_type_iter.name_here() && !dedup_type_iter.offset_here()) {
		  cerr << " <some anonymous DIE>";
	 }
	 cerr << "." << endl;
}
Exemple #5
0
void print_type_die(std::ostream &_s, iterator_df<dwarf::core::basic_die> die_iter, optional<type_set&> types) {
	if (!die_iter) return;
	
	// Special case root early: just print all children
	if (die_iter.tag_here() == 0) {
		auto children = die_iter.children_here();
		for (auto iter = children.first; iter != children.second; iter++) {
			 print_type_die(_s, iter.base(), types);
			_s << endl;
		}
		return;
	}
	
	srk31::indenting_newline_ostream s(_s);
	//	auto &die = *die_iter;
	auto name_ptr = die_iter.name_here();
	auto tag = string(DEFAULT_DWARF_SPEC.tag_lookup(die_iter.tag_here())); 
	if (tag.compare("(unknown tag)") == 0) {
		// Leave unknown tags as hex
		tag = to_hex(die_iter.tag_here());
	} else {
		tag = tag.substr(7, string::npos); // remove DW_TAG_
	}
	auto offset = die_iter.offset_here();

	/* Offset, tag, name, type */

	bool offset_printed = false;
	bool name_printed = false;
	bool type_printed = false;
	
	if (offset) {
		s << "@0x" << std::hex << offset << std::dec << " ";
		offset_printed = true;
	}
	
	s << tag;

	if (name_ptr) {
		s << " " << *name_ptr;
		name_printed = true;
	}
	
	auto attrs = die_iter.copy_attrs(die_iter.get_root());
	auto &root = die_iter.get_root();

	/* Convert the type offset into a name if possible. */
	/* Two types (ha) of die with type information:
	   with_type_describing_layout_die => variables, members, etc, things *with* a type
	   type_describing_subprogram_die => subprograms (functions etc) *returning* a thing with a type
	   type_chain_die => things which are types with a type, e.g. typedefs, pointers, arrays
	   (yes, you're right, I can't count)
	*/
	dwarf::core::iterator_df<dwarf::core::type_die> type_die;
	auto with_type_iter = die_iter.as_a<with_type_describing_layout_die>();
	auto returning_type_iter = die_iter.as_a<type_describing_subprogram_die>();
	auto type_chain_iter = die_iter.as_a<type_chain_die>();
	if (with_type_iter) type_die = with_type_iter->get_type();
	else if (returning_type_iter) type_die = returning_type_iter->get_type();
	else if (type_chain_iter) type_die = type_chain_iter->get_type();
	
	if (type_die) {
		 // Dedup
		 if (types) {
			  auto dedup_type_iter = types->find(type_die);
			  //assert(dedup_type_iter != types->end());
			  if (dedup_type_iter != types->end()) {
				   _debug_print_dedup(type_die, *dedup_type_iter);
				   type_die = *dedup_type_iter;
			  }
		 }
		 auto abstract_name = type_die.name_here();
		 // Concretify (traverse typedefs etc)
		 auto concrete_die = type_die->get_concrete_type(root);
		 // Also dedup that. Just in case.
		 if (concrete_die && types) {
			  auto concrete_die_iter = types->find(concrete_die);
			  //assert(concrete_die_iter != types->end());
			  if (concrete_die_iter != types->end()) {
				   _debug_print_dedup(concrete_die, *concrete_die_iter);
				   concrete_die = *concrete_die_iter;
			  }
		 }
		 auto concrete_name = concrete_die.name_here();
		 auto type_name = (concrete_name ? concrete_name : abstract_name);
		 if (type_name) {
			  _debug_print_print(name_ptr, offset, type_die, concrete_die);
			  s << " : " << *type_name;
		 } else {
			  auto type_offset = (concrete_die ? concrete_die.offset_here() : type_die.offset_here());
			  s << " : @" << to_hex(type_offset);
			  
			  if (types->find(type_die) == types->end() && types->find(concrete_die) == types->end()) {
				   cerr << endl << "WARNING: a type was called for that wasn't in types!" << endl << "abstract: ";
				   type_die.print_with_attrs(cerr, 0);
				   cerr << endl << "concrete: ";
				   concrete_die.print_with_attrs(cerr, 0);
				   cerr << endl << "context: ";
				   die_iter.print_with_attrs(cerr, 0);
				   cerr << endl << endl;
			  }
			  type_printed = true;
		 }
		 
	} else {
		 try {
			  auto &v = attrs.at(DW_AT_type);
			  auto ref = v.get_ref();
			  s << " : " << (ref.abs ? "@" : "+") << to_hex(ref.off);
			  type_printed = true;
		 } catch (std::out_of_range) {}
	}
	
	/* Attribute list */

	if (name_printed) attrs.erase(DW_AT_name);
	if (type_printed) attrs.erase(DW_AT_type);
	if (attrs.size() > 0) {
		s << " [";
		s.inc_level();
		unsigned int attrs_printed = 0;
		for (auto iter = attrs.begin(); iter != attrs.end(); iter++) {
			auto pair = *iter;
			auto k = string(DEFAULT_DWARF_SPEC.attr_lookup(pair.first));
			if (k.compare("(unknown attribute)") == 0) {
				// FIXME FIXME FIXME
				continue;
				/* Leave unknown attributes as hex */
				k = to_hex(pair.first);
			} else {
				k = k.substr(6, string::npos); // remove DW_AT_
			}

			const char *drop_attrs[] = {
				 "decl_file",
				 "decl_line",
				 "prototyped",
				 "external",
				 "sibling",
				 nullptr
			};

			for (unsigned int i = 0; drop_attrs[i] != nullptr; i++) {
				 if (k.compare(drop_attrs[i]) == 0) {
					  continue;
				 }
			}
			
			auto v = pair.second;
			if (attrs_printed++ != 0) {
				s << "," << endl;
			}
			s << k << " = ";

			switch (v.get_form()) {
			case attribute_value::STRING: {
				string content = v.get_string();
				replace_all(content, "\\", "\\\\");
				replace_all(content, "\n", "\\n");
				replace_all(content, "\"", "\\\"");
				s << "\"" << content << "\"";
			}
				break;
			case attribute_value::FLAG: {
				if (v.get_flag()) {
					s << "true";
				} else {
					s << "false";
				}
			}
				break;
			case attribute_value::UNSIGNED:
				s << to_dec(v.get_unsigned()) << "u";
				break;
			case attribute_value::SIGNED:
				s << to_dec(v.get_signed());
				break;
			case attribute_value::ADDR:
				s << to_hex(v.get_address());
				break;
			case attribute_value::REF: {
				auto ref = v.get_ref();
				if (ref.abs) {
					s << "@";
				} else {
					s << "+";
				}
				s << to_hex(ref.off);
			}
				break;
			case attribute_value::LOCLIST: {
				auto loclist = v.get_loclist();
				if (loclist.size() == 1 && loclist[0].lopc == 0 && (loclist[0].hipc == 0 || loclist[0].hipc == std::numeric_limits<Dwarf_Addr>::max())) {
					s << "{";
					s.inc_level();
					auto locexpr = loclist[0];
					for (auto iter = locexpr.begin(); iter != locexpr.end(); iter++) {
						if (iter != locexpr.begin()) {
							s << endl;
						}
						s << opcode_to_string(*iter) << ";";
					}
					s.dec_level();
					s << "}";
					
				} else {
					s << "/* FIXME dummy location for multiple vaddr loclist */ { addr(0); }";
				}
			}
				break;
			default:
				s << "/* FIXME */ \"" << v << "\"";
				break;
			}
		}
		s.dec_level();
		s << "]";
	}

	/* Children list (recursively) */

	// auto lambda = [] (iterator_base &iter) {
	// 	return (iter.is_a<compile_unit_die>() || iter.is_a<member_die>() || iter.is_a<formal_parameter_die>() || iter.is_a<subprogram_die>() || iter.is_a<root_die>());
	// };
	auto children = die_iter.children_here(); //.subseq_with<decltype(lambda)>(lambda);
	
	if (children.first != children.second) {
		s << " {";
		s.inc_level();
		for (auto iter = children.first; iter != children.second; iter++) {
			 // user tags
			 if (iter.tag_here() > 0x4000) continue;
			 
			switch (iter.tag_here()) {
				// Only print these tags
			case DW_TAG_compile_unit:
			case DW_TAG_member:
			case DW_TAG_formal_parameter:
			case DW_TAG_subprogram:
			case 0: // root
				 print_type_die(s, iter.base(), types);
				s << endl;
				break;
			case DW_TAG_inlined_subroutine:
			case DW_TAG_lexical_block:
			case DW_TAG_variable:
				 // Specifically skip some.
				 continue; // definitely
				 break; // not confusing
			default:
				 print_type_die(s, iter.base(), types);
				 s << endl;
				 break;
			}
		}
		s.dec_level();
		s << "}";
	}
	
	s << ";";
}