/**
 * @file op_bfd.cpp
 * Encapsulation of bfd objects
 *
 * @remark Copyright 2002 OProfile authors
 * @remark Read the file COPYING
 *
 * @author Philippe Elie
 * @author John Levon
 */

#include "op_file.h"
#include "op_config.h"
#include "config.h"

#include <fcntl.h>
#include <cstring>

#include <sys/stat.h>
#include <unistd.h>

#include <cstdlib>

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <sstream>

#include "op_bfd.h"
#include "locate_images.h"
#include "string_filter.h"
#include "stream_util.h"
#include "cverb.h"

using namespace std;


verbose vbfd("bfd");


namespace {

/// function object for filtering symbols to remove
struct remove_filter {
	remove_filter(string_filter const & filter)
		: filter_(filter) {}

	bool operator()(op_bfd_symbol const & symbol) {
		return !filter_.match(symbol.name());
	}

	string_filter filter_;
};


} // namespace anon


op_bfd_symbol::op_bfd_symbol(asymbol const * a)
	: bfd_symbol(a), symb_value(a->value),
	  section_filepos(a->section->filepos),
	  section_vma(a->section->vma),
	  symb_size(0), symb_hidden(false), symb_weak(false),
	  symb_artificial(false)
{
	// Some sections have unnamed symbols in them. If
	// we just ignore them then we end up sticking
	// things like .plt hits inside of _init. So instead
	// we name the symbol after the section.
	if (a->name && a->name[0] != '\0') {
		symb_name = a->name;
		symb_weak = a->flags & BSF_WEAK;
		symb_hidden = (a->flags & BSF_LOCAL)
 			&& !(a->flags & BSF_GLOBAL);
	} else {
		symb_name = string("??") + a->section->name;
	}
}


op_bfd_symbol::op_bfd_symbol(bfd_vma vma, size_t size, string const & name)
	: bfd_symbol(0), symb_value(vma),
	  section_filepos(0), section_vma(0),
	  symb_size(size), symb_name(name),
	  symb_hidden(false), symb_weak(false), symb_artificial(true)
{
}


bool op_bfd_symbol::operator<(op_bfd_symbol const & rhs) const
{
	return filepos() < rhs.filepos();
}

unsigned long op_bfd_symbol::symbol_endpos(void) const
{
	return bfd_symbol->section->filepos + bfd_symbol->section->size;
}


op_bfd::op_bfd(string const & fname, string_filter const & symbol_filter,
	       extra_images const & extra_images, bool & ok)
	:
	filename(fname),
	archive_path(extra_images.get_archive_path()),
	extra_found_images(extra_images),
	file_size(-1),
	anon_obj(false),
	vma_adj(0)
{
	fd =  -1;
	struct stat st;
	// after creating all symbol it's convenient for user code to access
	// symbols through a vector. We use an intermediate list to avoid a
	// O(N�) behavior when we will filter vector element below
	symbols_found_t symbols;
	asection const * sect;
	string suf = ".jo";

	image_error img_ok;
	string const image_path =
		extra_images.find_image_path(filename, img_ok, true);

	cverb << vbfd << "op_bfd ctor for " << image_path << endl;

	// if there's a problem already, don't try to open it
	if (!ok || img_ok != image_ok) {
		cverb << vbfd << "can't locate " << image_path << endl;
		goto out_fail;
	}

	fd = open(image_path.c_str(), O_RDONLY);
	if (fd == -1) {
		cverb << vbfd << "open failed for " << image_path << endl;
		ok = false;
		goto out_fail;
	}

	if (fstat(fd, &st)) {
		cverb << vbfd << "stat failed for " << image_path << endl;
		ok = false;
		goto out_fail;
	}

	file_size = st.st_size;

	ibfd.abfd = fdopen_bfd(image_path, fd);
	if (!ibfd.valid()) {
		cverb << vbfd << "fdopen_bfd failed for " << image_path << endl;
		ok = false;
		goto out_fail;
	}

	string::size_type pos;
	pos = filename.rfind(suf);
	if (pos != string::npos && pos == filename.size() - suf.size())
		anon_obj = true;


	// find .text and use it
	for (sect = ibfd.abfd->sections; sect; sect = sect->next) {
		if (sect->flags & SEC_CODE) {
			if (filepos_map[sect->name] != 0) {
				cerr << "Found section \"" << sect->name
				     << "\" twice for " << get_filename()
				     << endl;
				abort();
			}

			filepos_map[sect->name] = sect->filepos;

			if (sect->vma == 0 && strcmp(sect->name, ".text"))
				filtered_section.push_back(sect);
		}
	}

	get_symbols(symbols);

out:
	add_symbols(symbols, symbol_filter);
	return;
out_fail:
	ibfd.close();
	dbfd.close();
	// make the fake symbol fit within the fake file
	file_size = -1;
	goto out;
}


