home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / bfd / amigadoslink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-09  |  28.6 KB  |  995 lines

  1. /* BFD back-end for Commodore-Amiga AmigaDOS binaries. Linker routines.
  2.    Copyright (C) 1990-1994 Free Software Foundation, Inc.
  3.    Contributed by Stephan Thesing
  4.  
  5. This file is part of BFD, the Binary File Descriptor library.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22. INODE
  23. amigalink, , implementation, amiga
  24. SECTION
  25.     amigalink
  26.  
  27. This is the description of the linker routines for the amiga.
  28. In fact, this includes a description of the changes made to the
  29. a.out code, in order to build a working linker for the Amiga.
  30. @menu
  31. @* alterations::
  32. @end menu
  33.  
  34. INODE 
  35. alterations, , , amigalink
  36. SUBSECTION
  37.     alterations
  38.  
  39. The file @file{aout-amiga.c} defines the amiga a.out backend. It differs from
  40. the sun3 backend only in these details:
  41.     o The @code{final_link} routine is @code{amiga_final_link}.
  42.     o The routine to get the relocated section contents is
  43.            @code{aout_bfd_get_relocated_section_contents}.
  44.  
  45. This ensures that the link is performed properly, but has the side effect of loosing
  46. performance.
  47.  
  48.  
  49. The amiga bfd code uses the same @code{amiga_final_link} routine, but with a 
  50. different <<get_relocated_section_contents>> entry: <<amiga_bfd_get_relocated_section_contents>>.
  51. The latter  differs from the routine of the a.out backend only in the application of relocs
  52.  to the section contents.
  53. @@*
  54.  
  55. The usage of a special linker code has one reason:
  56. The bfd library assumes that a program is always loaded at a known memory
  57. address. This is not a case on an Amiga. So the Amiga format has to take over
  58. some relocs to an executable output file. 
  59. This is not the case with a.out formats, so there relocations can be applied at link time,
  60. not at run time, like on the Amiga.
  61. The special routines compensate this: instead of applying the relocations, they are
  62. copied to the output file, if neccessary.
  63. As as consequence, the @code{final_link} and @code{get_relocated_section_contents} are nearly identical to
  64. the original routines from @file{linker.c} and @file{reloc.c}.
  65. */
  66.  
  67. #include "bfd.h"
  68. #include "bfdlink.h"
  69. #include "genlink.h"
  70. #include "sysdep.h"
  71. #include "libbfd.h"
  72.  
  73. #include "libamiga.h"
  74. #undef GET_SWORD
  75. #define aadata ((bfd)->tdata.amiga_data->a)
  76. #undef adata
  77. #include "libaout.h"
  78.  
  79.  
  80. #define max(x,y) (((x)<=(y))?(y):(x))
  81.  
  82. #define DEBUG_AMIGA 10000
  83.  
  84. #if DEBUG_AMIGA
  85. #include <varargs.h>
  86. static void error_print(va_alist)
  87. va_dcl
  88. {
  89. va_list args;
  90. char *fmt;
  91.  
  92. va_start(args);
  93. fmt=va_arg(args,char *);
  94.  
  95. (void)vfprintf(stderr,fmt,args);
  96. va_end(args);
  97. }
  98.  
  99. #define DPRINT(L,x) if (L>=DEBUG_AMIGA) error_print x
  100. #else
  101. #define DPRINT(L,x) 
  102. #endif
  103.  
  104. /* This one is used to indicate base-relative (and maybe later residentable) linking */
  105. int amiga_base_relative=0;
  106.  
  107. extern boolean default_indirect_link_order
  108.   PARAMS ((bfd *, struct bfd_link_info *, asection *,
  109.        struct bfd_link_order *, boolean));
  110.  
  111.  
  112.  
  113. bfd_byte *
  114. get_relocated_section_contents(bfd *, struct bfd_link_info *,
  115.                    struct bfd_link_order *, bfd_byte *,
  116.                    boolean , asymbol **);
  117. static bfd_reloc_status_type 
  118. amiga_perform_reloc(bfd *, arelent *, PTR, asection *, bfd *, char **);
  119. static bfd_reloc_status_type 
  120. aout_perform_reloc(bfd *, arelent *, PTR, asection *, bfd *, char **);
  121. static boolean
  122. amiga_reloc_link_order (bfd *, struct bfd_link_info *,asection *,struct bfd_link_order *);
  123.  
  124.  
  125. /* This one is nearly identical to bfd_generic_get_relocated_section_contents from reloc.c */
  126. bfd_byte *
  127. get_relocated_section_contents (abfd, link_info, link_order, data,
  128.                         relocateable, symbols)
  129.      bfd *abfd;
  130.      struct bfd_link_info *link_info;
  131.      struct bfd_link_order *link_order;
  132.      bfd_byte *data;
  133.      boolean relocateable;
  134.      asymbol **symbols;
  135. {
  136.   bfd *input_bfd = link_order->u.indirect.section->owner;
  137.   asection *input_section = link_order->u.indirect.section;
  138.  
  139.   long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  140.   arelent **reloc_vector = NULL;
  141.   long reloc_count;
  142.   bfd_reloc_status_type (*reloc_func)(bfd *, arelent *, PTR, asection *, bfd *, char **);
  143.  
  144.   DPRINT(5,("Entering get_rel_sec_cont\n"));
  145.   if (reloc_size < 0)
  146.     goto error_return;
  147.  
  148.   if (input_bfd->xvec->flavour==bfd_target_amiga_flavour)
  149.     reloc_func=amiga_perform_reloc;
  150.   else if (input_bfd->xvec->flavour==bfd_target_aout_flavour)
  151.     reloc_func=aout_perform_reloc;
  152.   else
  153.     {
  154.       bfd_set_error(bfd_error_bad_value);
  155.       goto error_return;
  156.     }
  157.  
  158.   reloc_vector = (arelent **) malloc (reloc_size);
  159.   if (reloc_vector == NULL && reloc_size != 0)
  160.     {
  161.       bfd_set_error (bfd_error_no_memory);
  162.       goto error_return;
  163.     }
  164.  
  165.   DPRINT(5,("GRSC: GetSecCont()\n"));
  166.   /* read in the section */
  167.   if (!bfd_get_section_contents (input_bfd,
  168.                  input_section,
  169.                  (PTR) data,
  170.                  0,
  171.                  input_section->_raw_size))
  172.     goto error_return;
  173.  
  174.   /* We're not relaxing the section, so just copy the size info */
  175.   input_section->_cooked_size = input_section->_raw_size;
  176.   input_section->reloc_done = true;
  177.  
  178.   DPRINT(5,("GRSC: CanReloc\n"));
  179.   reloc_count = bfd_canonicalize_reloc (input_bfd,
  180.                     input_section,
  181.                     reloc_vector,
  182.                     symbols);
  183.   if (reloc_count < 0)
  184.     goto error_return;
  185.  
  186.   if (reloc_count > 0)
  187.     {
  188.       arelent **parent;
  189.  
  190.       DPRINT(5,("reloc_count=%d\n",reloc_count));
  191.  
  192.       for (parent = reloc_vector; *parent != (arelent *) NULL;
  193.        parent++)
  194.     {
  195.       char *error_message = (char *) NULL;
  196.       bfd_reloc_status_type r ;
  197.  
  198.       DPRINT(5,("Applying a reloc\nparent=%lx, reloc_vector=%lx, *parent=%lx\n",parent,reloc_vector,*parent));
  199.       r=(*reloc_func) (input_bfd,
  200.                *parent,
  201.                (PTR) data,
  202.                input_section,
  203.                relocateable ? abfd : (bfd *) NULL,
  204.                &error_message);
  205.       
  206.       if (relocateable)
  207.         {
  208.           asection *os = input_section->output_section;
  209.  
  210.           DPRINT(5,("Keeping reloc\n"));
  211.           /* A partial link, so keep the relocs */
  212.           os->orelocation[os->reloc_count] = *parent;
  213.           os->reloc_count++;
  214.         }
  215.  
  216.       if (r != bfd_reloc_ok)
  217.         {
  218.           switch (r)
  219.         {
  220.         case bfd_reloc_undefined:
  221.           if (!((*link_info->callbacks->undefined_symbol)
  222.             (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
  223.              input_bfd, input_section, (*parent)->address)))
  224.             goto error_return;
  225.           break;
  226.         case bfd_reloc_dangerous:
  227.           BFD_ASSERT (error_message != (char *) NULL);
  228.           if (!((*link_info->callbacks->reloc_dangerous)
  229.             (link_info, error_message, input_bfd, input_section,
  230.              (*parent)->address)))
  231.             goto error_return;
  232.           break;
  233.         case bfd_reloc_overflow:
  234.           if (!((*link_info->callbacks->reloc_overflow)
  235.             (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
  236.              (*parent)->howto->name, (*parent)->addend,
  237.              input_bfd, input_section, (*parent)->address)))
  238.             goto error_return;
  239.           break;
  240.         case bfd_reloc_outofrange:
  241.         default:
  242.           DPRINT(10,("get_rel_sec_cont fails, perform reloc returned $%x\n",r));
  243.           abort ();
  244.           break;
  245.         }
  246.  
  247.         }
  248.     }
  249.     }
  250.   if (reloc_vector != NULL)
  251.     free (reloc_vector);
  252.   DPRINT(5,("GRSC: Returning ok\n"));
  253.   return data;
  254.  
  255. error_return:
  256.   DPRINT(5,("GRSC: Error_return\n"));
  257.   if (reloc_vector != NULL)
  258.     free (reloc_vector);
  259.   return NULL;
  260. }
  261.  
  262.  
  263. /* Add a value to a location */
  264. static bfd_reloc_status_type
  265. my_add_to(PTR data, int offset, int size, int add)
  266. {
  267.   signed char *p;
  268.   int val;
  269.   bfd_reloc_status_type ret;
  270.  
  271.   DPRINT(5,("Entering add_value\n"));
  272.  
  273.   ret=bfd_reloc_ok;
  274.   p=((signed char*)data)+offset;
  275.  
  276.   switch (size)
  277.     {
  278.     case 0: /* byte size */
  279.       val=(int)(p[0]);
  280.       val+=add;
  281.       if ((val&0xffffff00)!=0 && (val&0xffffff00)!=0xffffff00) /* Overflow */
  282.     {
  283.       ret=bfd_reloc_overflow;
  284.     }
  285.       p[0]=val&0xff;
  286.       break;
  287.  
  288.     case 1: /* word size */
  289.       val=(int)(p[1]|(p[0]<<8));
  290.       val+=add;
  291.       if ((val&0xffff0000)!=0 && (val&0xffff0000)!=0xffff0000) /* Overflow */
  292.     {
  293.       ret=bfd_reloc_overflow;
  294.     }
  295.       p[1]=val&0xff;
  296.       p[0]=((val&0xff00)>>8)&0xff;
  297.       break;
  298.  
  299.     case 2: /* long word */
  300.       val=p[3]|((int)(p[2]<<8))|((int)(p[1]<<16))|((int)(p[0]<<24));
  301.       val=+add;
  302.       p[3]=val&0xff;
  303.       p[2]=((val&0xff00)>>8)&0xff;
  304.       p[1]=((val&0xff0000)>>16)&0xff;
  305.       p[0]=((val&0xff000000)>>24)&0xff;
  306.       break;
  307.       
  308.     default: /* Error */
  309.       ret=bfd_reloc_notsupported;
  310.       break;
  311.     }/* Of switch */
  312.  
  313.   DPRINT(5,("Leaving add_value\n"));
  314.   return (ret);
  315. }
  316.  
  317.  
  318. /* Get the value of ___a4_init */
  319. static asymbol *
  320. mygeta4(bfd *abfd)
  321. {
  322.   asymbol *s;
  323.   int i;
  324.  
  325.   for (i=0;i<abfd->symcount;i++)
  326.     {
  327.       s=abfd->outsymbols[i];
  328.       if (strcmp(s->name,"___a4_init")==0)
  329.     return s;
  330.     }
  331.  
  332.   return (NULL); /* Not found */
  333. }
  334.  
  335. /* Perform an Amiga relocation */
  336. static bfd_reloc_status_type 
  337. amiga_perform_reloc(bfd *abfd, arelent *r, PTR data, asection *sec, bfd *obfd, char **error_message)
  338. {
  339.   asymbol *sym; /* Reloc is relative to sym */
  340.   asymbol *a4init; /* This symbol is used with baserelative relocs */
  341.   asection *target_section; /* reloc is relative to this section */
  342.   int relocation;
  343.   boolean copy;
  344.   bfd_reloc_status_type ret;
  345.   int size;
  346.  
  347.   DPRINT(5,("Entering APR\nflavour is %d (aflavour=%d, aout_flavour=%d)\n",sec->owner->xvec->flavour,
  348.       bfd_target_amiga_flavour, bfd_target_aout_flavour));
  349.  
  350.   /* If obfd==NULL: Apply the reloc, if possible. */
  351.   /* Else: Modify it and return */
  352.  
  353.   if (obfd!=NULL) /* Only modify the reloc */
  354.     {
  355.       r->address+=sec->output_offset;
  356.       sec->output_section->flags|=SEC_RELOC;
  357.       DPRINT(5,("Leaving APR, modified case \n"));
  358.       return bfd_reloc_ok;
  359.     }
  360.  
  361.   /* Try to apply the reloc */
  362.  
  363.   sym=*(r->sym_ptr_ptr);
  364.   target_section=sym->section;
  365.  
  366.   if (target_section==bfd_und_section_ptr) /* Error */
  367.     {
  368.       DPRINT(10,("perform_reloc: Target is undefined section\n"));
  369.       return bfd_reloc_undefined;
  370.     }
  371.   
  372.   relocation=0; copy=false; ret=bfd_reloc_ok;
  373.  
  374.   switch(r->howto->type)
  375.     {
  376.     case HUNK_RELOC32: /* 32 bit reloc */
  377.       DPRINT(5,("RELOC32\n"));
  378.       size=2;
  379.       if (target_section==bfd_abs_section_ptr) /* Ref to absolute hunk */
  380.     relocation=sym->value;
  381.       else if (target_section==bfd_com_section_ptr) /* ref to common */
  382.     {
  383.       relocation=0;
  384.       copy=true;
  385.     }
  386.       else
  387.     {
  388.       /* If we access a symbol in the .bss section, we have to convert this to an access to .data section*/
  389.       /* This is done through a change to the symbol... */
  390.       if (amiga_base_relative && (strcmp(sym->section->output_section->name,".bss")==0))
  391.         {
  392.           /* get value for .data section */
  393.           bfd *ibfd;
  394.           asection *s;
  395.  
  396.           ibfd=target_section->output_section->owner;
  397.           for (s=ibfd->sections;s!=NULL;s=s->next)
  398.         if (strcmp(s->name,".data")==0)
  399.           {
  400.             sym->section->output_offset=s->_raw_size;
  401.             sym->section->output_section=s;
  402.           }
  403.         }
  404.  
  405.       relocation=0;
  406.       copy=true;
  407.     }
  408.       break;
  409.  
  410.     case HUNK_RELOC8:
  411.     case HUNK_RELOC16:
  412.       DPRINT(5,("RELOC16/8\n"));
  413.       size=(r->howto->type==HUNK_RELOC8)?0:1;
  414.       if (target_section==bfd_abs_section_ptr) /* Ref to absolute hunk */
  415.     relocation=sym->value;
  416.       if (target_section==bfd_com_section_ptr) /* Error.. */
  417.     {
  418.       relocation=0;
  419.       copy=false;
  420.       ret=bfd_reloc_undefined;
  421.     }
  422.       else
  423.     {
  424.       DPRINT(5,("PC relative\n"));
  425.       /* This is a pc relative hunk... */
  426.       if (sec->output_section!=target_section->output_section) /* Error */
  427.         {
  428.           DPRINT(10,("pc relative, but out of range I\n"));
  429.           relocation=0;
  430.           copy =false;
  431.           ret=bfd_reloc_outofrange;
  432.         }
  433.       else
  434.         { /* Same section */
  435.           relocation=-(r->address+sec->output_offset);
  436.           copy=false;
  437.         }
  438.     }
  439.       break;
  440.       
  441.     case HUNK_DREL32: /* baserel relocs */
  442.     case HUNK_DREL16:
  443.     case HUNK_DREL8:
  444.       DPRINT(5,("HUNK_BASEREL relocs\n"));
  445.       /* Relocs are always relative to the symbol ___a4_init */
  446.       /* Relocs to .bss section are converted to a reloc to .data section, since
  447.      .bss section contains only COMMON sections...... and should be following .data section.. */
  448.  
  449.       size=(r->howto->type==HUNK_DREL32)?2:((r->howto->type==HUNK_DREL16)?1:0);
  450.       
  451.       if (target_section==bfd_abs_section_ptr) /* Hmmmm, this should have been baserel, but we allow
  452.                           this */
  453.     {
  454.       fprintf(stderr,"Warning: Baserel reloc to symbol %s converted to absolut in section %s\n",
  455.           sym->name,sec->name);
  456.       relocation=sym->value;
  457.     }
  458.       else 
  459.     {
  460.       /* Get value for ___a4init */
  461.       if ((a4init=mygeta4(target_section->output_section->owner))==NULL)
  462.         {
  463.           fprintf(stderr,"Base symbol for base relative reloc not defined, section %s, reloc to symbol"
  464.               "%s\n",sec->name,sym->name);
  465.           copy=false;
  466.           ret=bfd_reloc_notsupported;
  467.           break;
  468.         }
  469.  
  470.       /* If target->out is .bss, add the value of the .data section to sym->value and
  471.          set output_section new to .data section.... */
  472.       if (strcmp(target_section->output_section->name,".bss")==0)
  473.         {
  474.           bfd *ibfd;
  475.           asection *s;
  476.  
  477.           ibfd=target_section->output_section->owner;
  478.           for (s=ibfd->sections;s!=NULL;s=s->next)
  479.         if (strcmp(s->name,".data")==0)
  480.           {
  481.             sym->section->output_section=s;
  482.             sym->section->output_offset=s->_raw_size;
  483.           }
  484.         }
  485.  
  486.       relocation=sym->value+sym->section->output_offset-a4init->value+r->addend;
  487.     
  488.       copy=false; 
  489.     }
  490.       break;
  491.       
  492.     default:
  493.       fprintf(stderr,"Error:Not supported reloc type:%d\n",r->howto->type);
  494.       copy=false;
  495.       relocation=0;
  496.       ret=bfd_reloc_notsupported;
  497.       break;
  498.     } /* Of switch */
  499.   
  500.   /* Add in relocation */
  501.   if (relocation!=0)
  502.     ret=my_add_to(data,r->address,2,relocation);
  503.   
  504.   if (copy)/* Copy reloc to output section */
  505.     {
  506.       DPRINT(5,("Copying reloc\n"));
  507.       target_section=sec->output_section;
  508.       r->address+=sec->output_offset;
  509.       target_section->orelocation[target_section->reloc_count++]=r;
  510.       sec->output_section->flags|=SEC_RELOC;
  511.     }
  512.   DPRINT(5,("Leaving a_perform_reloc\n"));
  513.   return ret;
  514. }
  515.  
  516.  
  517. /* Perform an a.out reloc */
  518. static bfd_reloc_status_type 
  519. aout_perform_reloc(bfd *abfd, arelent *r, PTR data, asection *sec, bfd *obfd, char **error_message)
  520. {
  521.   asymbol *sym; /* Reloc is relative to this */
  522.   asymbol *a4init;
  523.   asection *target_section; /* reloc is relative to this section */
  524.   int relocation;
  525.   boolean copy;
  526.   bfd_reloc_status_type ret;
  527.   int size;
  528.  
  529.   /* If obfd==NULL: Apply the reloc, if possible. */
  530.   /* Else: Modify it and return */
  531.   DPRINT(5,("Entering aout_perf_reloc\n"));
  532.  
  533.   if (obfd!=NULL) /* Only modify the reloc */
  534.     {
  535.       r->address+=sec->output_offset;
  536.       DPRINT(5,("Leaving aout_perf_reloc, modified\n"));
  537.       return bfd_reloc_ok;
  538.     }
  539.  
  540.   sym=*(r->sym_ptr_ptr);
  541.   target_section=sym->section;
  542.  
  543.   if (target_section==bfd_und_section_ptr) /* Error */
  544.     {
  545.       DPRINT(10,("target_sec=UND, aout_perf_rel\n"));
  546.       return bfd_reloc_undefined;
  547.     }
  548.  
  549.   relocation=0; copy=false; ret=bfd_reloc_ok;
  550.  
  551.   switch (r->howto->type)
  552.     {
  553.     case 0: /* 8 bit reloc, pc relative or absolut */
  554.     case 1: /* 16 bit reloc */
  555.       DPRINT(10,("16/8 bit relative\n"));
  556.       size=r->howto->type;
  557.       if (target_section==bfd_abs_section_ptr) /* Ref to absolute hunk */
  558.     relocation=sym->value;
  559.       else if (target_section==bfd_com_section_ptr) /* Error.. */
  560.     {
  561.       relocation=0;
  562.       copy=false;
  563.       ret=bfd_reloc_undefined;
  564.       fprintf(stderr,"Pc relative relocation to  common symbol \"%s\" in section %s\n",
  565.           sym->name,sec->name);
  566.       DPRINT(10,("Ref to common symbol...aout_perf_reloc\n"));
  567.     }
  568.       else 
  569.     {
  570.       /* This is a pc relative hunk... or a baserel... */
  571.       if (sec->output_section!=target_section->output_section) /* Error or baserel */
  572.         {
  573.           if (target_section->output_section->flags&SEC_DATA!=0) /* Baserel reloc */
  574.         {
  575.           goto baserel; /* Dirty, but no code doubling.. */
  576.         }/* Of is baserel */
  577.  
  578.           relocation=0;
  579.           copy =false;
  580.           ret=bfd_reloc_outofrange;
  581.           fprintf(stderr,"pc relative relocation out of range in section %s. Relocation was to"
  582.               "symbol %s\n",sec->name,sym->name);
  583.  
  584.           DPRINT(10,("Section%s, target %s: Reloc out of range...not same section, aout_perf\n" 
  585.               "sec->out=%s, target->out=%s, offset=%lx\n",sec->name, target_section->name,
  586.               sec->output_section->name,target_section->output_section->name,r->address));
  587.         }
  588.       else
  589.         { /* Same section */
  590.           relocation=-(r->address+sec->output_offset);
  591.           copy=false;
  592.           DPRINT(5,("Reloc to same section...\n"));
  593.         }
  594.     }
  595.       break;
  596.     case 2: /* 32 bit reloc, abs. or relative */
  597.       DPRINT(10,("32 bit\n"));
  598.       size=2;
  599.       if (target_section==bfd_abs_section_ptr) /* Ref to absolute hunk */
  600.     relocation=sym->value;
  601.       else if (target_section==bfd_com_section_ptr) /* ref to common */
  602.     {
  603.       relocation=0;
  604.       copy=true;
  605.     }
  606.       else
  607.     {
  608.       /* If we access a symbol in the .bss section, we have to convert this to an access to .data section*/
  609.       /* This is done through a change to the output section of the symbol... */
  610.       if (amiga_base_relative && (strcmp(sym->section->output_section->name,".bss")==0))
  611.         {
  612.           /* get value for .data section */
  613.           bfd *ibfd;
  614.           asection *s;
  615.  
  616.           ibfd=target_section->output_section->owner;
  617.           for (s=ibfd->sections;s!=NULL;s=s->next)
  618.         if (strcmp(s->name,".data")==0)
  619.           {
  620.             sym->section->output_section=s;
  621.             sym->section->output_offset=s->_raw_size;
  622.           }
  623.         }
  624.       relocation=0;
  625.       copy=true;
  626.     }
  627.       DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n",
  628.          target_section->output_section->name,
  629.          target_section->output_section,sec->output_section->name,
  630.          sec->output_section,sym->name));
  631.  
  632.       break;
  633.     case 9: /* 16 bit base relative */
  634.     case 10: /* 32 bit base relative */
  635.       DPRINT(10,("32/16 bit baserel\n"));
  636.       /* We use the symbol ___a4_init as base */
  637.  
  638.       size=r->howto->type-8;
  639.       
  640.     baserel: 
  641.       if (target_section==bfd_abs_section_ptr) /* Hmmmm, this should have been baserel, but we allow
  642.                           this */
  643.     {
  644.       fprintf(stderr,"Warning: Baserel reloc to symbol %s converted to absolut in section %s\n",
  645.           sym->name,sec->name);
  646.       relocation=sym->value;
  647.     }
  648.       else if (target_section==bfd_com_section_ptr) /* Error.. */
  649.     {
  650.       relocation=0;
  651.       copy=false;
  652.       ret=bfd_reloc_undefined;
  653.       fprintf(stderr,"Baserelative relocation to common \"%s\"\n", sym->name);
  654.  
  655.       DPRINT(10,("Ref to common symbol...aout_perf_reloc\n"));
  656.     }
  657.       else /* Target section and sec need not be the same... */
  658.     {
  659.       /* Get value for ___a4init */
  660.       if ((a4init=mygeta4(target_section->output_section->owner))==NULL)
  661.         {
  662.           fprintf(stderr,"Base symbol for base relative reloc not defined, section %s, reloc to symbol"
  663.               "%s\n",sec->name,sym->name);
  664.           copy=false;
  665.           ret=bfd_reloc_notsupported;
  666.           DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n",
  667.              target_section->output_section->name,
  668.              target_section->output_section,sec->output_section->name,
  669.              sec->output_section,sym->name));
  670.           
  671.           break;
  672.         }
  673.       
  674.       /* If target->out is .bss, add the value of the .data section....to sym, set new output_section */
  675.       if (strcmp(target_section->output_section->name,".bss")==0)
  676.         {
  677.           bfd *ibfd;
  678.           asection *s;
  679.  
  680.           ibfd=target_section->output_section->owner;
  681.           for (s=ibfd->sections;s!=NULL;s=s->next)
  682.         if (strcmp(s->name,".data")==0)
  683.           {
  684.             sym->section->output_offset=s->_raw_size;
  685.             sym->section->output_section=s;
  686.           }
  687.         }
  688.  
  689.       relocation=sym->value+sym->section->output_offset-a4init->value+r->addend;
  690.       copy=false; /* Nothing to do, since write_section_contents adds output_offset.. */
  691.     }
  692.       DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n",
  693.          target_section->output_section->name,
  694.          target_section->output_section,sec->output_section->name,
  695.          sec->output_section,sym->name));
  696.       break;
  697.       
  698.     default:
  699.       copy=false;
  700.       relocation=0;
  701.       ret=bfd_reloc_notsupported;
  702.       DPRINT(10,("Unsupported reloc:%d\n",r->howto->type));
  703.       break;
  704.  
  705.     }/* Of switch */
  706.  
  707.   /* Add in relocation */
  708.   if (relocation!=0)
  709.     ret=my_add_to(data,r->address,2,relocation);
  710.   
  711.   if (copy)/* Copy reloc to output section */
  712.     {
  713.       DPRINT(5,("Copying reloc\n"));
  714.       target_section=sec->output_section;
  715.       r->address+=sec->output_offset;
  716.       target_section->orelocation[target_section->reloc_count++]=r;
  717.     }
  718.   DPRINT(5,("Leaving aout_perf_reloc with %d (OK=%d)\n",ret,bfd_reloc_ok));
  719.   return ret;
  720. }
  721.  
  722.  
  723. /* The final link routine, used both by Amiga and a.out backend*/
  724. /* This is nearly a copy of _bfd_generic_final_link */
  725. boolean
  726. amiga_final_link (abfd, info)
  727.      bfd *abfd;
  728.      struct bfd_link_info *info;
  729. {
  730.   bfd *sub;
  731.   asection *o,*act_sec;
  732.   struct bfd_link_order *p;
  733.   size_t outsymalloc;
  734.   struct generic_write_global_symbol_info wginfo;
  735.  
  736.   DPRINT(5,("Entering final_link\n"));
  737.  
  738.   abfd->outsymbols = (asymbol **) NULL;
  739.   abfd->symcount = 0;
  740.   outsymalloc = 0;
  741.  
  742.   /* Build the output symbol table.  */
  743.   for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
  744.     if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
  745.       return false;
  746.  
  747.   DPRINT(10,("Did build output symbol table\n"));
  748.  
  749.   /* Accumulate the global symbols.  */
  750.   wginfo.info = info;
  751.   wginfo.output_bfd = abfd;
  752.   wginfo.psymalloc = &outsymalloc;
  753.   _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info),
  754.                                    _bfd_generic_link_write_global_symbol,
  755.                                    (PTR) &wginfo);
  756.  
  757.   DPRINT(10,("Accumulated global symbols\n"));
  758.  
  759.   DPRINT(10,("Output bfd is %s(%lx)\n",abfd->filename,abfd));
  760.  
  761.   /* Allocate space for the output relocs for each section.  */
  762.   /* We also handle base-relative linking special, by setting the .data sections real length to
  763.      it's length + .bss length */
  764.   /* This is different to bfd_generic_final_link: We ALWAYS alloc space for the relocs,
  765.      because we may need it anyway */
  766.   for (o = abfd->sections;
  767.        o != (asection *) NULL;
  768.        o = o->next)
  769.     {
  770.       /* If section is .data, find .bss and add that length */
  771.       if (!info->relocateable && amiga_base_relative && (strcmp(o->name,".data")==0))
  772.     {
  773.       if (abfd->xvec->flavour!=bfd_target_amiga_flavour) /* oops */
  774.         {
  775.           fprintf(stderr,"You can't use base relative linking with partial links.\n");
  776.         }
  777.       else
  778.         {
  779.           for (act_sec=abfd->sections; act_sec!=NULL;act_sec=act_sec->next)
  780.         if (strcmp(act_sec->name,".bss")==0)
  781.           amiga_per_section(o)->real_length=o->_raw_size+act_sec->_raw_size;
  782.         }
  783.     }/* Of base-relative linking */
  784.  
  785.       DPRINT(10,("Section in output bfd is %s (%lx)\n",o->name,o));
  786.  
  787.       o->reloc_count = 0;
  788.       for (p = o->link_order_head;
  789.        p != (struct bfd_link_order *) NULL;
  790.        p = p->next)
  791.     {
  792.       if (p->type == bfd_section_reloc_link_order
  793.           || p->type == bfd_symbol_reloc_link_order)
  794.         ++o->reloc_count;
  795.       else if (p->type == bfd_indirect_link_order)
  796.         {
  797.           asection *input_section;
  798.           bfd *input_bfd;
  799.           long relsize;
  800.           arelent **relocs;
  801.           asymbol **symbols;
  802.           long reloc_count;
  803.           
  804.           input_section = p->u.indirect.section;
  805.           input_bfd = input_section->owner;
  806.  
  807.           DPRINT(10,("\tIndirect section from bfd %s, section is %s(%lx) (COM=%lx)\n",
  808.              input_bfd->filename,input_section->name,input_section,
  809.              bfd_com_section_ptr));
  810.  
  811.           relsize = bfd_get_reloc_upper_bound (input_bfd,
  812.                            input_section);
  813.           if (relsize < 0)
  814.         {
  815.           DPRINT(10,("Relsize<0.I..in bfd %s, sec %s\n",input_bfd->filename,
  816.                  input_section->name));
  817.           return false;
  818.         }
  819.  
  820.           relocs = (arelent **) malloc ((size_t) relsize);
  821.           if (!relocs && relsize != 0)
  822.         {
  823.           bfd_set_error (bfd_error_no_memory);
  824.           return false;
  825.         }
  826.           symbols = _bfd_generic_link_get_symbols (input_bfd);
  827.           reloc_count = bfd_canonicalize_reloc (input_bfd,
  828.                             input_section,
  829.                             relocs,
  830.                             symbols);
  831.           if (reloc_count < 0)
  832.         {
  833.           DPRINT(10,("Relsize<0.II..in bfd %s, sec %s\n",input_bfd->filename,
  834.                  input_section->name));
  835.           return false;
  836.         }
  837.  
  838.           BFD_ASSERT (reloc_count == input_section->reloc_count);
  839.           o->reloc_count += reloc_count;
  840.           free (relocs);
  841.         }
  842.     }
  843.       if (o->reloc_count > 0)
  844.     {
  845.       o->orelocation = ((arelent **)
  846.                 bfd_alloc (abfd,
  847.                        (o->reloc_count
  848.                     * sizeof (arelent *))));
  849.       if (!o->orelocation)
  850.         {
  851.           bfd_set_error (bfd_error_no_memory);
  852.           return false;
  853.         }
  854.       /* o->flags |= SEC_RELOC; There may be no relocs. This can be determined only later */
  855.       /* Reset the count so that it can be used as an index
  856.          when putting in the output relocs.  */
  857.       o->reloc_count = 0;
  858.     }
  859.     }
  860.         
  861.   DPRINT(10,("Got all relocs\n"));
  862.  
  863.   /* Handle all the link order information for the sections.  */
  864.   for (o = abfd->sections;
  865.        o != (asection *) NULL;
  866.        o = o->next)
  867.     {
  868.       for (p = o->link_order_head;
  869.            p != (struct bfd_link_order *) NULL;
  870.            p = p->next)
  871.         {
  872.           switch (p->type)
  873.             {
  874.             case bfd_section_reloc_link_order:
  875.             case bfd_symbol_reloc_link_order:
  876.               if (! amiga_reloc_link_order (abfd, info, o, p)) /* We use an own routine */
  877.                 return false;
  878.               break;
  879.             case bfd_indirect_link_order:
  880.               if (! default_indirect_link_order (abfd, info, o, p, true)) 
  881.         /* Calls our get_relocated_section_contents*/
  882.                 return false;
  883.               break;
  884.             default:
  885.               if (! _bfd_default_link_order (abfd, info, o, p))
  886.                 return false;
  887.               break;
  888.             }
  889.         }
  890.     }
  891.   if (abfd->xvec->flavour==bfd_target_amiga_flavour&&!info->relocateable)
  892.     AMIGA_DATA(abfd)->IsLoadFile=true;
  893.  
  894.   DPRINT(10,("Leaving final_link\n"));
  895.   return true;
  896. }
  897.  
  898.  
  899. /* Handle reloc link order . This is nearly a copy from gneric_reloc_link_order in linker.c*/
  900. static boolean 
  901. amiga_reloc_link_order(bfd *abfd,struct bfd_link_info *info  , asection *sec, struct bfd_link_order *link_order)
  902. {
  903.    amiga_reloc_type *r;
  904.  
  905.    DPRINT(5,("Entering amiga_reloc_link_order\n"));
  906.    /* We generate a new AMIGA style reloc */
  907.    BFD_ASSERT(sec->orelocation!=NULL);
  908.  
  909.    if (sec->orelocation == (arelent **) NULL)
  910.      {
  911.        DPRINT(10,("aborting, since orelocation==NULL\n"));
  912.        abort ();
  913.      }
  914.  
  915.    r = (amiga_reloc_type *) bfd_zalloc (abfd, sizeof (amiga_reloc_type));
  916.    if (r ==  NULL)
  917.      {
  918.        bfd_set_error (bfd_error_no_memory);
  919.        DPRINT(5,("Leaving amiga_reloc_link, no mem\n"));
  920.        return false;
  921.      }
  922.    
  923.    r->relent.address = link_order->offset;
  924.    r->relent.howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
  925.    if (r->relent.howto ==  NULL)
  926.      {
  927.        bfd_set_error (bfd_error_bad_value);
  928.        DPRINT(5,("Leaving amiga_reloc_link, bad value\n"));
  929.        return false;
  930.      }
  931.    
  932.    /* Get the symbol to use for the relocation.  */
  933.    if (link_order->type == bfd_section_reloc_link_order)
  934.      r->relent.sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr;
  935.    else
  936.      {
  937.        struct generic_link_hash_entry *h;
  938.        
  939.        h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
  940.                       link_order->u.reloc.p->u.name,
  941.                       false, false, true);
  942.        if (h == (struct generic_link_hash_entry *) NULL
  943.        || ! h->written)
  944.      {
  945.        if (! ((*info->callbacks->unattached_reloc)
  946.           (info, link_order->u.reloc.p->u.name,
  947.            (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
  948.          return false;
  949.        bfd_set_error (bfd_error_bad_value);
  950.        DPRINT(5,("Leaving amiga_reloc_link, bad value in hash lookup\n"));
  951.        return false;
  952.      }
  953.        r->relent.sym_ptr_ptr = &h->sym;
  954.      }
  955.    DPRINT(5,("Got symbol for relocation\n"));
  956.    /* Store the addend */
  957.    r->relent.addend = link_order->u.reloc.p->addend;
  958.  
  959.  
  960.    /* If we are generating relocateable output, just add the reloc */
  961.    if (info->relocateable)
  962.      {
  963.        DPRINT(5,("Adding reloc\n"));
  964.        sec->orelocation[sec->reloc_count] = (arelent *)r;
  965.        ++sec->reloc_count; 
  966.        sec->flags|=SEC_RELOC;
  967.      }
  968.    else
  969.      { /* Try to apply the reloc */
  970.        char *em="";
  971.        PTR data;
  972.        bfd_reloc_status_type ret;
  973.  
  974.        DPRINT(5,("Apply link_order_reloc\n"));
  975.        /*FIXME: Maybe, we have to get the section contents, before we use them, if they have not been
  976.      set by now.. */
  977.  
  978.        BFD_ASSERT(sec->contents!=NULL);
  979.        data=(PTR)(sec->contents);
  980.  
  981.        if (bfd_get_flavour(abfd)==bfd_target_amiga_flavour)
  982.      ret=amiga_perform_reloc(abfd,(arelent *)r,data,sec,NULL,&em);
  983.        else
  984.      ret=aout_perform_reloc(abfd,(arelent *)r,data,sec,NULL,&em);
  985.  
  986.        if (ret!=bfd_reloc_ok)
  987.      {
  988.        DPRINT(5,("Leaving amiga_reloc_link, value false\n"));
  989.        return false;
  990.      }
  991.      }
  992.    DPRINT(5,("Leaving amiga_reloc_link\n"));
  993.    return true;
  994. }
  995.