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
00026
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
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
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
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
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
00145
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
00166
00167
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
00182
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
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
00199
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
00208 if (i < entry_count)
00209 rc = create_text_section(i, entry_count - 1);
00210 out:
00211 return rc;
00212 }
00213
00214
00215
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
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
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 }