op_bfd::~op_bfd()
{
	if (fd != -1)
		close(fd);
}


unsigned long op_bfd::get_start_offset(bfd_vma vma) const
{
	if (!vma || !ibfd.valid()) {
		filepos_map_t::const_iterator it = filepos_map.find(".text");
		if (it != filepos_map.end())
			return it->second;
		return 0;
	}

	return 0;
}


void op_bfd::get_symbols(op_bfd::symbols_found_t & symbols)
{
	ibfd.get_symbols();

	// On separate debug file systems, the main bfd has no symbols,
	// so even for non -g reports, we want to process the dbfd.
	// This hurts us pretty badly (the CRC), but we really don't
	// have much choice at the moment.
	has_debug_info();

	dbfd.set_image_bfd_info(&ibfd);
	dbfd.get_symbols();
	if (dbfd.valid() && !ibfd.nr_syms)
		vma_adj = ibfd.abfd->start_address - dbfd.abfd->start_address;
	else
		vma_adj= 0;

	size_t i;
	for (i = 0; i < ibfd.nr_syms; ++i) {
		if (!interesting_symbol(ibfd.syms[i]))
			continue;
		if (find(filtered_section.begin(), filtered_section.end(),
			 ibfd.syms[i]->section) != filtered_section.end())
			continue;
		symbols.push_back(op_bfd_symbol(ibfd.syms[i]));
	}

	for (i = 0; i < dbfd.nr_syms; ++i) {
		if (!interesting_symbol(dbfd.syms[i]))
			continue;

		// need to use filepos of original file's section for
		// debug file symbols. We probably need to be more
		// careful for special symbols which have ->section from
		// .rodata like *ABS*
		u32 filepos = filepos_map[dbfd.syms[i]->section->name];
		if (filepos != 0)
			dbfd.syms[i]->section->filepos = filepos;
		symbols.push_back(op_bfd_symbol(dbfd.syms[i]));
	}

	symbols.sort();

	symbols_found_t::iterator it = symbols.begin();

	// we need to ensure than for a given vma only one symbol exist else
	// we read more than one time some samples. Fix #526098
	while (it != symbols.end()) {
		symbols_found_t::iterator temp = it;
		++temp;
		if (temp != symbols.end() && (it->vma() == temp->vma()) &&
			(it->filepos() == temp->filepos())) {
			if (boring_symbol(*it, *temp)) {
				it = symbols.erase(it);
			} else {
				symbols.erase(temp);
			}
		} else {
			++it;
		}
	}

	// now we can calculate the symbol size, we can't first include/exclude
	// symbols because the size of symbol is calculated from the difference
	// between the vma of a symbol and the next one.
	for (it = symbols.begin() ; it != symbols.end(); ++it) {
		op_bfd_symbol const * next = 0;
		symbols_found_t::iterator temp = it;
		++temp;
		if (temp != symbols.end())
			next = &*temp;
		it->size(symbol_size(*it, next));
	}
}


void op_bfd::add_symbols(op_bfd::symbols_found_t & symbols,
                         string_filter const & symbol_filter)
{
	// images with no symbols debug info available get a placeholder symbol
	if (symbols.empty())
		symbols.push_back(create_artificial_symbol());

	cverb << vbfd << "number of symbols before filtering "
	      << dec << symbols.size() << hex << endl;

	symbols_found_t::iterator it;
	it = remove_if(symbols.begin(), symbols.end(),
	               remove_filter(symbol_filter));

	copy(symbols.begin(), it, back_inserter(syms));

	cverb << vbfd << "number of symbols now "
	      << dec << syms.size() << hex << endl;
}


bfd_vma op_bfd::offset_to_pc(bfd_vma offset) const
{
	asection const * sect = ibfd.abfd->sections;

	for (; sect; sect = sect->next) {
		if (offset >= bfd_vma(sect->filepos) &&
		    (!sect->next || offset < bfd_vma(sect->next->filepos))) {
			return sect->vma + (offset - sect->filepos);
		}
	}

	return 0;
}

