15 |
|
|
16 |
*/ |
*/ |
17 |
|
|
18 |
|
/* for testing in standalone manner define STAND |
19 |
|
You may then compile this file cc -g -DSTAND -DDEBUG -I../hn |
20 |
|
a.out /tmp/foo.o /public/gcl/unixport/saved_kcl /public/gcl/unixport/ |
21 |
|
will write a /tmp/sfasltest file |
22 |
|
which you can use comp to compare with one produced by ld. |
23 |
|
*/ |
24 |
|
|
25 |
|
|
26 |
#ifndef __linux__ |
#ifndef __linux__ |
27 |
#define ELF_TARGET_SPARC 1 |
#define ELF_TARGET_SPARC 1 |
28 |
#endif |
#endif |
37 |
|
|
38 |
#include <elf.h> |
#include <elf.h> |
39 |
|
|
40 |
|
#include "gclincl.h" |
41 |
|
#ifdef HAVE_LIBBFD |
42 |
|
#include <bfd.h> |
43 |
|
#endif |
44 |
|
|
45 |
|
#ifdef STAND |
46 |
|
#include "include.h" |
47 |
|
|
48 |
|
#define FEerror(a...) do {fprintf(stderr,##a);exit(1);} while (0) |
49 |
|
#endif |
50 |
|
|
51 |
static void relocate_symbols(Elf32_Sym *sym,int nsyms,int nscns, int *init_address_ptr); |
static void relocate_symbols(Elf32_Sym *sym,int nsyms,int nscns, int *init_address_ptr); |
52 |
static void relocate(Elf32_Sym *symbol_table,Elf32_Rela |
static void relocate(Elf32_Sym *symbol_table,Elf32_Rela |
53 |
*reloc_info,Elf32_Word sh_type); |
*reloc_info,Elf32_Word sh_type); |
54 |
|
|
55 |
|
|
56 |
#ifdef STAND |
#ifdef STAND |
57 |
char *kcl_self; |
char *kcl_self,*system_directory; |
58 |
main(argc,argv) |
main(argc,argv) |
59 |
char *argv[]; |
char *argv[]; |
60 |
{char *file ; |
{char *file ; |
61 |
file = argv[1]; |
file = argv[1]; |
62 |
kcl_self = argv[2]; |
kcl_self = argv[2]; |
63 |
|
system_directory = argv[3]; |
64 |
|
/* _fmode = O_BINARY; */ |
65 |
fasload(file); |
fasload(file); |
66 |
|
return 0; |
67 |
} |
} |
68 |
|
|
69 |
|
node_compare(node1,node2) |
70 |
|
char *node1, *node2; |
71 |
|
{ return(strcmp( ((struct node *)node1)->string, |
72 |
|
((struct node *)node2)->string));} |
73 |
|
|
74 |
|
|
75 |
|
|
76 |
|
read_special_symbols(symfile) |
77 |
|
char *symfile; |
78 |
|
{FILE *symin; |
79 |
|
char *symbols; |
80 |
|
int i,jj; |
81 |
|
struct lsymbol_table tab; |
82 |
|
if (!(symin=fopen(symfile,"r"))) |
83 |
|
{perror(symfile);exit(1);}; |
84 |
|
if(!fread((char *)&tab,sizeof(tab),1,symin)) |
85 |
|
FEerror("No header",0,0); |
86 |
|
symbols=malloc(tab.tot_leng); |
87 |
|
c_table.alloc_length=( (PTABLE_EXTRA+ tab.n_symbols)); |
88 |
|
(c_table.ptable) = (TABL *) malloc(sizeof(struct node) * c_table.alloc_length); |
89 |
|
if (!(c_table.ptable)) {perror("could not allocate"); exit(1);}; |
90 |
|
i=0; c_table.length=tab.n_symbols; |
91 |
|
while(i < tab.n_symbols) |
92 |
|
{ fread((char *)&jj,sizeof(int),1,symin); |
93 |
|
(SYM_ADDRESS(c_table,i))=jj; |
94 |
|
SYM_STRING(c_table,i)=symbols; |
95 |
|
|
96 |
|
while( *(symbols++) = getc(symin)) |
97 |
|
{;} |
98 |
|
/* dprintf( name %s , SYM_STRING(c_table,i)); |
99 |
|
dprintf( addr %d , jj); |
100 |
|
*/ |
101 |
|
i++; |
102 |
|
} |
103 |
|
|
104 |
|
/* |
105 |
|
for(i=0;i< 5;i++) |
106 |
|
{printf("Symbol: %d %s %d \n",i,SYM_STRINGN(c_table,i), |
107 |
|
SYM_ADDRESS(*ptable,i));} |
108 |
|
*/ |
109 |
|
} |
110 |
|
|
111 |
#endif |
#endif |
112 |
|
|
113 |
static Elf32_Ehdr *file_h; |
static Elf32_Ehdr *file_h; |
149 |
Elf32_Shdr *shp; |
Elf32_Shdr *shp; |
150 |
int file; |
int file; |
151 |
struct stat stat_buf; |
struct stat stat_buf; |
152 |
|
#ifndef STAND |
153 |
object * old_vs_base = vs_base ; |
object * old_vs_base = vs_base ; |
154 |
object * old_vs_top = vs_top ; |
object * old_vs_top = vs_top ; |
155 |
|
#endif |
156 |
int symtab_index,j; |
int symtab_index,j; |
157 |
int nsyms; |
int nsyms; |
158 |
int init_address=-1; |
int init_address=-1; |
167 |
section = section_org; |
section = section_org; |
168 |
|
|
169 |
#ifdef STAND |
#ifdef STAND |
170 |
strcpy(filename,faslfile); |
strcpy(filename,(char *)faslfile); |
171 |
fp=fopen(filename,RDONLY); |
fp=fopen(filename,RDONLY); |
172 |
#else |
#else |
173 |
coerce_to_filename(faslfile, filename); |
coerce_to_filename(faslfile, filename); |
247 |
extra_bss = 0; |
extra_bss = 0; |
248 |
|
|
249 |
|
|
250 |
|
#ifndef STAND |
251 |
memory = alloc_object(t_cfdata); |
memory = alloc_object(t_cfdata); |
252 |
memory->cfd.cfd_self = 0; |
memory->cfd.cfd_self = 0; |
253 |
memory->cfd.cfd_start = 0; |
memory->cfd.cfd_start = 0; |
254 |
memory->cfd.cfd_size = current + (max_align > sizeof(char *) ? |
memory->cfd.cfd_size = current + (max_align > sizeof(char *) ? |
255 |
max_align :0); |
max_align :0); |
256 |
|
|
|
|
|
257 |
the_start=start_address= |
the_start=start_address= |
258 |
memory->cfd.cfd_start = |
memory->cfd.cfd_start = |
259 |
alloc_contblock(memory->cfd.cfd_size); |
alloc_contblock(memory->cfd.cfd_size); |
260 |
|
#else |
261 |
|
memory=(object)malloc(sizeof(*memory)); |
262 |
|
memory->cfd.cfd_self = 0; |
263 |
|
memory->cfd.cfd_start = 0; |
264 |
|
memory->cfd.cfd_size = current + (max_align > sizeof(char *) ? |
265 |
|
max_align :0); |
266 |
|
the_start=start_address=memory->cfd.cfd_start= |
267 |
|
malloc(memory->cfd.cfd_size + 0x80000); |
268 |
|
the_start=start_address= (char *)(0x1000 * |
269 |
|
((((int)the_start + 0x70000) + 0x1000)/0x1000)); |
270 |
|
#endif |
271 |
|
|
272 |
/* make sure the memory is aligned */ |
/* make sure the memory is aligned */ |
273 |
start_address = ROUND_UP(start_address,max_align); |
start_address = ROUND_UP(start_address,max_align); |
294 |
for (j=1 ; j < file_h->e_shnum ; j++) |
for (j=1 ; j < file_h->e_shnum ; j++) |
295 |
{ |
{ |
296 |
shp = &SECTION_H(j); |
shp = &SECTION_H(j); |
297 |
if (shp->sh_type == SHT_RELA |
if ((shp->sh_type == SHT_RELA || shp->sh_type == SHT_REL) && |
298 |
&& (SECTION_H(shp->sh_info).sh_flags & SHF_ALLOC)) |
shp->sh_info<file_h->e_shnum && |
299 |
{ |
(SECTION_H(shp->sh_info).sh_flags & SHF_ALLOC)) |
|
int index_to_relocate = shp->sh_info; |
|
|
if (symtab_index != shp->sh_link) |
|
|
FEerror("unexpected symbol table used"); |
|
|
the_start = start_address + section[index_to_relocate].start; |
|
|
} |
|
|
else if (shp->sh_type == SHT_REL |
|
|
&& (SECTION_H(shp->sh_info).sh_flags & SHF_ALLOC)) |
|
300 |
{ |
{ |
301 |
int index_to_relocate = shp->sh_info; |
int index_to_relocate = shp->sh_info; |
302 |
if (symtab_index != shp->sh_link) |
if (symtab_index != shp->sh_link) |
303 |
FEerror("unexpected symbol table used"); |
FEerror("unexpected symbol table used"); |
304 |
the_start = start_address + section[index_to_relocate].start; |
the_start = start_address + section[index_to_relocate].start; |
305 |
} |
} |
306 |
|
/* else if (shp->sh_type == SHT_REL */ |
307 |
|
/* && (SECTION_H(shp->sh_info).sh_flags & SHF_ALLOC)) */ |
308 |
|
/* { */ |
309 |
|
/* int index_to_relocate = shp->sh_info; */ |
310 |
|
/* if (symtab_index != shp->sh_link) */ |
311 |
|
/* FEerror("unexpected symbol table used"); */ |
312 |
|
/* the_start = start_address + section[index_to_relocate].start; */ |
313 |
|
/* } */ |
314 |
|
|
315 |
else if ( (shp->sh_type == SHT_REL) || (shp->sh_type == SHT_RELA) ) |
else if ( (shp->sh_type == SHT_REL) || (shp->sh_type == SHT_RELA) ) |
316 |
{ if (get_section_number(".rel.stab") == j) |
{ if (get_section_number(".rel.stab") == j) |
322 |
{ |
{ |
323 |
int k=0; |
int k=0; |
324 |
char *rel = (char *) base + shp->sh_offset; |
char *rel = (char *) base + shp->sh_offset; |
325 |
for (k= 0; k< shp->sh_size ; k+= shp->sh_entsize) |
for (k= 0; k< shp->sh_size ; k+= shp->sh_entsize) |
326 |
relocate(symbol_table,(Elf32_Rela *)(rel + k),shp->sh_type); |
relocate(symbol_table,(Elf32_Rela *)(rel + k),shp->sh_type); |
327 |
} |
} |
328 |
} |
} |
329 |
} |
} |
330 |
|
|
331 |
|
#ifdef STAND |
332 |
|
{FILE *out;char pad=0; |
333 |
|
out=fopen("/tmp/sfasltest","wb"); |
334 |
|
for (j=1 ; j < file_h->e_shnum ; j++) |
335 |
|
if ((SECTION_H(j).sh_flags & SHF_ALLOC) && (SECTION_H(j).sh_type == SHT_PROGBITS)) |
336 |
|
memcpy(base+SECTION_H(j).sh_offset,start_address+section[j].start,SECTION_H(j).sh_size); |
337 |
|
fwrite((char *)base, stat_buf.st_size, 1, out); |
338 |
|
fclose(out);} |
339 |
|
printf("\n(start %x)\n",start_address); |
340 |
|
#else |
341 |
|
|
342 |
SEEK_TO_END_OFILE(fp); |
SEEK_TO_END_OFILE(fp); |
343 |
|
|
344 |
/* init_address += section[text_index].start ; */ |
/* init_address += section[text_index].start ; */ |
355 |
else |
else |
356 |
free(base); |
free(base); |
357 |
|
|
358 |
|
close_stream(faslfile); |
|
close_stream(faslfile); |
|
359 |
|
|
360 |
#ifdef CLEAR_CACHE |
#ifdef CLEAR_CACHE |
361 |
CLEAR_CACHE; |
CLEAR_CACHE; |
365 |
|
|
366 |
vs_base = old_vs_base; |
vs_base = old_vs_base; |
367 |
vs_top = old_vs_top; |
vs_top = old_vs_top; |
368 |
|
|
369 |
if(symbol_value(sLAload_verboseA)!=Cnil) |
if(symbol_value(sLAload_verboseA)!=Cnil) |
370 |
printf("start address -T %x ",memory->cfd.cfd_start); |
printf("start address -T %x ",memory->cfd.cfd_start); |
371 |
return(memory->cfd.cfd_size); |
return(memory->cfd.cfd_size); |
372 |
|
|
373 |
|
#endif /* STAND */ |
374 |
|
|
375 |
} |
} |
376 |
|
|
377 |
|
|
445 |
} |
} |
446 |
} |
} |
447 |
|
|
448 |
|
|
449 |
|
#ifdef HAVE_LIBBFD |
450 |
|
|
451 |
|
typedef struct { |
452 |
|
unsigned int type; |
453 |
|
reloc_howto_type *h; |
454 |
|
} mtbl; |
455 |
|
|
456 |
|
int in_bfd_init=0; |
457 |
|
|
458 |
|
static void |
459 |
|
do_bfd_reloc(unsigned int oc,unsigned int val, |
460 |
|
unsigned int *where) { |
461 |
|
|
462 |
|
static bfd *dum; |
463 |
|
static reloc_howto_type * m[BFD_RELOC_UNUSED]; |
464 |
|
reloc_howto_type *h; |
465 |
|
|
466 |
|
if (!m[0]) { |
467 |
|
|
468 |
|
bfd_reloc_code_real_type t; |
469 |
|
|
470 |
|
in_bfd_init=1; |
471 |
|
|
472 |
|
bfd_init(); |
473 |
|
|
474 |
|
if (!(dum=bfd_openr("/dev/null",NULL))) |
475 |
|
FEerror("Cannot open dummy bfd\n"); |
476 |
|
|
477 |
|
for (t=BFD_RELOC_UNUSED;t>_dummy_first_bfd_reloc_code_real;t--) |
478 |
|
if ((h=bfd_reloc_type_lookup(dum,t))) |
479 |
|
m[h->type]=h; |
480 |
|
|
481 |
|
in_bfd_init=0; |
482 |
|
|
483 |
|
} |
484 |
|
|
485 |
|
if (oc>=BFD_RELOC_UNUSED || !m[oc]) |
486 |
|
FEerror("Cannot lookup type %u\n",oc); |
487 |
|
h=m[oc]; |
488 |
|
|
489 |
|
if (h->pc_relative) |
490 |
|
val-=(unsigned int)where; |
491 |
|
|
492 |
|
val>>=h->rightshift; |
493 |
|
val<<=h->bitpos; |
494 |
|
/* *where = ( (*where & ~h->dst_mask) | */ |
495 |
|
/* (((*where & h->src_mask) + val) & h->dst_mask)); */ |
496 |
|
|
497 |
|
#define DOIT(x) \ |
498 |
|
x = ( (x & ~h->dst_mask) | (((x & h->src_mask) + val) & h->dst_mask)) |
499 |
|
|
500 |
|
switch (h->size) { |
501 |
|
case 0: |
502 |
|
{ |
503 |
|
char x = bfd_get_8 (dum, (char *) where); |
504 |
|
DOIT (x); |
505 |
|
bfd_put_8 (dum, x, (unsigned char *) where); |
506 |
|
} |
507 |
|
break; |
508 |
|
|
509 |
|
case 1: |
510 |
|
{ |
511 |
|
short x = bfd_get_16 (dum, (bfd_byte *) where); |
512 |
|
DOIT (x); |
513 |
|
bfd_put_16 (dum, (bfd_vma) x, (unsigned char *) where); |
514 |
|
} |
515 |
|
break; |
516 |
|
case 2: |
517 |
|
{ |
518 |
|
long x = bfd_get_32 (dum, (bfd_byte *) where); |
519 |
|
DOIT (x); |
520 |
|
bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); |
521 |
|
} |
522 |
|
break; |
523 |
|
case -2: |
524 |
|
{ |
525 |
|
long x = bfd_get_32 (dum, (bfd_byte *) where); |
526 |
|
val = -val; |
527 |
|
DOIT (x); |
528 |
|
bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); |
529 |
|
} |
530 |
|
break; |
531 |
|
|
532 |
|
case -1: |
533 |
|
{ |
534 |
|
long x = bfd_get_16 (dum, (bfd_byte *) where); |
535 |
|
val = -val; |
536 |
|
DOIT (x); |
537 |
|
bfd_put_16 (dum, (bfd_vma) x, (bfd_byte *) where); |
538 |
|
} |
539 |
|
break; |
540 |
|
|
541 |
|
case 3: |
542 |
|
/* Do nothing */ |
543 |
|
break; |
544 |
|
|
545 |
|
case 4: |
546 |
|
#ifdef BFD64 |
547 |
|
{ |
548 |
|
bfd_vma x = bfd_get_64 (dum, (bfd_byte *) where); |
549 |
|
DOIT (x); |
550 |
|
bfd_put_64 (dum, x, (bfd_byte *) where); |
551 |
|
} |
552 |
|
#else |
553 |
|
FEerror("Bad howto size %u\n",h->size); |
554 |
|
/* abort (); */ |
555 |
|
#endif |
556 |
|
break; |
557 |
|
default: |
558 |
|
FEerror("Bad howto size %u\n",h->size); |
559 |
|
break; |
560 |
|
} |
561 |
|
|
562 |
|
} |
563 |
|
|
564 |
|
#endif /* HAVE_LIBBFD */ |
565 |
|
|
566 |
static void |
static void |
567 |
relocate(symbol_table,reloc_info,sh_type) |
relocate(symbol_table,reloc_info,sh_type) |
568 |
Elf32_Rela *reloc_info; |
Elf32_Rela *reloc_info; |
582 |
FEerror("relocate() error: unknown sh_type in ELF object"); |
FEerror("relocate() error: unknown sh_type in ELF object"); |
583 |
b = (unsigned int) the_start; |
b = (unsigned int) the_start; |
584 |
s = symbol_table[ELF32_R_SYM(reloc_info->r_info)].st_value; |
s = symbol_table[ELF32_R_SYM(reloc_info->r_info)].st_value; |
585 |
|
/* printf("Doing %s\n",string_table + symbol_table[ELF32_R_SYM(reloc_info->r_info)].st_name); */ |
586 |
where = the_start + reloc_info->r_offset; |
where = the_start + reloc_info->r_offset; |
587 |
p = (unsigned int) where; |
p = (unsigned int) where; |
588 |
|
|
592 |
*(unsigned int *)where = ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
*(unsigned int *)where = ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
593 |
#define ADD_VAL(where, mask, val) \ |
#define ADD_VAL(where, mask, val) \ |
594 |
*(unsigned int *)where += ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
*(unsigned int *)where += ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
595 |
|
|
596 |
|
#ifdef HAVE_LIBBFD |
597 |
|
do_bfd_reloc(ELF32_R_TYPE(reloc_info->r_info),s+a,(unsigned int *)where); |
598 |
|
#else |
599 |
switch(ELF32_R_TYPE(reloc_info->r_info)){ |
switch(ELF32_R_TYPE(reloc_info->r_info)){ |
600 |
#if (defined(__svr4__) || defined(__linux__)) && defined(__i386__) |
#if (defined(__svr4__) || defined(__linux__)) && defined(__i386__) |
601 |
case R_386_NONE: |
case R_386_NONE: |
650 |
break; |
break; |
651 |
#endif |
#endif |
652 |
|
|
653 |
#else |
#else /* (defined(__svr4__) || defined(__linux__)) && defined(__i386__) */ |
654 |
case R_SPARC_WDISP30: |
case R_SPARC_WDISP30: |
655 |
/* v-disp30*/ |
/* v-disp30*/ |
656 |
val=(s+a-p) >> 2; |
val=(s+a-p) >> 2; |
680 |
val = (s+a) & MASK(10); |
val = (s+a) & MASK(10); |
681 |
*(short *)(where +2) |= val; |
*(short *)(where +2) |= val; |
682 |
break; |
break; |
683 |
#endif |
#endif /* (defined(__svr4__) || defined(__linux__)) && defined(__i386__) */ |
684 |
default: |
default: |
685 |
printf("(non supported relocation type %d)\n", |
printf("(non supported relocation type %d)\n", |
686 |
ELF32_R_TYPE(reloc_info->r_info)); |
ELF32_R_TYPE(reloc_info->r_info)); |
687 |
} |
} |
688 |
|
#endif /* HAVE_LIBBFD */ |
689 |
} |
} |
690 |
} |
} |
691 |
|
|