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
00029
00030 #define OP_SPU_MEMSIZE 0x3ffff
00031
00032 using namespace std;
00033
00034 extern verbose vbfd;
00035
00036
00037
00038
00039
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
00093
00094
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
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
00140
00141
00142
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
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
00172
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