create_bfd.c

Go to the documentation of this file.
00001 
00017 #include "opjitconv.h"
00018 #include "opd_printf.h"
00019 #include "op_libiberty.h"
00020 
00021 #include <bfd.h>
00022 #include <stdint.h>
00023 #include <stdio.h>
00024 
00025 /* Create the symbols and fill the syms array for all functions
00026  * from start_idx to end_idx pointing into entries_address_ascending array */
00027 static int fill_symtab(void)
00028 {
00029     int rc = OP_JIT_CONV_OK;
00030     u32 i;
00031     int r;
00032     struct jitentry const * e;
00033     asymbol * s;
00034     asection * section = NULL;
00035 
00036     /* Check for valid value of entry_count to avoid integer overflow. */
00037     if (entry_count > UINT32_MAX - 1) {
00038         bfd_perror("invalid entry_count value");
00039         rc = OP_JIT_CONV_FAIL;
00040         goto out;
00041     }
00042     
00043     syms = xmalloc(sizeof(asymbol *) * (entry_count+1));
00044     syms[entry_count] = NULL;
00045     for (i = 0; i < entry_count; i++) {
00046         e = entries_address_ascending[i];
00047         if (e->section)
00048             section = e->section;
00049         s = bfd_make_empty_symbol(cur_bfd);
00050         if (!s) {
00051             bfd_perror("bfd_make_empty_symbol");
00052             rc = OP_JIT_CONV_FAIL;
00053             goto out;
00054         }
00055         s->name = e->symbol_name;
00056         s->section = section;
00057         s->flags = BSF_GLOBAL | BSF_FUNCTION;
00058         s->value = e->vma - section->vma;
00059         verbprintf(debug,"add sym: name=%s, value=%llx\n", s->name,
00060                (unsigned long long)s->value);
00061         syms[i] = s;
00062     }
00063     r = bfd_set_symtab(cur_bfd, syms, entry_count);
00064     if (r == FALSE) {
00065         bfd_perror("bfd_set_symtab");
00066         rc = OP_JIT_CONV_FAIL;
00067     }
00068 out:
00069     return rc;
00070 }
00071 
00072 /*
00073  * create a new section.
00074  */
00075 asection * create_section(bfd * abfd, char const * section_name,
00076               size_t size, bfd_vma vma, flagword flags)
00077 {
00078     asection * section;
00079 
00080     verbprintf(debug, "create_section() %s\n", section_name);
00081     section = bfd_make_section(abfd, section_name);
00082     if (section == NULL)  {
00083         bfd_perror("bfd_make_section");
00084         goto error;
00085     }
00086     if (bfd_set_section_vma(abfd, section, vma) == FALSE) {
00087         bfd_perror("bfd_set_section_vma");
00088         goto error;
00089     }
00090     if (bfd_set_section_size(abfd, section, size) == FALSE) {
00091         bfd_perror("bfd_set_section_size");
00092         goto error;
00093     }
00094     if (bfd_set_section_flags(abfd, section, flags) == FALSE) {
00095         bfd_perror("bfd_set_section_flags");
00096         goto error;
00097     }
00098     return section;
00099 error:
00100     return NULL;
00101 }
00102 
00103 
00104 /* create a .text section. end_idx: index last jitentry (inclusive!)  */
00105 static int create_text_section(int start_idx, int end_idx)
00106 {
00107     int rc = OP_JIT_CONV_OK;
00108 
00109     asection * section;
00110     char const * section_name;
00111     int idx = start_idx;
00112     unsigned long long vma_start =
00113         entries_address_ascending[start_idx]->vma;
00114     struct jitentry * ee = entries_address_ascending[end_idx];
00115     unsigned long long vma_end = ee->vma + ee->code_size;
00116     int size = vma_end - vma_start;
00117 
00118     section_name = bfd_get_unique_section_name(cur_bfd, ".text", &idx);
00119     verbprintf(debug, "section idx=%i, name=%s, vma_start=%llx, size=%i\n",
00120            idx, section_name, vma_start, size);
00121 
00122     section = create_section(cur_bfd, section_name, size, vma_start,
00123                SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_CODE|SEC_HAS_CONTENTS);
00124     if (section)
00125         entries_address_ascending[start_idx]->section = section;
00126     else
00127         rc = OP_JIT_CONV_FAIL;
00128 
00129     return rc;
00130 }
00131 
00132 /* fill a section contents at a given offset from the start of the section */
00133 int fill_section_content(bfd * abfd, asection * section,
00134              void const * b, file_ptr offset, size_t sz)
00135 {
00136     if (bfd_set_section_contents(abfd, section, b, offset, sz) == FALSE) {
00137         bfd_perror("bfd_set_section_contents");
00138         return OP_JIT_CONV_FAIL;
00139     }
00140     return OP_JIT_CONV_OK;
00141 }
00142 
00143 /*
00144  * Copy all code of the functions that are within start_idx and end_idx to 
00145  * the section.
00146  */
00147 static int fill_text_section_content(asection * section, int start_idx,
00148                      int end_idx)
00149 {
00150     int rc = OP_JIT_CONV_OK;
00151     unsigned long long vma_start =
00152         entries_address_ascending[start_idx]->vma;
00153     struct jitentry const * e;
00154     int i;
00155 
00156     for (i = start_idx; i <= end_idx; i++) {
00157         e = entries_address_ascending[i];
00158         verbprintf(debug, "section = %s, i = %i, code = %llx,"
00159                " vma = %llx, offset = %llx,"
00160                "size = %i, name = %s\n",
00161                section->name, i,
00162                (unsigned long long) (uintptr_t) e->code,
00163                e->vma, e->vma - vma_start,
00164                e->code_size, e->symbol_name);
00165         /* the right part that is created by split_entry may 
00166          * have no code; also, the agent may have passed NULL
00167          * for the code location.
00168          */
00169         if (e->code) {
00170             rc = fill_section_content(cur_bfd, section,
00171                 e->code, (file_ptr) (e->vma - vma_start),
00172                 (bfd_size_type)e->code_size);
00173             if (rc != OP_JIT_CONV_OK)
00174                 break;
00175         }
00176     }
00177     return rc;
00178 }
00179 
00180 
00181 /* Walk over the symbols sorted by address and create ELF sections. Whenever we
00182  * have a gap greater or equal to 4096 make a new section.
00183  */
00184 int partition_sections(void)
00185 {
00186     int rc = OP_JIT_CONV_OK;
00187     u32 i, j;
00188     struct jitentry const * pred;
00189     struct jitentry const * entry;
00190     unsigned long long end_addr;
00191 
00192     // i: start index of the section
00193     i = 0;
00194     for (j = 1; j < entry_count; j++) {
00195         entry = entries_address_ascending[j];
00196         pred = entries_address_ascending[j - 1];
00197         end_addr = pred->vma + pred->code_size;
00198         // calculate gap between code, if it is more than one page
00199         // create an additional section
00200         if ((entry->vma - end_addr) >= 4096) {
00201             rc = create_text_section(i, j - 1);
00202             if (rc == OP_JIT_CONV_FAIL)
00203                 goto out;
00204             i = j;
00205         }
00206     }
00207     // this holds always if we have at least one jitentry
00208     if (i < entry_count)
00209         rc = create_text_section(i, entry_count - 1);
00210 out:
00211     return rc;
00212 }
00213 
00214 
00215 /* Fill the code content into the sections created by partition_sections() */
00216 int fill_sections(void)
00217 {
00218     int rc = OP_JIT_CONV_OK;
00219     u32 i, j;
00220     asection * section;
00221 
00222     rc = fill_symtab();
00223     if (rc == OP_JIT_CONV_FAIL)
00224         goto out;
00225 
00226     verbprintf(debug, "opjitconv: fill_sections\n");
00227     i = 0;
00228     for (j = 1; j < entry_count; j++) {
00229         if (entries_address_ascending[j]->section) {
00230             section = entries_address_ascending[i]->section;
00231             rc = fill_text_section_content(section, i,
00232                                j - 1);
00233             if (rc == OP_JIT_CONV_FAIL)
00234                 goto out;
00235             i = j;
00236         }
00237     }
00238     // this holds always if we have at least one jitentry
00239     if (i < entry_count) {
00240         section = entries_address_ascending[i]->section;
00241         rc = fill_text_section_content(section,
00242                            i, entry_count - 1);
00243     }
00244 out:
00245     return rc;
00246 }
00247 
00248 
00249 /* create the elf file */
00250 bfd * open_elf(char const * filename)
00251 {
00252     bfd * abfd;
00253 
00254     abfd = bfd_openw(filename, dump_bfd_target_name);
00255     if (!abfd) {
00256         bfd_perror("bfd_openw");
00257         goto error1;
00258     }
00259     if (bfd_set_format(abfd, bfd_object) == FALSE) {
00260         bfd_perror("bfd_set_format");
00261         goto error;
00262     }
00263     if (bfd_set_arch_mach(abfd, dump_bfd_arch, dump_bfd_mach) == FALSE) {
00264         bfd_perror("bfd_set_format");
00265         goto error;
00266     }
00267     return abfd;
00268 error:
00269     bfd_close(abfd);
00270 error1:
00271     return NULL;
00272 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1