Beispiel #1
0
/*
 * This overload of the op_bfd constructor is patterned after the
 * constructor in libutil++/op_bfd.cpp, with the additional processing
 * needed to handle an embedded spu offset.
 */
op_bfd::op_bfd(uint64_t spu_offset, string const & fname,
	       string_filter const & symbol_filter, 
	       extra_images const & extra_images, bool & ok)
	:
	archive_path(extra_images.get_archive_path()),
	extra_found_images(extra_images),
	file_size(-1),
	embedding_filename(fname)
{
	int fd;
	struct stat st;
	int notes_remaining;
	bool spu_note_found = false;
	size_t sec_size = 0;
	unsigned int oct_per_byte;
	asection * note = NULL;

	symbols_found_t symbols;
	asection const * sect;

	image_error image_ok;
	string const image_path =
		extra_images.find_image_path(fname, image_ok, true);

	cverb << vbfd << "op_bfd ctor for " << image_path << endl;
	if (!ok)
		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 = spu_open_bfd(image_path, fd, spu_offset);

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

	/* For embedded SPU ELF, a note section named '.note.spu_name'
	 * contains the name of the SPU binary image in the description
	 * field.
	 */
	note = bfd_get_section_by_name(ibfd.abfd, ".note.spu_name");
	if (!note) {
		cverb << vbfd << "No .note.spu-name section found" << endl;
		goto find_sec_code;
	}
	cverb << vbfd << "found .note.spu_name section" << endl;

	bfd_byte * sec_contents;
	oct_per_byte = bfd_octets_per_byte(ibfd.abfd);
	sec_size = bfd_section_size(ibfd.abfd, note)/oct_per_byte;

	sec_contents = (bfd_byte *) xmalloc(sec_size);
	if (!bfd_get_section_contents(ibfd.abfd, note, sec_contents,
				      0, sec_size)) {
		cverb << vbfd << "bfd_get_section_contents with size "
		      << sec_size << " returned an error" << endl;
		ok = false;
		goto out_fail;
	}
	notes_remaining = sec_size;
	while (notes_remaining && !spu_note_found) {
		unsigned int  nsize, dsize, type;
		nsize = *((unsigned int *) sec_contents);
		dsize = *((unsigned int *) sec_contents +1);
		type = *((unsigned int *) sec_contents +2);
		int remainder, desc_start, name_pad_length, desc_pad_length;
		name_pad_length = desc_pad_length = 0;
		/* Calculate padding for 4-byte alignment */
		remainder = nsize % 4;
		if (remainder != 0)
			name_pad_length = 4 - remainder;
		desc_start = 12 + nsize + name_pad_length;
		if (type != 1) {
			int note_record_length;
			if ((remainder = (dsize % 4)) != 0)
				desc_pad_length = 4 - remainder;
			note_record_length = 12 + nsize +
				name_pad_length + dsize + desc_pad_length;
			notes_remaining -= note_record_length;
			sec_contents += note_record_length;
			continue;
		} else {
			spu_note_found = true;
			/* Must memcpy the data from sec_contents to a
			 * 'char *' first, then stringify it, since
			 * the type of sec_contents (bfd_byte *) cannot be
			 * used as input for creating a string.
			 */
			char * description = (char *) xmalloc(dsize);
			memcpy(description, sec_contents + desc_start, dsize);
			filename = description;
			free(description);
		}
	}
	free(sec_contents);
	/* Default to app name for the image name */
	if (spu_note_found == false)
		filename = fname;

find_sec_code:
	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;
		}
	}

	get_symbols(symbols);

	/* In some cases the SPU library code generates code stubs on the stack. */
	/* The kernel module remaps those addresses so add an entry to catch/report them. */
	symbols.push_back(op_bfd_symbol(OP_SPU_DYN_FLAG, OP_SPU_MEMSIZE,
			  "__send_to_ppe(stack)"));

out:
	add_symbols(symbols, symbol_filter);
	return;
out_fail:
	ibfd.close();
	dbfd.close();
	file_size = -1;
	goto out;
}
Beispiel #2
0
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)
{
	int fd;
	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;
}