Revision b8076a74 dyngen.c
b/dyngen.c | ||
---|---|---|
1203 | 1203 |
} |
1204 | 1204 |
} |
1205 | 1205 |
|
1206 |
#ifdef HOST_IA64 |
|
1207 |
|
|
1208 |
#define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */ |
|
1209 |
|
|
1210 |
struct plt_entry { |
|
1211 |
struct plt_entry *next; |
|
1212 |
const char *name; |
|
1213 |
unsigned long addend; |
|
1214 |
} *plt_list; |
|
1215 |
|
|
1216 |
static int |
|
1217 |
get_plt_index (const char *name, unsigned long addend) |
|
1218 |
{ |
|
1219 |
struct plt_entry *plt, *prev= NULL; |
|
1220 |
int index = 0; |
|
1221 |
|
|
1222 |
/* see if we already have an entry for this target: */ |
|
1223 |
for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next) |
|
1224 |
if (strcmp(plt->name, name) == 0 && plt->addend == addend) |
|
1225 |
return index; |
|
1226 |
|
|
1227 |
/* nope; create a new PLT entry: */ |
|
1228 |
|
|
1229 |
plt = malloc(sizeof(*plt)); |
|
1230 |
if (!plt) { |
|
1231 |
perror("malloc"); |
|
1232 |
exit(1); |
|
1233 |
} |
|
1234 |
memset(plt, 0, sizeof(*plt)); |
|
1235 |
plt->name = strdup(name); |
|
1236 |
plt->addend = addend; |
|
1237 |
|
|
1238 |
/* append to plt-list: */ |
|
1239 |
if (prev) |
|
1240 |
prev->next = plt; |
|
1241 |
else |
|
1242 |
plt_list = plt; |
|
1243 |
return index; |
|
1244 |
} |
|
1245 |
|
|
1246 |
#endif |
|
1247 |
|
|
1206 | 1248 |
#ifdef HOST_ARM |
1207 | 1249 |
|
1208 | 1250 |
int arm_emit_ldr_info(const char *name, unsigned long start_offset, |
... | ... | |
1392 | 1434 |
/* 08 00 84 00 */ |
1393 | 1435 |
if (get32((uint32_t *)p) != 0x00840008) |
1394 | 1436 |
error("br.ret.sptk.many b0;; expected at the end of %s", name); |
1395 |
copy_size = p - p_start;
|
|
1437 |
copy_size = p_end - p_start;
|
|
1396 | 1438 |
} |
1397 | 1439 |
#elif defined(HOST_SPARC) |
1398 | 1440 |
{ |
... | ... | |
1529 | 1571 |
} |
1530 | 1572 |
fprintf(outfile, ";\n"); |
1531 | 1573 |
} |
1574 |
#if defined(HOST_IA64) |
|
1575 |
fprintf(outfile, " extern char %s;\n", name); |
|
1576 |
#else |
|
1532 | 1577 |
fprintf(outfile, " extern void %s();\n", name); |
1578 |
#endif |
|
1533 | 1579 |
|
1534 | 1580 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
1535 | 1581 |
host_ulong offset = get_rel_offset(rel); |
... | ... | |
1550 | 1596 |
continue; |
1551 | 1597 |
} |
1552 | 1598 |
#endif |
1553 |
#ifdef __APPLE__
|
|
1599 |
#if defined(__APPLE__)
|
|
1554 | 1600 |
/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */ |
1555 | 1601 |
fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name); |
1602 |
#elif defined(HOST_IA64) |
|
1603 |
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) |
|
1604 |
/* |
|
1605 |
* PCREL21 br.call targets generally |
|
1606 |
* are out of range and need to go |
|
1607 |
* through an "import stub". |
|
1608 |
*/ |
|
1609 |
fprintf(outfile, " extern char %s;\n", |
|
1610 |
sym_name); |
|
1556 | 1611 |
#else |
1557 | 1612 |
fprintf(outfile, "extern char %s;\n", sym_name); |
1558 | 1613 |
#endif |
... | ... | |
1964 | 2019 |
} |
1965 | 2020 |
#elif defined(HOST_IA64) |
1966 | 2021 |
{ |
2022 |
unsigned long sym_idx; |
|
2023 |
long code_offset; |
|
1967 | 2024 |
char name[256]; |
1968 | 2025 |
int type; |
1969 |
int addend; |
|
2026 |
long addend; |
|
2027 |
|
|
1970 | 2028 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
1971 |
if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { |
|
1972 |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
|
1973 |
get_reloc_expr(name, sizeof(name), sym_name); |
|
1974 |
type = ELF64_R_TYPE(rel->r_info); |
|
1975 |
addend = rel->r_addend; |
|
1976 |
switch(type) { |
|
1977 |
case R_IA64_LTOFF22: |
|
1978 |
error("must implemnt R_IA64_LTOFF22 relocation"); |
|
1979 |
case R_IA64_PCREL21B: |
|
1980 |
error("must implemnt R_IA64_PCREL21B relocation"); |
|
1981 |
default: |
|
1982 |
error("unsupported ia64 relocation (%d)", type); |
|
1983 |
} |
|
1984 |
} |
|
2029 |
sym_idx = ELF64_R_SYM(rel->r_info); |
|
2030 |
if (rel->r_offset < start_offset |
|
2031 |
|| rel->r_offset >= start_offset + copy_size) |
|
2032 |
continue; |
|
2033 |
sym_name = (strtab + symtab[sym_idx].st_name); |
|
2034 |
if (strstart(sym_name, "__op_jmp", &p)) { |
|
2035 |
int n; |
|
2036 |
n = strtol(p, NULL, 10); |
|
2037 |
/* __op_jmp relocations are done at |
|
2038 |
runtime to do translated block |
|
2039 |
chaining: the offset of the instruction |
|
2040 |
needs to be stored */ |
|
2041 |
fprintf(outfile, " jmp_offsets[%d] =" |
|
2042 |
"%ld + (gen_code_ptr - gen_code_buf);\n", |
|
2043 |
n, rel->r_offset - start_offset); |
|
2044 |
continue; |
|
2045 |
} |
|
2046 |
get_reloc_expr(name, sizeof(name), sym_name); |
|
2047 |
type = ELF64_R_TYPE(rel->r_info); |
|
2048 |
addend = rel->r_addend; |
|
2049 |
code_offset = rel->r_offset - start_offset; |
|
2050 |
switch(type) { |
|
2051 |
case R_IA64_IMM64: |
|
2052 |
fprintf(outfile, |
|
2053 |
" ia64_imm64(gen_code_ptr + %ld, " |
|
2054 |
"%s + %ld);\n", |
|
2055 |
code_offset, name, addend); |
|
2056 |
break; |
|
2057 |
case R_IA64_LTOFF22X: |
|
2058 |
case R_IA64_LTOFF22: |
|
2059 |
fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld," |
|
2060 |
" %s + %ld, %d);\n", |
|
2061 |
code_offset, name, addend, |
|
2062 |
(type == R_IA64_LTOFF22X)); |
|
2063 |
break; |
|
2064 |
case R_IA64_LDXMOV: |
|
2065 |
fprintf(outfile, |
|
2066 |
" ia64_ldxmov(gen_code_ptr + %ld," |
|
2067 |
" %s + %ld);\n", code_offset, name, addend); |
|
2068 |
break; |
|
2069 |
|
|
2070 |
case R_IA64_PCREL21B: |
|
2071 |
if (strstart(sym_name, "__op_gen_label", NULL)) { |
|
2072 |
fprintf(outfile, |
|
2073 |
" ia64_imm21b(gen_code_ptr + %ld," |
|
2074 |
" (long) (%s + %ld -\n\t\t" |
|
2075 |
"((long) gen_code_ptr + %ld)) >> 4);\n", |
|
2076 |
code_offset, name, addend, |
|
2077 |
code_offset & ~0xfUL); |
|
2078 |
} else { |
|
2079 |
fprintf(outfile, |
|
2080 |
" IA64_PLT(gen_code_ptr + %ld, " |
|
2081 |
"%d);\t/* %s + %ld */\n", |
|
2082 |
code_offset, |
|
2083 |
get_plt_index(sym_name, addend), |
|
2084 |
sym_name, addend); |
|
2085 |
} |
|
2086 |
break; |
|
2087 |
default: |
|
2088 |
error("unsupported ia64 relocation (0x%x)", |
|
2089 |
type); |
|
2090 |
} |
|
1985 | 2091 |
} |
2092 |
fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n", |
|
2093 |
copy_size - 16 + 2); |
|
1986 | 2094 |
} |
1987 | 2095 |
#elif defined(HOST_SPARC) |
1988 | 2096 |
{ |
... | ... | |
2236 | 2344 |
" LDREntry *arm_ldr_ptr = arm_ldr_table;\n" |
2237 | 2345 |
" uint32_t *arm_data_ptr = arm_data_table;\n"); |
2238 | 2346 |
#endif |
2347 |
#ifdef HOST_IA64 |
|
2348 |
{ |
|
2349 |
long addend, not_first = 0; |
|
2350 |
unsigned long sym_idx; |
|
2351 |
int index, max_index; |
|
2352 |
const char *sym_name; |
|
2353 |
EXE_RELOC *rel; |
|
2354 |
|
|
2355 |
max_index = -1; |
|
2356 |
for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
|
2357 |
sym_idx = ELF64_R_SYM(rel->r_info); |
|
2358 |
sym_name = (strtab + symtab[sym_idx].st_name); |
|
2359 |
if (strstart(sym_name, "__op_gen_label", NULL)) |
|
2360 |
continue; |
|
2361 |
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) |
|
2362 |
continue; |
|
2363 |
|
|
2364 |
addend = rel->r_addend; |
|
2365 |
index = get_plt_index(sym_name, addend); |
|
2366 |
if (index <= max_index) |
|
2367 |
continue; |
|
2368 |
max_index = index; |
|
2369 |
fprintf(outfile, " extern void %s(void);\n", sym_name); |
|
2370 |
} |
|
2371 |
|
|
2372 |
fprintf(outfile, |
|
2373 |
" struct ia64_fixup *plt_fixes = NULL, " |
|
2374 |
"*ltoff_fixes = NULL;\n" |
|
2375 |
" static long plt_target[] = {\n\t"); |
|
2376 |
|
|
2377 |
max_index = -1; |
|
2378 |
for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
|
2379 |
sym_idx = ELF64_R_SYM(rel->r_info); |
|
2380 |
sym_name = (strtab + symtab[sym_idx].st_name); |
|
2381 |
if (strstart(sym_name, "__op_gen_label", NULL)) |
|
2382 |
continue; |
|
2383 |
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) |
|
2384 |
continue; |
|
2385 |
|
|
2386 |
addend = rel->r_addend; |
|
2387 |
index = get_plt_index(sym_name, addend); |
|
2388 |
if (index <= max_index) |
|
2389 |
continue; |
|
2390 |
max_index = index; |
|
2391 |
|
|
2392 |
if (not_first) |
|
2393 |
fprintf(outfile, ",\n\t"); |
|
2394 |
not_first = 1; |
|
2395 |
if (addend) |
|
2396 |
fprintf(outfile, "(long) &%s + %ld", sym_name, addend); |
|
2397 |
else |
|
2398 |
fprintf(outfile, "(long) &%s", sym_name); |
|
2399 |
} |
|
2400 |
fprintf(outfile, "\n };\n" |
|
2401 |
" unsigned int plt_offset[%u] = { 0 };\n", max_index + 1); |
|
2402 |
} |
|
2403 |
#endif |
|
2239 | 2404 |
|
2240 | 2405 |
fprintf(outfile, |
2241 | 2406 |
"\n" |
... | ... | |
2298 | 2463 |
" }\n" |
2299 | 2464 |
" the_end:\n" |
2300 | 2465 |
); |
2466 |
#ifdef HOST_IA64 |
|
2467 |
fprintf(outfile, |
|
2468 |
" ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, " |
|
2469 |
"(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t" |
|
2470 |
"sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t" |
|
2471 |
"plt_target, plt_offset);\n"); |
|
2472 |
#endif |
|
2301 | 2473 |
|
2302 | 2474 |
/* generate some code patching */ |
2303 | 2475 |
#ifdef HOST_ARM |
Also available in: Unified diff