bool op_bfd::
symbol_has_contents(symbol_index_t sym_idx)
{
	op_bfd_symbol const & bfd_sym = syms[sym_idx];
	string const name = bfd_sym.name();
	if (name.size() == 0 || bfd_sym.artificial() || !ibfd.valid())
		return false;
	else
		return true;
}

bool op_bfd::
get_symbol_contents(symbol_index_t sym_index, unsigned char * contents) const
{
	op_bfd_symbol const & bfd_sym = syms[sym_index];
	size_t size = bfd_sym.size();

	if (!bfd_get_section_contents(ibfd.abfd, bfd_sym.symbol()->section, 
				 contents, 
				 static_cast<file_ptr>(bfd_sym.value()), size)) {
		return false;
	}
	return true;
}

bool op_bfd::has_debug_info() const
{
	if (debug_info.cached())
		return debug_info.get();

	if (!ibfd.valid())
		return debug_info.reset(false);

	if (ibfd.has_debug_info())
		return debug_info.reset(true);

	// check to see if there is an .debug file

	if (find_separate_debug_file(ibfd.abfd, filename, debug_filename, extra_found_images)) {
		cverb << vbfd << "now loading: " << debug_filename << endl;
		dbfd.abfd = open_bfd(debug_filename);
		if (dbfd.has_debug_info())
			return debug_info.reset(true);
	}

	// .debug is optional, so will not fail if there's a problem
	cverb << vbfd << "failed to process separate debug file "
	      << debug_filename << endl;

	return debug_info.reset(false);
}


bool op_bfd::get_linenr(symbol_index_t sym_idx, bfd_vma offset,
			string & source_filename, unsigned int & linenr) const
{
	if (!has_debug_info())
		return false;

	bfd_info const & b = dbfd.valid() ? dbfd : ibfd;
	op_bfd_symbol const & sym = syms[sym_idx];

	linenr_info const info = find_nearest_line(b, sym, offset, anon_obj);

	if (!info.found)
		return false;

	source_filename = info.filename;
	linenr = info.line;
	return true;
}


size_t op_bfd::symbol_size(op_bfd_symbol const & sym,
			   op_bfd_symbol const * next) const
{
	unsigned long long start = sym.filepos();
	unsigned long long end;

	if (next && (sym.section() != next->section()))
		end = sym.symbol_endpos();
	else
		end = next ? next->filepos() : sym.section()->filepos + file_size;

	if (start > end)
		return 0;

	return end - start;
}


void op_bfd::get_symbol_range(symbol_index_t sym_idx,
			      unsigned long long & start, unsigned long long & end) const
{
	op_bfd_symbol const & sym = syms[sym_idx];

	bool const verbose = cverb << (vbfd & vlevel1);

	if (anon_obj)
		start = sym.vma();
	else
		start = sym.filepos();
	end = start + sym.size();

	if (!verbose)
		return;

	io_state state(cverb << (vbfd & vlevel1));

	cverb << (vbfd & vlevel1) << "symbol " << sym.name()
	      << ", value " << hex << sym.value() << endl;
	cverb << (vbfd & vlevel1)
	      << "start " << hex << start << ", end " << end << endl;

	if (sym.symbol()) {
		cverb << (vbfd & vlevel1) << "in section "
		      << sym.symbol()->section->name << ", filepos "
		      << hex << sym.symbol()->section->filepos << endl;
	}
}


void op_bfd::get_vma_range(bfd_vma & start, bfd_vma & end) const
{
	if (!syms.empty()) {
		// syms are sorted by vma so vma of the first symbol and vma +
		// size of the last symbol give the vma range for gprof output
		op_bfd_symbol const & last_symb = syms[syms.size() - 1];
		start = syms[0].vma();
		// end is excluded from range so + 1 *if* last_symb.size() != 0
		end = last_symb.vma() + last_symb.size() + (last_symb.size() != 0);
	} else {
		start = 0;
		end = file_size;
	}
}


op_bfd_symbol const op_bfd::create_artificial_symbol()
{

	bfd_vma start, end;
	get_vma_range(start, end);
	return op_bfd_symbol(start, end - start, get_filename());
}


string op_bfd::get_filename() const
{
	return filename;
}


size_t op_bfd::bfd_arch_bits_per_address() const
{
	if (ibfd.valid())
		return ::bfd_arch_bits_per_address(ibfd.abfd);
	// FIXME: this function should be called only if the underlined ibfd
	// is ok, must we throw ?
	return sizeof(bfd_vma);
}
