op_spu_bfd.cpp

Go to the documentation of this file.
00001 
00013 #include <fcntl.h>
00014 #include <sys/stat.h>
00015 #include <cstdlib>
00016 #include <cstring>
00017 
00018 #include <iostream>
00019 #include <cstring>
00020 #include <cstdlib>
00021 
00022 #include "op_bfd.h"
00023 #include "locate_images.h"
00024 #include "op_libiberty.h"
00025 #include "string_filter.h"
00026 #include "cverb.h"
00027 
00028 #define OP_SPU_DYN_FLAG     0x10000000  /* kernel module adds this offset */
00029                         /* to SPU code it can't find in the map */
00030 #define OP_SPU_MEMSIZE      0x3ffff     /* Physical memory size on an SPU */
00031 
00032 using namespace std;
00033 
00034 extern verbose vbfd;
00035 
00036 /*
00037  * This overload of the op_bfd constructor is patterned after the
00038  * constructor in libutil++/op_bfd.cpp, with the additional processing
00039  * needed to handle an embedded spu offset.
00040  */
00041 op_bfd::op_bfd(uint64_t spu_offset, string const & fname,
00042            string_filter const & symbol_filter, 
00043            extra_images const & extra_images, bool & ok)
00044     :
00045     archive_path(extra_images.get_archive_path()),
00046     extra_found_images(extra_images),
00047     file_size(-1),
00048     embedding_filename(fname),
00049     anon_obj(false)
00050 {
00051     int fd;
00052     struct stat st;
00053     int notes_remaining;
00054     bool spu_note_found = false;
00055     size_t sec_size = 0;
00056     unsigned int oct_per_byte;
00057     asection * note = NULL;
00058 
00059     symbols_found_t symbols;
00060     asection const * sect;
00061 
00062     image_error image_ok;
00063     string const image_path =
00064         extra_images.find_image_path(fname, image_ok, true);
00065 
00066     cverb << vbfd << "op_bfd ctor for " << image_path << endl;
00067     if (!ok)
00068         goto out_fail;
00069 
00070     fd = open(image_path.c_str(), O_RDONLY);
00071     if (fd == -1) {
00072         cverb << vbfd << "open failed for " << image_path << endl;
00073         ok = false;
00074         goto out_fail;
00075     }
00076 
00077     if (fstat(fd, &st)) {
00078         cverb << vbfd << "stat failed for " << image_path << endl;
00079         ok = false;
00080         goto out_fail;
00081     }
00082 
00083     file_size = st.st_size;
00084     ibfd.abfd = spu_open_bfd(image_path, fd, spu_offset);
00085 
00086     if (!ibfd.valid()) {
00087         cverb << vbfd << "fdopen_bfd failed for " << image_path << endl;
00088         ok = false;
00089         goto out_fail;
00090     }
00091 
00092     /* For embedded SPU ELF, a note section named '.note.spu_name'
00093      * contains the name of the SPU binary image in the description
00094      * field.
00095      */
00096     note = bfd_get_section_by_name(ibfd.abfd, ".note.spu_name");
00097     if (!note) {
00098         cverb << vbfd << "No .note.spu-name section found" << endl;
00099         goto find_sec_code;
00100     }
00101     cverb << vbfd << "found .note.spu_name section" << endl;
00102 
00103     bfd_byte * sec_contents;
00104     oct_per_byte = bfd_octets_per_byte(ibfd.abfd);
00105     sec_size = bfd_section_size(ibfd.abfd, note)/oct_per_byte;
00106 
00107     sec_contents = (bfd_byte *) xmalloc(sec_size);
00108     if (!bfd_get_section_contents(ibfd.abfd, note, sec_contents,
00109                       0, sec_size)) {
00110         cverb << vbfd << "bfd_get_section_contents with size "
00111               << sec_size << " returned an error" << endl;
00112         ok = false;
00113         goto out_fail;
00114     }
00115     notes_remaining = sec_size;
00116     while (notes_remaining && !spu_note_found) {
00117         unsigned int  nsize, dsize, type;
00118         nsize = *((unsigned int *) sec_contents);
00119         dsize = *((unsigned int *) sec_contents +1);
00120         type = *((unsigned int *) sec_contents +2);
00121         int remainder, desc_start, name_pad_length, desc_pad_length;
00122         name_pad_length = desc_pad_length = 0;
00123         /* Calculate padding for 4-byte alignment */
00124         remainder = nsize % 4;
00125         if (remainder != 0)
00126             name_pad_length = 4 - remainder;
00127         desc_start = 12 + nsize + name_pad_length;
00128         if (type != 1) {
00129             int note_record_length;
00130             if ((remainder = (dsize % 4)) != 0)
00131                 desc_pad_length = 4 - remainder;
00132             note_record_length = 12 + nsize +
00133                 name_pad_length + dsize + desc_pad_length;
00134             notes_remaining -= note_record_length;
00135             sec_contents += note_record_length;
00136             continue;
00137         } else {
00138             spu_note_found = true;
00139             /* Must memcpy the data from sec_contents to a
00140              * 'char *' first, then stringify it, since
00141              * the type of sec_contents (bfd_byte *) cannot be
00142              * used as input for creating a string.
00143              */
00144             char * description = (char *) xmalloc(dsize);
00145             memcpy(description, sec_contents + desc_start, dsize);
00146             filename = description;
00147             free(description);
00148         }
00149     }
00150     free(sec_contents);
00151     /* Default to app name for the image name */
00152     if (spu_note_found == false)
00153         filename = fname;
00154 
00155 find_sec_code:
00156     for (sect = ibfd.abfd->sections; sect; sect = sect->next) {
00157         if (sect->flags & SEC_CODE) {
00158             if (filepos_map[sect->name] != 0) {
00159                 cerr << "Found section \"" << sect->name
00160                      << "\" twice for " << get_filename()
00161                      << endl;
00162                 abort();
00163             }
00164 
00165             filepos_map[sect->name] = sect->filepos;
00166         }
00167     }
00168 
00169     get_symbols(symbols);
00170 
00171     /* In some cases the SPU library code generates code stubs on the stack. */
00172     /* The kernel module remaps those addresses so add an entry to catch/report them. */
00173     symbols.push_back(op_bfd_symbol(OP_SPU_DYN_FLAG, OP_SPU_MEMSIZE,
00174               "__send_to_ppe(stack)"));
00175 
00176 out:
00177     add_symbols(symbols, symbol_filter);
00178     return;
00179 out_fail:
00180     ibfd.close();
00181     dbfd.close();
00182     file_size = -1;
00183     goto out;
00184 }
00185 

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1