oprofile 0.9.6

Copy in the rest of the oprofile 0.9.6 tree so we have a source
copy to match the prebuilt binaries that are checked into
external/.

Change-Id: Iaac327571d5d583594a4194973bf256569061048
diff --git a/libutil++/bfd_spu_support.cpp b/libutil++/bfd_spu_support.cpp
new file mode 100644
index 0000000..2dd497d
--- /dev/null
+++ b/libutil++/bfd_spu_support.cpp
@@ -0,0 +1,116 @@
+/**
+ * @file libutil++/bfd_spu_support.cpp
+ * Special BFD functions for processing a Cell BE SPU profile
+ *
+ * @remark Copyright 2007 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author Maynard Johnson
+ * (C) Copyright IBM Corporation 2007
+ */
+
+#include "bfd_support.h"
+#include "op_bfd.h"
+#include "config.h"
+#include "cverb.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <cstring>
+#include <sys/types.h>
+
+struct spu_elf {
+	FILE * stream;
+	off_t spu_offset;
+};
+
+using namespace std;
+
+extern verbose vbfd;
+
+#ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS
+
+namespace {
+
+static void *
+spu_bfd_iovec_open(bfd * nbfd, void * open_closure)
+{
+	/* Checking nbfd isn't really necessary, except to silence
+	 * compile warning.  In fact, nbfd will always be non-NULL.
+	 */
+	if (nbfd)
+		return open_closure;
+	else
+		return NULL;
+}
+
+static int
+spu_bfd_iovec_close(bfd * nbfd, void * stream)
+{
+	spu_elf * my_stream = (spu_elf *) stream;
+
+	fclose(my_stream->stream);
+	free(my_stream);
+	/* Checking nbfd isn't really necessary, except to silence
+	 * compile warning.  In fact, nbfd will always be non-NULL.
+	 */
+	if (nbfd)
+		return 1;
+	else
+		return 0;
+}
+
+static file_ptr
+spu_bfd_iovec_pread(bfd * abfd, void * stream, void * buf,
+		    file_ptr nbytes, file_ptr offset)
+{
+	spu_elf * my_stream = (spu_elf *) stream;
+	fseek(my_stream->stream, my_stream->spu_offset + offset,
+	      SEEK_SET);
+	nbytes = fread(buf, sizeof(char), nbytes, my_stream->stream);
+	/* Checking abfd isn't really necessary, except to silence
+	 * compile warning.  In fact, abfd will always be non-NULL.
+	 */
+	if (abfd)
+		return nbytes;
+	else
+		return 0;
+}
+} // namespace anon
+#endif
+
+bfd *
+spu_open_bfd(string const name, int fd, uint64_t offset_to_spu_elf)
+{
+
+	bfd * nbfd = NULL;
+	spu_elf * spu_elf_stream = (spu_elf *)malloc(sizeof(spu_elf));
+
+	FILE * fp = fdopen(fd, "r");
+	spu_elf_stream->stream = fp;
+	spu_elf_stream->spu_offset = offset_to_spu_elf;
+#ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS
+	nbfd = bfd_openr_iovec(strdup(name.c_str()), "elf32-spu",
+			       spu_bfd_iovec_open, spu_elf_stream,
+			       spu_bfd_iovec_pread, spu_bfd_iovec_close, NULL);
+#else
+	ostringstream os;
+	os << "Attempt to process a Cell Broadband Engine SPU profile without"
+	   << "proper BFD support.\n"
+	   << "Rebuild the opreport utility with the correct BFD library.\n"
+	   << "See the OProfile user manual for more information.\n";
+	throw op_runtime_error(os.str());
+#endif
+	if (!nbfd) {
+		cverb << vbfd << "spu_open_bfd failed for " << name << endl;
+		return NULL;
+	}
+
+	bfd_check_format(nbfd, bfd_object);
+
+	return nbfd;
+}