00001
00017 #include "opjitconv.h"
00018 #include "jitdump.h"
00019 #include "opd_printf.h"
00020 #include "op_libiberty.h"
00021
00022 #include <string.h>
00023 #include <stdio.h>
00024
00025
00026 static int parse_code_load(void const * ptr_arg, int size,
00027 unsigned long long end_time)
00028 {
00029 struct jitentry * entry;
00030 int rc = OP_JIT_CONV_OK;
00031 char const * ptr = ptr_arg;
00032 struct jr_code_load const * rec = ptr_arg;
00033 char const * end;
00034 size_t padding_count, rec_totalsize;
00035 end = rec->code_addr ? ptr + size : NULL;
00036
00037 entry = xcalloc(1, sizeof(struct jitentry));
00038
00039
00040 entry->next = NULL;
00041 ptr += sizeof(*rec);
00042
00043 entry->symbol_name = (char *)ptr;
00044 entry->sym_name_malloced = 0;
00045 ptr += strlen(ptr) + 1;
00046 entry->code = rec->code_addr ? ptr : NULL;
00047 entry->vma = rec->vma;
00048 entry->code_size = rec->code_size;
00049 entry->section = NULL;
00050 entry->life_start = rec->timestamp;
00051
00052
00053
00054 entry->life_end = end_time;
00055
00056
00057 entry->next = jitentry_list;
00058 jitentry_list = entry;
00059
00060
00061
00062
00063 rec_totalsize = sizeof(*rec) + strlen(entry->symbol_name) + 1 + entry->code_size;
00064 padding_count = PADDING_8ALIGNED(rec_totalsize);
00065
00066 verbprintf(debug, "record0: name=%s, vma=%llx, code_size=%i, "
00067 "padding_count=%llu, life_start=%lli, life_end=%lli\n", entry->symbol_name,
00068 entry->vma, entry->code_size, (unsigned long long)padding_count, entry->life_start,
00069 entry->life_end);
00070
00071
00072
00073 if (end && (ptr + entry->code_size + padding_count != end)) {
00074 verbprintf(debug, "record total size mismatch\n");
00075 rc = OP_JIT_CONV_FAIL;
00076 }
00077 return rc;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086 static void parse_code_unload(void const * ptr, unsigned long long end_time)
00087 {
00088 struct jr_code_unload const * rec = ptr;
00089 struct jitentry * entry;
00090
00091 verbprintf(debug,"record1: vma=%llx, life_end=%lli\n",
00092 rec->vma, rec->timestamp);
00099 if (rec->timestamp > 0 && rec->vma != 0) {
00100 for (entry = jitentry_list; entry; entry = entry->next) {
00101 if (entry->vma == rec->vma &&
00102 entry->life_end == end_time) {
00103 entry->life_end = rec->timestamp;
00104 verbprintf(debug,"matching record found\n");
00105 break;
00106 }
00107 }
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116 static void parse_code_debug_info(void const * ptr, void const * end,
00117 unsigned long long end_time)
00118 {
00119 struct jr_code_debug_info const * rec = ptr;
00120 struct jitentry_debug_line * debug_line =
00121 xmalloc(sizeof(struct jitentry_debug_line));
00122
00123 debug_line->data = rec;
00124 debug_line->end = end;
00125 debug_line->life_start = rec->timestamp;
00126 debug_line->life_end = end_time;
00127
00128 debug_line->next = jitentry_debug_line_list;
00129 jitentry_debug_line_list = debug_line;
00130 }
00131
00132
00133
00134
00135
00136
00137 static int parse_entries(void const * ptr, void const * end,
00138 unsigned long long end_time)
00139 {
00140 int rc = OP_JIT_CONV_OK;
00141 struct jr_prefix const * rec = ptr;
00142
00143 while ((void *)rec + sizeof(struct jr_prefix) < end) {
00144 if (((void *) rec + rec->total_size) > end) {
00145 verbprintf(debug, "record past end of file\n");
00146 rc = OP_JIT_CONV_FAIL;
00147 break;
00148 }
00149
00150 switch (rec->id) {
00151 case JIT_CODE_LOAD:
00152 if (parse_code_load(rec, rec->total_size, end_time)) {
00153 rc = OP_JIT_CONV_FAIL;
00154 break;
00155 }
00156 break;
00157
00158 case JIT_CODE_UNLOAD:
00159 parse_code_unload(rec, end_time);
00160 break;
00161
00162
00163 case JIT_CODE_CLOSE:
00164 break;
00165
00166 case JIT_CODE_DEBUG_INFO:
00167 if (rec->total_size == 0) {
00168
00169
00170
00171 rc = OP_JIT_CONV_FAIL;
00172 break;
00173 }
00174
00175 parse_code_debug_info(rec, end, end_time);
00176 break;
00177
00178 default:
00179 verbprintf(debug, "unknown record type\n");
00180 rc = OP_JIT_CONV_FAIL;
00181 break;
00182 }
00183
00184
00185 rec = (void *)rec + rec->total_size;
00186 }
00187
00188 return rc;
00189 }
00190
00191
00192
00193
00194
00195
00196 static int parse_header(char const ** ptr, char const * end)
00197 {
00198 int rc = OP_JIT_CONV_OK;
00199 struct jitheader const * header;
00200
00201 if (*ptr + sizeof(struct jitheader) >= end) {
00202 verbprintf(debug,
00203 "opjitconv: EOF in jitdump file, no header\n");
00204 rc = OP_JIT_CONV_FAIL;
00205 goto out;
00206 }
00207 header = (struct jitheader *)*ptr;
00208 if (header->magic != JITHEADER_MAGIC) {
00209 verbprintf(debug, "opjitconv: Wrong jitdump file magic\n");
00210 rc = OP_JIT_CONV_FAIL;
00211 goto out;
00212 }
00213 if (header->version != JITHEADER_VERSION) {
00214 verbprintf(debug, "opjitconv: Wrong jitdump file version\n");
00215 rc = OP_JIT_CONV_FAIL;
00216 goto out;
00217 }
00218 if (*ptr + header->totalsize > end) {
00219 verbprintf(debug, "opjitconv: EOF in jitdump file, not enough "
00220 "data for header\n");
00221 rc = OP_JIT_CONV_FAIL;
00222 goto out;
00223 }
00224 dump_bfd_arch = header->bfd_arch;
00225 dump_bfd_mach = header->bfd_mach;
00226 dump_bfd_target_name = header->bfd_target;
00227 verbprintf(debug, "header: bfd-arch=%i, bfd-mach=%i,"
00228 " bfd_target_name=%s\n", dump_bfd_arch, dump_bfd_mach,
00229 dump_bfd_target_name);
00230 *ptr = *ptr + header->totalsize;
00231 out:
00232 return rc;
00233 }
00234
00235
00236
00237
00238
00239 int parse_all(void const * start, void const * end,
00240 unsigned long long end_time)
00241 {
00242 char const * ptr = start;
00243 if (!parse_header(&ptr, end))
00244 return parse_entries(ptr, end, end_time);
00245 else
00246 return OP_JIT_CONV_FAIL;
00247 }