Beispiel #1
0
string const find_image_path(string const & archive_path,
			     string const & image_name,
                             extra_images const & extra_images,
                             image_error & error)
{
	error = image_ok;

	string const image = op_realpath(archive_path + image_name);

	// simplest case
	if (op_file_readable(image)) {
		error = image_ok;
		return image_name;
	}

	if (errno == EACCES) {
		error = image_unreadable;
		return image_name;
	}

	string const base = op_basename(image);

	vector<string> result = extra_images.find(base);

	// not found, try a module search
	if (result.empty())
		result = extra_images.find(module_matcher(base + ".ko"));

	if (result.empty()) {
		error = image_not_found;
		return image_name;
	}

	if (result.size() > 1) {
		error = image_multiple_match;
		return image_name;
	}

	return result[0];
}
/*
 *  valid filename are variations on:
 *
 * {kern}/name/event_spec
 * {root}/path/to/bin/{dep}/{root}/path/to/bin/event_spec
 * {root}/path/to/bin/{dep}/{anon:anon}/pid.start.end/event_spec
 * {root}/path/to/bin/{dep}/{anon:[vdso]}/pid.start.end/event_spec
 * {root}/path/to/bin/{dep}/{kern}/name/event_spec
 * {root}/path/to/bin/{dep}/{root}/path/to/bin/{cg}/{root}/path/to/bin/event_spec

 *
 * where /name/ denote a unique path component
 */
parsed_filename parse_filename(string const & filename,
                               extra_images const & extra_found_images)
{
    struct stat st;

    string::size_type pos = filename.find_last_of('/');
    if (pos == string::npos) {
        throw invalid_argument("parse_filename() invalid filename: " +
                               filename);
    }
    string event_spec = filename.substr(pos + 1);
    string filename_spec = filename.substr(0, pos);

    parsed_filename result = parse_event_spec(event_spec);

    result.filename = filename;

    vector<string> path = separate_token(filename_spec, '/');

    remove_base_dir(path);

    // pp_interface PP:3.19 to PP:3.23 path must start either with {root}
    // or {kern} and we must found at least 2 component, remove_base_dir()
    // return an empty path if {root} or {kern} are not found
    if (path.size() < 2) {
        throw invalid_argument("parse_filename() invalid filename: " +
                               filename);
    }

    size_t i;
    for (i = 1 ; i < path.size() ; ++i) {
        if (path[i] == "{dep}")
            break;

        result.image += "/" + path[i];
    }

    if (i == path.size()) {
        throw invalid_argument("parse_filename() invalid filename: " +
                               filename);
    }

    // skip "{dep}"
    ++i;

    // PP:3.19 {dep}/ must be followed by {kern}/, {root}/ or {anon}/
    if (path[i] != "{kern}" && path[i] != "{root}" &&
            path[i].find("{anon", 0) != 0) {
        throw invalid_argument("parse_filename() invalid filename: " +
                               filename);
    }

    bool anon = path[i].find("{anon:", 0) == 0;

    // skip "{root}", "{kern}" or "{anon:.*}"
    ++i;

    for (; i < path.size(); ++i) {
        if (path[i] == "{cg}")
            break;

        if (anon) {
            pos = filename_spec.rfind('.');
            pos = filename_spec.rfind('.', pos-1);
            if (pos == string::npos) {
                throw invalid_argument("parse_filename() pid.addr.addr name expected: " +
                                       filename_spec);
            }
            string jitdump = filename_spec.substr(0, pos) + ".jo";
            // if a jitdump file exists, we point to this file
            if (!stat(jitdump.c_str(), &st)) {
                // later code assumes an optional prefix path
                // is stripped from the lib_image.
                result.lib_image =
                    extra_found_images.strip_path_prefix(jitdump);
                result.jit_dumpfile_exists = true;
            } else {
                result.lib_image =  parse_anon(path[i], path[i - 1]);
            }
            i++;
            break;
        } else {
            result.lib_image += "/" + path[i];
        }
    }

    if (i == path.size())
        return result;

    // skip "{cg}"
    ++i;
    if (i == path.size() ||
            (path[i] != "{kern}" && path[i] != "{root}" &&
             path[i].find("{anon", 0) != 0)) {
        throw invalid_argument("parse_filename() invalid filename: "
                               + filename);
    }

    // skip "{root}", "{kern}" or "{anon}"
    anon = (path[i].find("{anon", 0) == 0);
    ++i;

    if (anon) {
        result.cg_image = parse_anon(path[i], path[i - 1]);
        i++;
    } else {
        for (; i < path.size(); ++i)
            result.cg_image += "/" + path[i];
    }

    return result;
}
Beispiel #3
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 #4
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;
}