summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-devel/binutils/files/binutils-2.22-mint.patch')
-rw-r--r--sys-devel/binutils/files/binutils-2.22-mint.patch2656
1 files changed, 2656 insertions, 0 deletions
diff --git a/sys-devel/binutils/files/binutils-2.22-mint.patch b/sys-devel/binutils/files/binutils-2.22-mint.patch
new file mode 100644
index 0000000..4c2442e
--- /dev/null
+++ b/sys-devel/binutils/files/binutils-2.22-mint.patch
@@ -0,0 +1,2656 @@
+http://bugs.gentoo.org/show_bug.cgi?id=362559
+
+diff -ur --new-file binutils-2.21.51.0.7/bfd/Makefile.am binutils-2.21.51.0.7-mint/bfd/Makefile.am
+--- binutils-2.21.51.0.7/bfd/Makefile.am 2010-12-06 14:23:53.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/Makefile.am 2011-04-08 10:07:06.000000000 +0000
+@@ -379,6 +379,7 @@
+ peigen.lo \
+ plugin.lo \
+ ppcboot.lo \
++ prg-mint.lo \
+ reloc16.lo \
+ riscix.lo \
+ som.lo \
+@@ -559,6 +560,7 @@
+ pei-sh.c \
+ plugin.c \
+ ppcboot.c \
++ prg-mint.c \
+ reloc16.c \
+ riscix.c \
+ som.c \
+diff -ur --new-file binutils-2.21.51.0.7/bfd/Makefile.in binutils-2.21.51.0.7-mint/bfd/Makefile.in
+--- binutils-2.21.51.0.7/bfd/Makefile.in 2010-12-06 14:23:53.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/Makefile.in 2011-04-08 10:07:06.000000000 +0000
+@@ -679,6 +679,7 @@
+ peigen.lo \
+ plugin.lo \
+ ppcboot.lo \
++ prg-mint.lo \
+ reloc16.lo \
+ riscix.lo \
+ som.lo \
+@@ -859,6 +860,7 @@
+ pei-sh.c \
+ plugin.c \
+ ppcboot.c \
++ prg-mint.c \
+ reloc16.c \
+ riscix.c \
+ som.c \
+diff -ur --new-file binutils-2.21.51.0.7/bfd/acinclude.m4 binutils-2.21.51.0.7-mint/bfd/acinclude.m4
+--- binutils-2.21.51.0.7/bfd/acinclude.m4 2009-12-14 15:46:47.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/acinclude.m4 2011-04-08 10:07:06.000000000 +0000
+@@ -5,7 +5,7 @@
+ [AC_REQUIRE([AC_CANONICAL_TARGET])
+ case "${host}" in
+ changequote(,)dnl
+-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*)
+ changequote([,])dnl
+ AC_DEFINE(USE_BINARY_FOPEN, 1, [Use b modifier when opening binary files?]) ;;
+ esac])dnl
+diff -ur --new-file binutils-2.21.51.0.7/bfd/aoutx.h binutils-2.21.51.0.7-mint/bfd/aoutx.h
+--- binutils-2.21.51.0.7/bfd/aoutx.h 2011-03-07 18:05:31.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/aoutx.h 2011-04-08 10:07:06.000000000 +0000
+@@ -1841,6 +1841,11 @@
+ bfd_byte buffer[BYTES_IN_WORD];
+ bfd_size_type amt = BYTES_IN_WORD;
+
++ /* The MiNT backend writes past the string table. It therefore has to
++ know about the table size. */
++ obj_aout_external_string_size (abfd) = _bfd_stringtab_size (tab) +
++ BYTES_IN_WORD;
++
+ /* The string table starts with the size. */
+ PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
+ if (bfd_bwrite ((void *) buffer, amt, abfd) != amt)
+@@ -4220,10 +4225,17 @@
+ return FALSE;
+ }
+
++#ifdef MY_final_link_relocate_rel
++ r = MY_final_link_relocate_rel (howto,
++ input_bfd, input_section,
++ contents, r_addr, relocation,
++ (bfd_vma) 0, rel);
++#else
+ r = MY_final_link_relocate (howto,
+ input_bfd, input_section,
+ contents, r_addr, relocation,
+ (bfd_vma) 0);
++#endif
+ }
+
+ if (r != bfd_reloc_ok)
+diff -ur --new-file binutils-2.21.51.0.7/bfd/bfd-in.h binutils-2.21.51.0.7-mint/bfd/bfd-in.h
+--- binutils-2.21.51.0.7/bfd/bfd-in.h 2010-11-12 17:32:58.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/bfd-in.h 2011-04-08 10:07:06.000000000 +0000
+@@ -742,6 +742,15 @@
+ extern bfd_boolean bfd_sparclinux_size_dynamic_sections
+ (bfd *, struct bfd_link_info *);
+
++/* MiNT executable support routines for the linker. */
++
++extern bfd_boolean bfd_m68kmint_set_extended_flags
++ (bfd *, flagword);
++extern bfd_boolean bfd_m68kmint_set_stack_size
++ (bfd *, bfd_signed_vma);
++extern bfd_boolean bfd_m68kmint_add_tpa_relocation_entry
++ (bfd *, bfd_vma);
++
+ /* mmap hacks */
+
+ struct _bfd_window_internal;
+diff -ur --new-file binutils-2.21.51.0.7/bfd/bfd-in2.h binutils-2.21.51.0.7-mint/bfd/bfd-in2.h
+--- binutils-2.21.51.0.7/bfd/bfd-in2.h 2011-03-07 18:05:57.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/bfd-in2.h 2011-04-08 10:07:06.000000000 +0000
+@@ -749,6 +749,15 @@
+ extern bfd_boolean bfd_sparclinux_size_dynamic_sections
+ (bfd *, struct bfd_link_info *);
+
++/* MiNT executable support routines for the linker. */
++
++extern bfd_boolean bfd_m68kmint_set_extended_flags
++ (bfd *, flagword);
++extern bfd_boolean bfd_m68kmint_set_stack_size
++ (bfd *, bfd_signed_vma);
++extern bfd_boolean bfd_m68kmint_add_tpa_relocation_entry
++ (bfd *, bfd_vma);
++
+ /* mmap hacks */
+
+ struct _bfd_window_internal;
+diff -ur --new-file binutils-2.21.51.0.7/bfd/config.bfd binutils-2.21.51.0.7-mint/bfd/config.bfd
+--- binutils-2.21.51.0.7/bfd/config.bfd 2011-01-04 17:51:04.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/config.bfd 2011-04-08 10:07:06.000000000 +0000
+@@ -823,6 +823,11 @@
+ # targ_selvecs=m68kmach3_vec
+ # targ_cflags=-DSTAT_FOR_EXEC
+ ;;
++ m68*-*-mint*)
++ targ_defvec=aout0_big_vec
++ targ_selvecs=m68kmint_prg_vec
++ targ_underscore=yes
++ ;;
+ m68*-hp*-netbsd*)
+ targ_defvec=m68k4knetbsd_vec
+ targ_selvecs="m68knetbsd_vec hp300bsd_vec sunos_big_vec"
+diff -ur --new-file binutils-2.21.51.0.7/bfd/configure binutils-2.21.51.0.7-mint/bfd/configure
+--- binutils-2.21.51.0.7/bfd/configure 2011-03-07 18:05:31.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/configure 2011-04-08 10:07:07.000000000 +0000
+@@ -13623,7 +13623,7 @@
+
+
+ case "${host}" in
+-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*)
+
+ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
+ ;;
+@@ -15237,6 +15237,7 @@
+ m68kcoff_vec) tb="$tb coff-m68k.lo cofflink.lo" ;;
+ m68kcoffun_vec) tb="$tb coff-u68k.lo coff-m68k.lo cofflink.lo" ;;
+ m68klinux_vec) tb="$tb m68klinux.lo aout32.lo" ;;
++ m68kmint_prg_vec) tb="$tb prg-mint.lo aout32.lo" ;;
+ m68knetbsd_vec) tb="$tb m68knetbsd.lo aout32.lo" ;;
+ m68ksysvcoff_vec) tb="$tb coff-svm68k.lo cofflink.lo" ;;
+ m88kbcs_vec) tb="$tb coff-m88k.lo" ;;
+diff -ur --new-file binutils-2.21.51.0.7/bfd/configure.in binutils-2.21.51.0.7-mint/bfd/configure.in
+--- binutils-2.21.51.0.7/bfd/configure.in 2011-03-07 18:05:31.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/configure.in 2011-04-08 10:07:07.000000000 +0000
+@@ -880,6 +880,7 @@
+ m68kcoff_vec) tb="$tb coff-m68k.lo cofflink.lo" ;;
+ m68kcoffun_vec) tb="$tb coff-u68k.lo coff-m68k.lo cofflink.lo" ;;
+ m68klinux_vec) tb="$tb m68klinux.lo aout32.lo" ;;
++ m68kmint_prg_vec) tb="$tb prg-mint.lo aout32.lo" ;;
+ m68knetbsd_vec) tb="$tb m68knetbsd.lo aout32.lo" ;;
+ m68ksysvcoff_vec) tb="$tb coff-svm68k.lo cofflink.lo" ;;
+ m88kbcs_vec) tb="$tb coff-m88k.lo" ;;
+diff -ur --new-file binutils-2.21.51.0.7/bfd/libaout.h binutils-2.21.51.0.7-mint/bfd/libaout.h
+--- binutils-2.21.51.0.7/bfd/libaout.h 2009-10-09 22:25:42.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/libaout.h 2011-04-08 10:07:08.000000000 +0000
+@@ -422,6 +422,10 @@
+ table, used when linking on SunOS. This is indexed by the symbol
+ index. */
+ bfd_vma *local_got_offsets;
++
++ /* A pointer for data used by aout extensions. (Currently only used
++ by MiNT executables (see prg-mint.c). */
++ void *ext;
+ };
+
+ struct aout_data_struct
+@@ -449,6 +453,7 @@
+ #define obj_aout_string_window(bfd) (adata (bfd).string_window)
+ #define obj_aout_sym_hashes(bfd) (adata (bfd).sym_hashes)
+ #define obj_aout_dynamic_info(bfd) (adata (bfd).dynamic_info)
++#define obj_aout_ext(bfd) (adata (bfd).ext)
+
+ /* We take the address of the first element of an asymbol to ensure that the
+ macro is only ever applied to an asymbol. */
+diff -ur --new-file binutils-2.21.51.0.7/bfd/prg-mint.c binutils-2.21.51.0.7-mint/bfd/prg-mint.c
+--- binutils-2.21.51.0.7/bfd/prg-mint.c 1970-01-01 00:00:00.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/prg-mint.c 2011-04-08 10:07:08.000000000 +0000
+@@ -0,0 +1,1732 @@
++/* BFD backend for traditional MiNT executables.
++ Copyright 1998, 2007, 2008, 2009 Free Software Foundation, Inc.
++ Originally written by Guido Flohr (guido@freemint.de).
++ Modified by Vincent Riviere (vincent.riviere@freesbee.fr).
++
++ This file is part of BFD, the Binary File Descriptor library.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
++ MA 02110-1301, USA. */
++
++/* The format of executables on Atari is actually not a.out, it is
++ only chosen as an approach which comes close enough. The layout of a
++ program image on disk looked like this:
++
++ +-----------------+
++ | 28 Bytes Header |
++ +-----------------+
++ | Text segment |
++ +-----------------+
++ | Data segment |
++ +-----------------+
++ | BSS |
++ +-----------------+
++ | Symbol table |
++ +-----------------+
++ | TPA relocation |
++ +-----------------+
++
++ The 28 byte exec header used to look like this:
++
++ struct old_exec_header
++ {
++ bfd_byte a_magic[2];
++ bfd_byte a_text[4];
++ bfd_byte a_data[4];
++ bfd_byte a_bss[4];
++ bfd_byte a_syms[4];
++ bfd_byte a_resvd[4];
++ bfd_byte a_abs[2];
++ };
++
++ The first two bytes (A_MAGIC) contained an assembler branch
++ instruction to the beginning of the text segment. Because the
++ exec header had a fixed size and the text entry point was constant
++ this assembler instruction also had a constant value (0x601a).
++ In fact the operating system never really executed the branch
++ instruction but used this value (0x601a) as a magic value.
++
++ TEXT, DATA and BSS were as one would expect them. The symbol
++ table wasn't. Several different formats were in use, none of them
++ very efficient, none of them powerful enough to support source
++ level debugging. I've changed that and the GNU symbol table will
++ now be used instead (unless the --traditional-format option was
++ given to the linker).
++
++ If the last member A_ABS of the exec header is zero the program
++ image contains an additional table with relocation information
++ at the end of the image. The kernel can load program images at
++ virtually any address in the address space. In fact it will load
++ it at the start of the biggest block of free memory. This block
++ is then called the Transient Program Area TPA and the image has
++ to be relocated against the TPA at runtime. The relocation info
++ itself is in a simply way compressed: It starts with a four-byte
++ value, the first address within the image to be relocated. Now
++ following are one-byte offsets to the last address. The special
++ value of 1 (which is impossible as an offset) signifies that 254
++ has to be added to the next offset. The table is finished with
++ a zero-byte.
++
++ I now simply extended the header from its old 28 bytes to 256
++ bytes. The first 28 bytes give home to a standard Atari header,
++ the rest is for extensions. The extension header starts with
++ a ``real'' assembler instruction, a far jump to the text entry
++ point. The extension header gives home to a standard a.out
++ exec header (currently NMAGIC) plus some extra
++ more or less useful fields plus space to future extensions.
++ For the OS the extension header will already belong to the text
++ segment, for BFD backends the text segment is 228 (or 0xe4)
++ bytes smaller than for the OS. This explains for example the
++ funny TEXT_START_ADDR 0xe4.
++
++ The TARGET_PAGE_SIZE is 2 which is only fake. There is currently
++ no such thing as memory paging on the Atari (and this is why
++ ZMAGICs are disabled for now to allow for future enhancements).
++
++ If you think that this whole file looks quite like a big hack
++ you're probably right. But the results (mainly the output of
++ the linker) seem to work and they allow to use up-to-date
++ binutils on the Atari until a better executable format (maybe
++ ELF) has been established for this machine. */
++
++#include "sysdep.h"
++#include "bfd.h"
++
++#define N_HEADER_IN_TEXT(x) 0
++#define BYTES_IN_WORD 4
++#define ENTRY_CAN_BE_ZERO
++#define N_SHARED_LIB(x) 0
++#define TEXT_START_ADDR 0xe4
++#define TARGET_PAGE_SIZE 2
++#define TARGET_IS_BIG_ENDIAN_P
++#define DEFAULT_ARCH bfd_arch_m68k
++#define N_TXTADDR(x) TEXT_START_ADDR
++
++/* Do not "beautify" the CONCAT* macro args. Traditional C will not
++ remove whitespace added here, and thus will fail to concatenate
++ the tokens. */
++#define MY(OP) CONCAT2 (m68kmint_prg_,OP)
++#define TARGETNAME "a.out-mintprg"
++#define NAME(x,y) CONCAT3 (mintprg,_32_,y)
++
++/* We have to do quite a lot of magic to make the Atari format
++ for GEMDOS executables fit into the standard a.out format.
++ We start with the original header. */
++#define external_exec mint_external_exec
++struct mint_external_exec
++{
++ bfd_byte g_branch[2]; /* 0x601a. */
++ bfd_byte g_text[4]; /* Length of text section. */
++ bfd_byte g_data[4]; /* Length of data section. */
++ bfd_byte g_bss[4]; /* Length of bss section. */
++ bfd_byte g_syms[4]; /* Length of symbol table. */
++ bfd_byte g_extmagic[4]; /* Always 0x4d694e54
++ (in ASCII: ``MiNT''). */
++ bfd_byte g_flags[4]; /* Atari special flags. */
++ bfd_byte g_abs[2]; /* Non-zero if absolute (no relocation
++ info. */
++
++ /* We extend this header now to provide the information that the
++ binutils want to see. Everything following will actually be part
++ of the text segment (from MiNT's point of view). As a
++ consequence the text section has 228 bytes of redundancy.
++
++ The following eight bytes should be treated as opaque.
++ If the word ``opaque'' always attracts your curiosity in
++ typedefs and structs, here's the explanation: These eight bytes
++ are really two assembler instructions. The first one moves
++ the contents of e_entry into register d0, the second one
++ jumps (pc-relative) to the entry point. See swap_exec_header_out
++ for details. */
++ bfd_byte g_jump_entry[8];
++
++ /* Now following a standard a.out header. Note that the values
++ may differ from the one given on top. The traditional header
++ contains the values that the OS wants to see, the values below
++ are the values that make the binutils work. */
++ bfd_byte e_info[4]; /* Magic number and stuff. */
++ bfd_byte e_text[4]; /* Length of text section in bytes. */
++ bfd_byte e_data[4]; /* Length of data section. */
++ bfd_byte e_bss[4]; /* Length of standard symbol
++ table. */
++ bfd_byte e_syms[4]; /* Length of symbol table. */
++ bfd_byte e_entry[4]; /* Start address. */
++ bfd_byte e_trsize[4]; /* Length of text relocation
++ info. */
++ bfd_byte e_drsize[4]; /* Length of data relocation
++ info. */
++
++ bfd_byte g_tparel_pos[4]; /* File position of TPA relative
++ relocation info. */
++ bfd_byte g_tparel_size[4]; /* Length of TPA relative relocation
++ info. */
++
++ /* This is for extensions. */
++ bfd_byte g_stkpos[4]; /* If stacksize is hardcoded into
++ the executable you will find it
++ at file offset g_stkpos. If
++ not this is NULL. */
++
++ bfd_byte g_symbol_format[4]; /* Format of the symbol table. See
++ definitions for _MINT_SYMBOL_FORMAT*
++ above. */
++
++ /* Pad with zeros. */
++ bfd_byte g_pad0[172];
++};
++#define EXEC_BYTES_SIZE 256
++#define GEMDOS_HEADER_SIZE 28
++
++/* The following defines are required by aoutx.h.
++ They are not automatically defined in aout/aout64.h
++ if external_exec is defined. */
++
++#define OMAGIC 0407 /* Object file or impure executable. */
++#define NMAGIC 0410 /* Code indicating pure executable. */
++#define ZMAGIC 0413 /* Code indicating demand-paged executable. */
++#define BMAGIC 0415 /* Used by a b.out object. */
++#define QMAGIC 0314 /* Like ZMAGIC but with N_HEADER_IN_TEXT true. */
++
++/* Files using the following magic flags will not be loaded. */
++#define N_BADMAG(x) (N_MAGIC(x) != NMAGIC)
++
++/* For DRI symbol table format. */
++struct dri_symbol
++{
++ bfd_byte a_name[8]; /* Symbol name */
++ bfd_byte a_type[2]; /* Type flag, i.e. A_TEXT etc; see below. */
++ bfd_byte a_value[4]; /* value of this symbol (or sdb offset). */
++};
++#define DRI_SYMBOL_SIZE 14
++
++/* Simple values for a_type. */
++#define A_UNDF 0
++#define A_BSS 0x0100
++#define A_TEXT 0x0200
++#define A_DATA 0x0400
++#define A_EXT 0x0800 /* External. */
++#define A_EQREG 0x1000 /* Equated register. */
++#define A_GLOBL 0x2000 /* Global. */
++#define A_EQU 0x4000 /* Equated. */
++#define A_DEF 0x8000 /* Defined. */
++#define A_LNAM 0x0048 /* GST compatible long name. */
++ /* File symbols ala aln. */
++#define A_TFILE 0x0280 /* Text file corresponding to object module. */
++#define A_TFARC 0x02C0 /* Text file archive. Unfortunately this
++ conflicts with the bits in A_LNAM. */
++
++/* The following include contains the definitions for internal a.out structures
++ as well as the prototypes for the NAME(...) functions defined in aoutx.h. */
++
++#include "libaout.h"
++
++/* The following function is similar to _bfd_final_link_relocate, except it
++ adds the reloc structure as an additional parameter.
++ It will be used int aoutx.h. */
++
++static bfd_reloc_status_type
++m68kmint_prg_final_link_relocate_rel (reloc_howto_type *howto,
++ bfd *input_bfd,
++ asection *input_section,
++ bfd_byte *contents,
++ bfd_vma address,
++ bfd_vma value,
++ bfd_vma addend,
++ struct reloc_std_external *rel);
++
++#define MY_final_link_relocate_rel m68kmint_prg_final_link_relocate_rel
++
++/* The following include contains the definitions for the NAME(...) functions. */
++
++#include "aoutx.h"
++
++/* Data structure that holds some private information for us. */
++struct mint_internal_info
++{
++ struct bfd_link_info *linkinfo; /* Remembered from final_link. */
++ bfd_boolean traditional_format; /* Saved from link info. */
++ int symbol_format; /* Format of the symbol table. */
++ void *tparel; /* Data for TPA relative relocation
++ information. */
++ file_ptr tparel_pos; /* File position of TPA relative
++ relocation information. */
++ bfd_size_type tparel_size; /* Size of TPA relative relocation
++ information. */
++ bfd_size_type dri_symtab_size; /* Size of traditional symbol table. */
++
++#define MINT_RELOC_CHUNKSIZE 0x1000
++ bfd_vma *relocs; /* Array of address relocations. */
++ unsigned long relocs_used; /* Number of relocation entries
++ already used up. */
++ unsigned long relocs_allocated; /* Number of relocation entries
++ allocated. */
++
++ bfd_vma stkpos; /* File offset to value of _stksize. */
++
++ flagword prg_flags; /* Standard GEMDOS flags. */
++
++ bfd_boolean override_stack_size; /* TRUE if the executable stack size
++ must be overriden with stack_size. */
++ bfd_signed_vma stack_size;
++
++ bfd_boolean reloc_error; /* TRUE if an unhandled error during
++ relocation occured. */
++};
++
++/* If --traditional-format was given to the linker an old-style DRI
++ symbol table is written into the executable. This is with respect
++ to many old debugging tools or disassemblers which expect this format.
++ Although created by the linker, these symbols will be ignored from
++ input files. */
++#define _MINT_SYMBOL_FORMAT_GNU 0
++#define _MINT_SYMBOL_FORMAT_DRI 1
++
++/* Declarations for the variables and functions
++ defined later in aout-target.h. */
++
++static const bfd_target *
++m68kmint_prg_callback (bfd *abfd);
++
++static void
++MY_final_link_callback (bfd *abfd,
++ file_ptr *ptreloff,
++ file_ptr *pdreloff,
++ file_ptr *psymoff);
++
++extern const bfd_target m68kmint_prg_vec;
++
++/* Initialize a new BFD using our file format. */
++
++#define MY_mkobject m68kmint_prg_mkobject
++
++static bfd_boolean
++m68kmint_prg_mkobject (bfd *abfd)
++{
++ struct mint_internal_info *myinfo;
++
++ if (!NAME (aout, mkobject (abfd)))
++ return FALSE;
++
++ /* Allocate our private BFD data. */
++ myinfo = bfd_zalloc (abfd, sizeof (*myinfo));
++ if (myinfo == NULL)
++ return FALSE;
++ obj_aout_ext (abfd) = myinfo;
++
++ return TRUE;
++}
++
++/* Finish up the reading of an a.out file header. */
++
++#define MY_object_p m68kmint_prg_object_p
++
++static const bfd_target *
++m68kmint_prg_object_p (bfd *abfd)
++{
++ struct external_exec exec_bytes; /* Raw exec header from file. */
++ struct internal_exec exec; /* Cleaned-up exec header. */
++ const bfd_target *target;
++ bfd_size_type amt = EXEC_BYTES_SIZE;
++ struct mint_internal_info *myinfo;
++
++ /* Read the exec bytesd from the file. */
++ if (bfd_bread (&exec_bytes, amt, abfd) != amt)
++ {
++ if (bfd_get_error () != bfd_error_system_call)
++ bfd_set_error (bfd_error_wrong_format);
++ return NULL;
++ }
++
++ /* Instead of byte-swapping we compare bytes. */
++ if (exec_bytes.g_branch[0] != 0x60
++ || exec_bytes.g_branch[1] != 0x1a
++ || exec_bytes.g_extmagic[0] != 'M'
++ || exec_bytes.g_extmagic[1] != 'i'
++ || exec_bytes.g_extmagic[2] != 'N'
++ || exec_bytes.g_extmagic[3] != 'T')
++ {
++ bfd_set_error (bfd_error_wrong_format);
++ return NULL;
++ }
++
++ /* Swap the standard a.out fields. */
++ NAME (aout, swap_exec_header_in) (abfd, &exec_bytes, &exec);
++
++ /* Check a.out magic value. */
++ if (N_BADMAG (exec))
++ {
++ bfd_set_error (bfd_error_wrong_format);
++ return NULL;
++ }
++
++ /* Initialize this BFD with the exec values. */
++ target = NAME (aout, some_aout_object_p) (abfd, &exec, m68kmint_prg_callback);
++
++ /* Allocate our private BFD data. */
++ myinfo = bfd_zalloc (abfd, sizeof (*myinfo));
++ if (myinfo == NULL)
++ return NULL;
++ obj_aout_ext (abfd) = myinfo;
++
++ /* Now get the missing information. */
++ myinfo->prg_flags = bfd_h_get_32 (abfd, exec_bytes.g_flags);
++ myinfo->stkpos = bfd_h_get_32 (abfd, exec_bytes.g_stkpos);
++ myinfo->symbol_format = bfd_h_get_32 (abfd, exec_bytes.g_symbol_format);
++
++ /* TPA relocation information. */
++ myinfo->tparel_pos = bfd_h_get_32 (abfd, exec_bytes.g_tparel_pos);
++ myinfo->tparel_size = bfd_h_get_32 (abfd, exec_bytes.g_tparel_size);
++
++ /* FIXME: Currently we always read the TPA relative relocation
++ information. This is suboptimal because often times there
++ is no need for it. Read it only if need be! Maybe this should
++ also depend on abfd->cacheable? */
++ if (myinfo->tparel_size == 0)
++ myinfo->tparel = bfd_zalloc (abfd, 4);
++ else
++ myinfo->tparel = bfd_alloc (abfd, myinfo->tparel_size);
++
++ if (myinfo->tparel == NULL)
++ return NULL;
++
++ if (myinfo->tparel_size == 0)
++ {
++ myinfo->tparel_size = 4;
++ }
++ else
++ {
++ /* Read the information from the bfd. */
++ if (bfd_seek (abfd, myinfo->tparel_pos, SEEK_SET) != 0
++ || (bfd_bread (myinfo->tparel, myinfo->tparel_size, abfd)
++ != myinfo->tparel_size))
++ return NULL;
++ }
++
++ return target;
++}
++
++/* Free all information we have cached for this BFD. We can always
++ read it again later if we need it. */
++
++#define MY_bfd_free_cached_info m68kmint_prg_bfd_free_cached_info
++
++static bfd_boolean
++m68kmint_prg_bfd_free_cached_info (bfd *abfd)
++{
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++
++ if (myinfo != NULL && myinfo->relocs != NULL)
++ {
++ free (myinfo->relocs);
++ myinfo->relocs = NULL;
++ }
++
++ /* myinfo itself has been allocated by bfd_zalloc()
++ so will be automatically freed along with the BFD.
++ Same for myinfo->tparel. */
++
++ return NAME (aout, bfd_free_cached_info) (abfd);
++}
++
++/* Write a DRI symbol with TYPE and VALUE. If the NAME of the
++ symbol exceeds 8 characters write a long symbol. If it
++ exceeds 22 characters truncate the name. */
++
++static int
++write_dri_symbol (bfd *abfd, const char *name, int type, bfd_vma value)
++{
++ int written_bytes = 0;
++ struct dri_symbol sym;
++ int is_long_name = strlen (name) > sizeof (sym.a_name);
++
++ if (is_long_name)
++ type |= A_LNAM;
++
++ strncpy ((char*)sym.a_name, name, sizeof (sym.a_name));
++ bfd_put_16 (abfd, type, sym.a_type);
++ bfd_put_32 (abfd, value, sym.a_value);
++
++ if (bfd_bwrite (&sym, DRI_SYMBOL_SIZE, abfd) != DRI_SYMBOL_SIZE)
++ return -1;
++ written_bytes += DRI_SYMBOL_SIZE;
++
++ if (is_long_name)
++ {
++ char more_name[DRI_SYMBOL_SIZE];
++
++ strncpy (more_name, name + sizeof (sym.a_name), DRI_SYMBOL_SIZE);
++
++ if (bfd_bwrite (more_name, DRI_SYMBOL_SIZE, abfd) != DRI_SYMBOL_SIZE)
++ return -1;
++ written_bytes += DRI_SYMBOL_SIZE;
++ }
++
++ return written_bytes;
++}
++
++/* Emit a traditional DRI symbol table while linking.
++ Most of this code comes from aout_link_write_symbols() in aoutx.h. */
++
++static bfd_boolean
++link_write_traditional_syms (bfd *abfd, struct bfd_link_info *info)
++{
++ bfd *input_bfd;
++ enum bfd_link_strip strip = info->strip;
++ enum bfd_link_discard discard = info->discard;
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++ bfd *last_archive = NULL;
++
++ /* Position file pointer. */
++ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
++ return FALSE;
++
++ myinfo->dri_symtab_size = 0;
++
++ for (input_bfd = info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link_next)
++ {
++ bfd_size_type sym_count = obj_aout_external_sym_count (input_bfd);
++ char *strings = obj_aout_external_strings (input_bfd);
++ struct external_nlist *sym = obj_aout_external_syms (input_bfd);
++ struct external_nlist *sym_end = sym + sym_count;
++ struct aout_link_hash_entry **sym_hash = obj_aout_sym_hashes (input_bfd);
++ bfd_boolean pass = FALSE;
++ bfd_boolean skip = FALSE;
++ bfd_boolean skip_next = FALSE;
++ int written_bytes;
++ int a_type;
++ bfd_boolean write_archive_name = FALSE;
++ bfd_vma val = 0;
++
++ /* First write out a symbol for the archive if we do not
++ strip these symbols and if it differs from the last
++ one. */
++ if (input_bfd->my_archive != last_archive
++ && input_bfd->my_archive != NULL)
++ {
++ write_archive_name = TRUE;
++ last_archive = input_bfd->my_archive;
++ }
++
++ if (write_archive_name
++ && strip != strip_all
++ && (strip != strip_some
++ || bfd_hash_lookup (info->keep_hash,
++ input_bfd->my_archive->filename,
++ FALSE, FALSE) != NULL)
++ && discard != discard_all)
++ {
++ val = bfd_get_section_vma (abfd,
++ obj_textsec (input_bfd)->output_section)
++ + obj_textsec (input_bfd)->output_offset;
++
++ written_bytes = write_dri_symbol (abfd,
++ input_bfd->my_archive->filename,
++ A_TFILE, val);
++
++ if (written_bytes < 0)
++ return FALSE;
++ else
++ myinfo->dri_symtab_size += written_bytes;
++ }
++
++ /* Now write out a symbol for the object file if we do not
++ strip these symbols. */
++ if (strip != strip_all
++ && (strip != strip_some
++ || bfd_hash_lookup (info->keep_hash, input_bfd->filename,
++ FALSE, FALSE) != NULL)
++ && discard != discard_all)
++ {
++ val = bfd_get_section_vma (abfd,
++ obj_textsec (input_bfd)->output_section)
++ + obj_textsec (input_bfd)->output_offset;
++
++ written_bytes = write_dri_symbol (abfd, input_bfd->filename,
++ A_TFILE, val);
++ if (written_bytes < 0)
++ return FALSE;
++ else
++ myinfo->dri_symtab_size += written_bytes;
++ }
++
++ /* Now we have a problem. All symbols that we see have already
++ been marked written (because we write them a second time
++ here. If we would do it the clean way we would have
++ to traverse the entire symbol map and reset the written
++ flag. We hack here instead... */
++#define mark_written(h) (* (int *) &h->written = (int) TRUE + 1)
++#define is_written(h) ((int) h->written == (int) TRUE + 1)
++ for (; sym < sym_end; sym++, sym_hash++)
++ {
++ const char *name;
++ int type;
++ struct aout_link_hash_entry *h;
++ asection *symsec;
++ val = 0;
++
++ type = H_GET_8 (input_bfd, sym->e_type);
++ name = strings + GET_WORD (input_bfd, sym->e_strx);
++
++ h = NULL;
++
++ if (pass)
++ {
++ /* Pass this symbol through. It is the target of an
++ indirect or warning symbol. */
++ val = GET_WORD (input_bfd, sym->e_value);
++ pass = FALSE;
++ }
++ else if (skip_next)
++ {
++ /* Skip this symbol, which is the target of an indirect
++ symbol that we have changed to no longer be an indirect
++ symbol. */
++ skip_next = FALSE;
++ continue;
++ }
++ else
++ {
++ struct aout_link_hash_entry *hresolve = *sym_hash;
++
++ /* We have saved the hash table entry for this symbol, if
++ there is one. Note that we could just look it up again
++ in the hash table, provided we first check that it is an
++ external symbol. */
++ h = *sym_hash;
++
++ /* Use the name from the hash table, in case the symbol was
++ wrapped. */
++ if (h != NULL
++ && h->root.type != bfd_link_hash_warning)
++ name = h->root.root.string;
++
++ /* If this is an indirect or warning symbol, then change
++ hresolve to the base symbol. */
++ hresolve = h;
++ if (h != (struct aout_link_hash_entry *) NULL
++ && (h->root.type == bfd_link_hash_indirect
++ || h->root.type == bfd_link_hash_warning))
++ {
++ hresolve = (struct aout_link_hash_entry*) h->root.u.i.link;
++ while (hresolve->root.type == bfd_link_hash_indirect
++ || hresolve->root.type == bfd_link_hash_warning)
++ hresolve = ((struct aout_link_hash_entry*)
++ hresolve->root.u.i.link);
++ }
++
++ /* If the symbol has already been written out skip it. */
++ if (h != NULL
++ && is_written (h))
++ {
++ if ((type & N_TYPE) == N_INDR
++ || type == N_WARNING)
++ skip_next = TRUE;
++ continue;
++ }
++
++ /* See if we are stripping this symbol. */
++ skip = FALSE;
++
++ /* Skip all debugger symbols. No way to output them in
++ DRI format. This will also reduce a lot of headaches. */
++ if ((type & N_STAB) != 0)
++ skip = TRUE;
++
++ switch (strip)
++ {
++ case strip_none:
++ case strip_debugger:
++ break;
++ case strip_some:
++ if (bfd_hash_lookup (info->keep_hash, name, FALSE, FALSE)
++ == NULL)
++ skip = TRUE;
++ break;
++ case strip_all:
++ skip = TRUE;
++ break;
++ }
++
++ if (skip)
++ {
++ if (h != NULL)
++ mark_written (h);
++ continue;
++ }
++
++ /* Get the value of the symbol. */
++ if ((type & N_TYPE) == N_TEXT
++ || type == N_WEAKT)
++ symsec = obj_textsec (input_bfd);
++ else if ((type & N_TYPE) == N_DATA
++ || type == N_WEAKD)
++ symsec = obj_datasec (input_bfd);
++ else if ((type & N_TYPE) == N_BSS
++ || type == N_WEAKB)
++ symsec = obj_bsssec (input_bfd);
++ else if ((type & N_TYPE) == N_ABS
++ || type == N_WEAKA)
++ symsec = bfd_abs_section_ptr;
++ else if (((type & N_TYPE) == N_INDR
++ && (hresolve == NULL
++ || (hresolve->root.type != bfd_link_hash_defined
++ && hresolve->root.type != bfd_link_hash_defweak
++ && hresolve->root.type != bfd_link_hash_common)))
++ || type == N_WARNING)
++ {
++ /* Pass the next symbol through unchanged. The
++ condition above for indirect symbols is so that if
++ the indirect symbol was defined, we output it with
++ the correct definition so the debugger will
++ understand it. */
++ pass = TRUE;
++ val = GET_WORD (input_bfd, sym->e_value);
++ symsec = NULL;
++ }
++ else
++ {
++ /* If we get here with an indirect symbol, it means that
++ we are outputting it with a real definition. In such
++ a case we do not want to output the next symbol,
++ which is the target of the indirection. */
++ if ((type & N_TYPE) == N_INDR)
++ skip_next = TRUE;
++
++ symsec = NULL;
++
++ /* We need to get the value from the hash table. We use
++ hresolve so that if we have defined an indirect
++ symbol we output the final definition. */
++ if (h == NULL)
++ {
++ switch (type & N_TYPE)
++ {
++ case N_SETT:
++ symsec = obj_textsec (input_bfd);
++ break;
++ case N_SETD:
++ symsec = obj_datasec (input_bfd);
++ break;
++ case N_SETB:
++ symsec = obj_bsssec (input_bfd);
++ break;
++ case N_SETA:
++ symsec = bfd_abs_section_ptr;
++ break;
++ default:
++ val = 0;
++ break;
++ }
++ }
++ else if (hresolve->root.type == bfd_link_hash_defined
++ || hresolve->root.type == bfd_link_hash_defweak)
++ {
++ asection *input_section;
++ asection *output_section;
++
++ /* This case usually means a common symbol which was
++ turned into a defined symbol. */
++ input_section = hresolve->root.u.def.section;
++ output_section = input_section->output_section;
++ BFD_ASSERT (bfd_is_abs_section (output_section)
++ || output_section->owner == abfd);
++
++ /* The following reference to the output section VMA
++ is commented out because DRI symbols are relative
++ to the beginning of the section. */
++ val = (hresolve->root.u.def.value
++ /*+ bfd_get_section_vma (abfd, output_section)*/
++ + input_section->output_offset);
++
++ /* TEXT symbols values must be adjusted
++ by adding the size of the extended header. */
++ if (output_section == obj_textsec (abfd))
++ val += TEXT_START_ADDR;
++
++ /* Get the correct type based on the section. If
++ this is a constructed set, force it to be
++ globally visible. */
++ if (type == N_SETT
++ || type == N_SETD
++ || type == N_SETB
++ || type == N_SETA)
++ type |= N_EXT;
++
++ type &=~ N_TYPE;
++
++ if (output_section == obj_textsec (abfd))
++ type |= N_TEXT;
++ else if (output_section == obj_datasec (abfd))
++ type |= N_DATA;
++ else if (output_section == obj_bsssec (abfd))
++ type |= N_BSS;
++ else
++ type |= N_ABS;
++ }
++ else if (hresolve->root.type == bfd_link_hash_common)
++ val = hresolve->root.u.c.size;
++ else if (hresolve->root.type == bfd_link_hash_undefweak)
++ {
++ val = 0;
++ type = N_UNDF;
++ }
++ else
++ val = 0;
++ }
++ if (symsec != NULL)
++ {
++ /* The following reference to the output section VMA
++ is commented out because DRI symbols are relative
++ to the beginning of the section. */
++ val = (/*symsec->output_section->vma
++ +*/ symsec->output_offset
++ + (GET_WORD (input_bfd, sym->e_value)
++ - symsec->vma));
++
++ /* TEXT symbols values must be adjusted
++ by adding the size of the extended header. */
++ if (symsec == obj_textsec (input_bfd))
++ val += TEXT_START_ADDR;
++ }
++
++ /* If this is a global symbol set the written flag, and if
++ it is a local symbol see if we should discard it. */
++ if (h != NULL)
++ {
++ mark_written (h);
++ }
++ else if ((type & N_TYPE) != N_SETT
++ && (type & N_TYPE) != N_SETD
++ && (type & N_TYPE) != N_SETB
++ && (type & N_TYPE) != N_SETA)
++ {
++ switch (discard)
++ {
++ case discard_none:
++ case discard_sec_merge:
++ break;
++ case discard_l:
++ if (bfd_is_local_label_name (input_bfd, name))
++ skip = TRUE;
++ break;
++ default:
++ case discard_all:
++ skip = TRUE;
++ break;
++ }
++ if (skip)
++ {
++ pass = FALSE;
++ continue;
++ }
++ }
++ }
++
++ /* Now find the nearest type in DRI format. */
++ switch (type)
++ {
++ case N_ABS:
++ case N_ABS | N_EXT:
++ case N_SETA:
++ case N_SETA | N_EXT:
++ case N_WEAKA:
++ a_type = A_EQU | A_DEF | A_GLOBL;
++ break;
++ case N_TEXT:
++ case N_TEXT | N_EXT:
++ case N_SETT:
++ case N_SETT | N_EXT:
++ case N_WEAKT:
++ a_type = A_TEXT | A_DEF | A_GLOBL;
++ break;
++ case N_DATA:
++ case N_DATA | N_EXT:
++ case N_SETD:
++ case N_SETD | N_EXT:
++ case N_WEAKD:
++ a_type = A_DATA | A_DEF | A_GLOBL;
++ break;
++ case N_BSS:
++ case N_BSS | N_EXT:
++ case N_SETB:
++ case N_SETB | N_EXT:
++ case N_WEAKB:
++ a_type = A_BSS | A_DEF | A_GLOBL;
++ break;
++ default:
++ continue;
++ }
++
++ written_bytes = write_dri_symbol (abfd, name, a_type, val);
++ if (written_bytes < 0)
++ return FALSE;
++
++ myinfo->dri_symtab_size += written_bytes;
++ }
++ }
++
++ obj_aout_external_string_size (abfd) = 0;
++ return TRUE;
++}
++
++/* This is used for qsort() to sort addresses
++ for the TPA relocation table. */
++
++static int
++vma_cmp (const void *v1, const void *v2)
++{
++ return (int) ((*((bfd_vma *) v1)) - (*((bfd_vma *) v2)));
++}
++
++/* Alloc and fill the TPA relocation table. */
++
++static bfd_boolean
++fill_tparel (bfd *abfd)
++{
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++ unsigned long i;
++ bfd_size_type bytes;
++ unsigned char *ptr;
++
++ /* Sort the relocation info. */
++ if (myinfo->relocs != NULL)
++ qsort (myinfo->relocs, myinfo->relocs_used, sizeof (bfd_vma),
++ vma_cmp);
++
++ /* Now calculate the number of bytes we need. The relocation info
++ is encoded as follows: The first entry is a 32-bit value
++ denoting the first offset to relocate. All following entries
++ are relative to the preceding one. For relative offsets of
++ more than 254 bytes a value of 1 is used. The OS will then
++ add 254 bytes to the current offset. The list is then terminated
++ with the byte 0. */
++ bytes = 4; /* First entry is a long. */
++ for (i = 1; i < myinfo->relocs_used; i++)
++ {
++ unsigned long diff = myinfo->relocs[i] - myinfo->relocs[i - 1];
++ BFD_ASSERT(diff > 0);
++ bytes += (diff + 253) / 254;
++ }
++ /* Last entry is (bfd_byte) 0 if there are some relocations. */
++ if (myinfo->relocs_used > 0)
++ bytes++;
++
++ myinfo->tparel_size = bytes;
++ myinfo->tparel = bfd_alloc (abfd, bytes);
++ if (myinfo->tparel == NULL)
++ return FALSE;
++
++ /* Now fill the array. */
++ ptr = (bfd_byte*) myinfo->tparel;
++ if (myinfo->relocs != NULL)
++ bfd_put_32 (abfd, myinfo->relocs[0], ptr);
++ else
++ bfd_put_32 (abfd, 0, ptr);
++ ptr += 4;
++
++ for (i = 1; i < myinfo->relocs_used; i++)
++ {
++ unsigned long diff = myinfo->relocs[i] - myinfo->relocs[i - 1];
++ while (diff > 254)
++ {
++ *ptr++ = 1;
++ diff -= 254;
++ }
++ *ptr++ = (bfd_byte) diff;
++ }
++
++ if (myinfo->relocs_used > 0)
++ *ptr = 0;
++
++ return TRUE;
++}
++
++/* Final link routine. We need to use a call back to get the correct
++ offsets in the output file. And we need to malloc some internal
++ buffers. */
++
++#define MY_bfd_final_link m68kmint_prg_bfd_final_link
++
++static bfd_boolean
++m68kmint_prg_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
++{
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++ struct bfd_link_hash_table *hash = info->hash;
++ enum bfd_link_strip original_strip = info->strip;
++
++ if (info->relocatable)
++ {
++ _bfd_error_handler ("%B: relocatable output is not supported by format %s",
++ abfd, bfd_get_target (abfd));
++ bfd_set_error (bfd_error_invalid_operation);
++ return FALSE;
++ }
++
++ myinfo->linkinfo = info;
++
++ /* Make sure that for now we never write zmagics. */
++ abfd->flags &= ~D_PAGED;
++
++ /* Find the __stksize symbol. This symbol is used for a MiNT
++ special kludge. The libc defines this symbol in an object file
++ initialized to a default value to make sure it is defined in
++ every output file. The start-up code in crtinit() then simply
++ sets the stacksize accordingly. In your programs (if they need
++ an unusual stacksize) you can then simply code:
++
++ long _stksize = 0x2000;
++
++ This will create a program stack of 2k. Since MiNT cannot detect
++ a stack overflow this is the only way to prevent program crashes
++ caused by a stack that is too small.
++
++ The ancient linker ignored this feature, the ancient strip
++ program paid heed to it. By default, strip never stripped this
++ special symbol from the binary.
++
++ Another program called ``printstk'' and its colleague ``fixstk''
++ could be used to either print the current value of the stacksize
++ or to modify it without recompiling and rebuilding. These
++ programs traversed the symbol table and then took the appropriate
++ measures if the symbol was found.
++
++ Here we do a different approach. Since we already expanded the
++ standard executable header we now hardcode the address (as a file
++ offset) that the __stksize symbol points to into the header. We
++ can now let strip safely remove the entry from the symbol table
++ and we're not dependent on a special format of the symbol table.
++ Because the address is kept in the header we will always be able
++ to manipulate the stacksize value later. */
++ if (hash != NULL)
++ {
++ struct aout_link_hash_entry *h =
++ aout_link_hash_lookup (aout_hash_table (info), "__stksize",
++ FALSE, FALSE, FALSE);
++ asection *sec;
++
++ if (h != NULL)
++ {
++ switch (h->root.type)
++ {
++ case bfd_link_hash_defined:
++ case bfd_link_hash_defweak:
++ sec = h->root.u.def.section->output_section;
++ BFD_ASSERT (sec->owner == abfd);
++
++ myinfo->stkpos = (h->root.u.def.value + sec->vma
++ + h->root.u.def.section->output_offset
++ + GEMDOS_HEADER_SIZE);
++ break;
++ default: /* Ignore other types. */
++ break;
++ }
++ }
++ }
++
++ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
++ {
++ myinfo->traditional_format = TRUE;
++ myinfo->symbol_format = _MINT_SYMBOL_FORMAT_DRI;
++ }
++
++ /* Unconditionally unset the traditional flag. The only effect in
++ the a.out code is to disable string hashing (with respect to
++ SunOS gdx). This is not necessary for us. */
++
++ abfd->flags &= ~BFD_TRADITIONAL_FORMAT;
++
++ /* Do not write GNU symbols in traditional format. */
++ if (myinfo->traditional_format)
++ info->strip = strip_all;
++
++ if (NAME(aout,final_link) (abfd, info, MY_final_link_callback)
++ != TRUE)
++ return FALSE;
++
++ if (myinfo->reloc_error)
++ return FALSE;
++
++ /* Restore the strip status for the traditional symbols. */
++ info->strip = original_strip;
++
++ if (myinfo->traditional_format
++ && link_write_traditional_syms (abfd, info) != TRUE)
++ return FALSE;
++
++ if (fill_tparel (abfd) != TRUE)
++ return FALSE;
++
++ return TRUE;
++}
++
++/* Copy private BFD header information from the input BFD. */
++
++#define MY_bfd_copy_private_header_data m68kmint_prg_bfd_copy_private_header_data
++
++static bfd_boolean
++m68kmint_prg_bfd_copy_private_header_data (bfd *ibfd, bfd *obfd)
++{
++ (void)obfd; /* Unused. */
++
++ /* We can only copy BFD files using our own file format. */
++ if (ibfd->xvec != &m68kmint_prg_vec)
++ {
++ _bfd_error_handler ("%B: cannot convert from format %s to format %s",
++ ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
++ bfd_set_error (bfd_error_invalid_operation);
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++/* Copy backend specific data from one object module to another.
++ This function is used by objcopy and strip. */
++
++#define MY_bfd_copy_private_bfd_data m68kmint_prg_bfd_copy_private_bfd_data
++
++static bfd_boolean
++m68kmint_prg_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
++{
++ struct mint_internal_info *myinfo_in;
++ struct mint_internal_info *myinfo_out;
++
++ /* obfd uses our file format, ibfd may be foreign. */
++ if (ibfd->xvec != &m68kmint_prg_vec)
++ return TRUE;
++
++ myinfo_in = obj_aout_ext (ibfd);
++ BFD_ASSERT (myinfo_in != NULL);
++
++ myinfo_out = obj_aout_ext (obfd);
++ BFD_ASSERT (myinfo_out != NULL);
++
++ /* Copy myinfo. */
++ memcpy (myinfo_out, myinfo_in, sizeof (*myinfo_out));
++
++ /* Copy tparel. */
++ myinfo_out->tparel = bfd_alloc (obfd, myinfo_out->tparel_size);
++ if (myinfo_out->tparel == NULL)
++ return FALSE;
++ memcpy (myinfo_out->tparel, myinfo_in->tparel, myinfo_out->tparel_size);
++
++ /* Normalize the type of empty symbols. */
++ if (bfd_get_symcount (obfd) == 0)
++ myinfo_out->symbol_format = _MINT_SYMBOL_FORMAT_GNU;
++
++ return TRUE; /* _bfd_generic_bfd_copy_private_bfd_data (ibfd, obfd); */
++}
++
++/* Merge private BFD information from an input BFD to the output BFD when linking. */
++
++#define MY_bfd_merge_private_bfd_data m68kmint_prg_merge_private_bfd_data
++
++static bfd_boolean
++m68kmint_prg_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
++{
++ (void)obfd; /* Unused. */
++
++ /* Our file format cannot be used as linker input. */
++ if (ibfd->xvec == &m68kmint_prg_vec)
++ {
++ _bfd_error_handler ("%B: file format %s cannot be used as linker input",
++ ibfd, bfd_get_target (ibfd));
++ bfd_set_error (bfd_error_invalid_operation);
++ return FALSE;
++ }
++
++ return TRUE; /* _bfd_generic_bfd_merge_private_bfd_data (ibfd, obfd); */
++}
++
++/* Find out the symbol name. */
++
++static const char *
++find_symbol_name (reloc_howto_type *howto, bfd *input_bfd,
++ bfd_byte *location, struct reloc_std_external *rel)
++{
++ struct external_nlist *syms = obj_aout_external_syms (input_bfd);
++ char *strings = obj_aout_external_strings (input_bfd);
++ struct aout_link_hash_entry **sym_hashes
++ = obj_aout_sym_hashes (input_bfd);
++ struct aout_link_hash_entry *h = NULL;
++ const char *name;
++ bfd_size_type r_index;
++ int r_extern;
++
++ if (bfd_get_reloc_size (howto) != 4)
++ return "(not a symbol)";
++
++ /* The input bfd is always big-endian. There is no need to
++ call bfd_header_big_endian (input_bfd). */
++ r_index = ((rel->r_index[0] << 16)
++ | (rel->r_index[1] << 8)
++ | (rel->r_index[2]));
++ r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
++
++ if (sym_hashes != NULL)
++ h = sym_hashes[r_index];
++
++ if (!r_extern)
++ {
++ bfd_size_type i;
++ bfd_vma wanted_value = bfd_get_32 (input_bfd, location);
++
++ name = NULL;
++ for (i = 0; i < obj_aout_external_sym_count (input_bfd); i++)
++ {
++ bfd_vma this_value = bfd_get_32 (input_bfd, syms[i].e_value);
++
++ if (this_value == wanted_value)
++ {
++ bfd_byte symtype = bfd_get_8 (input_bfd, syms[i].e_type);
++
++ /* Skip debug symbols and the like. */
++ if ((symtype & N_STAB) != 0)
++ continue;
++
++ /* This is dirty but preferable to a plethoria of
++ single comparisons. */
++ if (symtype <= (N_BSS | N_EXT)
++ || (symtype >= N_WEAKU && symtype <= N_COMM))
++ {
++ name = strings + GET_WORD (input_bfd, syms[i].e_strx);
++ break;
++ }
++ }
++ }
++
++ /* FIXME: If the relocation is against a section there is
++ probably a symbol for that section floating around somewhere
++ in the bfd jungle. */
++ if (name == NULL)
++ {
++ switch ((r_index & N_TYPE) & ~N_EXT)
++ {
++ case N_TEXT:
++ name = "text section";
++ break;
++ case N_DATA:
++ name = "data section";
++ break;
++ case N_BSS:
++ name = "bss section";
++ break;
++ case N_ABS:
++ name = "absolute section";
++ break;
++ default:
++ name = "unknown section";
++ break;
++ }
++ }
++ }
++ else if (h != NULL)
++ name = h->root.root.string;
++ else if (r_index >= obj_aout_external_sym_count (input_bfd))
++ name = "(unknown symbol)"; /* Shouldn't happen. */
++ else
++ name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
++
++ return name;
++}
++
++/* This relocation routine is used by some of the backend linkers.
++ They do not construct asymbol or arelent structures, so there is no
++ reason for them to use bfd_perform_relocation. Also,
++ bfd_perform_relocation is so hacked up it is easier to write a new
++ function than to try to deal with it.
++
++ This routine does a final relocation. Whether it is useful for a
++ relocatable link depends upon how the object format defines
++ relocations.
++
++ FIXME: This routine ignores any special_function in the HOWTO,
++ since the existing special_function values have been written for
++ bfd_perform_relocation.
++
++ HOWTO is the reloc howto information.
++ INPUT_BFD is the BFD which the reloc applies to.
++ INPUT_SECTION is the section which the reloc applies to.
++ CONTENTS is the contents of the section.
++ ADDRESS is the address of the reloc within INPUT_SECTION.
++ VALUE is the value of the symbol the reloc refers to.
++ ADDEND is the addend of the reloc. */
++
++/* The additional parameter REL is specific to this backend.
++ This function is derived from _bfd_final_link_relocate()
++ found in reloc.c. It adds additional checking for dangerous
++ relocations in MiNT sharable text sections, then it records
++ the relocated offset in myinfo->relocs[] for further processing. */
++
++static bfd_reloc_status_type
++m68kmint_prg_final_link_relocate_rel (reloc_howto_type *howto,
++ bfd *input_bfd,
++ asection *input_section,
++ bfd_byte *contents,
++ bfd_vma address,
++ bfd_vma value,
++ bfd_vma addend,
++ struct reloc_std_external *rel)
++{
++ bfd_vma relocation;
++ bfd *output_bfd = input_section->output_section->owner;
++ struct mint_internal_info *myinfo = obj_aout_ext (output_bfd);
++ bfd_reloc_status_type retval;
++ int r_index;
++ int r_extern;
++ bfd_boolean need_tpa_relocation;
++
++ /* The input bfd is always big-endian. There is no need to
++ call bfd_header_big_endian (input_bfd). */
++ r_index = ((rel->r_index[0] << 16)
++ | (rel->r_index[1] << 8)
++ | (rel->r_index[2]));
++ r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
++
++#define _MINT_F_SHTEXT 0x800
++
++ /* Sanity check the address. */
++ if (address > bfd_get_section_limit (input_bfd, input_section))
++ return bfd_reloc_outofrange;
++
++ /* This function assumes that we are dealing with a basic relocation
++ against a symbol. We want to compute the value of the symbol to
++ relocate to. This is just VALUE, the value of the symbol, plus
++ ADDEND, any addend associated with the reloc. */
++ relocation = value + addend;
++
++ /* Check for dangerous relocations in images with a sharable
++ text section. */
++ if ((myinfo->prg_flags & _MINT_F_SHTEXT) != 0
++ && bfd_get_reloc_size (howto) == 4)
++ {
++ bfd_boolean error_found = FALSE;
++ const char *name = NULL;
++
++ if (input_section == obj_textsec (input_bfd))
++ {
++ if (!r_extern)
++ {
++ /* This is a relocation against another section. Only
++ relocations against the text section are allowed. */
++ if (r_index != N_TEXT && r_index != (N_TEXT | N_EXT))
++ error_found = TRUE;
++ }
++ else if (relocation > (input_section->output_section->vma
++ + input_section->output_section->size))
++ {
++ error_found = TRUE;
++ }
++ else if (relocation == (input_section->output_section->vma
++ + input_section->output_section->size))
++ {
++ name = find_symbol_name (howto, input_bfd,
++ contents + address,
++ rel);
++ if (strcmp (name, "_etext") == 0)
++ error_found = FALSE;
++ }
++ }
++
++ if (error_found)
++ {
++ const struct bfd_link_callbacks *callbacks
++ = myinfo->linkinfo->callbacks;
++
++ myinfo->reloc_error = TRUE;
++
++ if (callbacks->reloc_dangerous != NULL)
++ {
++ if (name == NULL)
++ name = find_symbol_name (howto, input_bfd,
++ contents + address,
++ rel);
++
++ callbacks->reloc_dangerous (myinfo->linkinfo, name,
++ input_bfd,
++ input_section, address);
++ }
++ }
++ }
++
++ /* If the relocation is PC relative, we want to set RELOCATION to
++ the distance between the symbol (currently in RELOCATION) and the
++ location we are relocating. Some targets (e.g., i386-aout)
++ arrange for the contents of the section to be the negative of the
++ offset of the location within the section; for such targets
++ pcrel_offset is FALSE. Other targets (e.g., m88kbcs or ELF)
++ simply leave the contents of the section as zero; for such
++ targets pcrel_offset is TRUE. If pcrel_offset is FALSE we do not
++ need to subtract out the offset of the location within the
++ section (which is just ADDRESS). */
++ if (howto->pc_relative)
++ {
++ relocation -= (input_section->output_section->vma
++ + input_section->output_offset);
++ if (howto->pcrel_offset)
++ relocation -= address;
++ }
++
++ retval = _bfd_relocate_contents (howto, input_bfd, relocation,
++ contents + address);
++
++ /* The symbol has to be relocated again iff the length of the relocation
++ is 2 words and it is not pc relative. */
++ need_tpa_relocation = FALSE;
++ if (!howto->pc_relative && bfd_get_reloc_size (howto) == 4)
++ {
++ if (r_extern)
++ {
++ struct aout_link_hash_entry **sym_hashes = obj_aout_sym_hashes (input_bfd);
++ struct aout_link_hash_entry *h = sym_hashes[r_index];
++ asection *output_section = h->root.u.def.section->output_section;
++
++ /* Do not relocate absolute symbols. */
++ if (output_section == obj_textsec (output_bfd)
++ || output_section == obj_datasec (output_bfd)
++ || output_section == obj_bsssec (output_bfd))
++ {
++ need_tpa_relocation = TRUE;
++ }
++ }
++ else
++ {
++ need_tpa_relocation = TRUE;
++ }
++ }
++
++ /* Here we add the TPA relocation entries for the address references
++ located inside the input sections. Note that if some references
++ to addresses are generated using data statements in the linker
++ script, they will not be relocated here because they do not
++ belong to any input section. */
++ if (need_tpa_relocation)
++ {
++ bfd_vma tpa_address = input_section->output_section->vma
++ + input_section->output_offset + address;
++
++ if (!bfd_m68kmint_add_tpa_relocation_entry(output_bfd, tpa_address))
++ return bfd_reloc_other;
++ }
++
++ return retval;
++}
++
++/* Write out the TPA relocation table. */
++
++static bfd_boolean
++write_tparel (bfd *abfd, struct internal_exec *execp)
++{
++ struct mint_internal_info* myinfo = obj_aout_ext (abfd);
++
++ if (myinfo->dri_symtab_size == 0)
++ myinfo->tparel_pos = N_STROFF (*execp)
++ + obj_aout_external_string_size (abfd);
++ else
++ myinfo->tparel_pos = N_SYMOFF (*execp)
++ + myinfo->dri_symtab_size;
++
++ if (bfd_seek (abfd, myinfo->tparel_pos, SEEK_SET) != 0)
++ return FALSE;
++
++ if (bfd_bwrite (myinfo->tparel, myinfo->tparel_size, abfd)
++ != myinfo->tparel_size)
++ return FALSE;
++
++ return TRUE;
++}
++
++/* Write the full exec header.
++ This function must be called last to ensure that we have all the
++ information needed to fill the MiNT-specific header fields. */
++
++static bfd_boolean
++write_exec_header (bfd *abfd, struct internal_exec *execp, struct external_exec *exec_bytes)
++{
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++ bfd_size_type symtab_size;
++
++ bfd_h_put_16 (abfd, 0x601a, exec_bytes->g_branch);
++
++ /* The OS will load our extension header fields into the text segment. */
++ bfd_h_put_32 (abfd, execp->a_text + (EXEC_BYTES_SIZE - GEMDOS_HEADER_SIZE),
++ exec_bytes->g_text);
++ bfd_h_put_32 (abfd, execp->a_data, exec_bytes->g_data);
++ bfd_h_put_32 (abfd, execp->a_bss, exec_bytes->g_bss);
++
++ /* The OS' notion of the size of the symbol table is another than
++ the bfd library's. We have to fill in the size of the table
++ itself plus the size of the string table but only if we have not written
++ a traditional symbol table. If we have written a traditional symbol
++ table we know the size. */
++ if (myinfo->dri_symtab_size != 0)
++ symtab_size = myinfo->dri_symtab_size;
++ else
++ symtab_size = myinfo->tparel_pos - N_SYMOFF (*execp);
++
++ bfd_h_put_32 (abfd, symtab_size, exec_bytes->g_syms);
++
++ bfd_h_put_32 (abfd, 0x4d694e54, exec_bytes->g_extmagic);
++ bfd_h_put_32 (abfd, myinfo->prg_flags, exec_bytes->g_flags);
++ bfd_h_put_16 (abfd, 0, exec_bytes->g_abs);
++
++ /* Generate the jump instruction to the entry point. In m68k
++ assembler mnemnonics it looks more or less like this:
++
++ move.l exec_bytes->e_entry(pc),d0
++ jmp -6(pc,d0.l)
++
++ Sorry for the wrong syntax. As a real assembler addict I
++ never actually use an assembler. I edit my binaries manually
++ with a hex editor, looks much cooler and it strengthens your
++ abstraction abilities. */
++
++ exec_bytes->g_jump_entry[0] = 0x20;
++ exec_bytes->g_jump_entry[1] = 0x3a;
++ exec_bytes->g_jump_entry[2] = 0x00;
++ exec_bytes->g_jump_entry[3] = 0x1a;
++ exec_bytes->g_jump_entry[4] = 0x4e;
++ exec_bytes->g_jump_entry[5] = 0xfb;
++ exec_bytes->g_jump_entry[6] = 0x08;
++ exec_bytes->g_jump_entry[7] = 0xfa;
++
++ bfd_h_put_32 (abfd, myinfo->tparel_pos, exec_bytes->g_tparel_pos);
++ bfd_h_put_32 (abfd, myinfo->tparel_size, exec_bytes->g_tparel_size);
++ bfd_h_put_32 (abfd, myinfo->stkpos, exec_bytes->g_stkpos);
++
++ /* If there are no symbols, pretend they are in GNU format. */
++ if (symtab_size == 0)
++ myinfo->symbol_format = _MINT_SYMBOL_FORMAT_GNU;
++
++ bfd_h_put_32 (abfd, myinfo->symbol_format, exec_bytes->g_symbol_format);
++
++ memset (&exec_bytes->g_pad0, 0, sizeof (exec_bytes->g_pad0));
++
++ /* The standard stuff. */
++ NAME(aout, swap_exec_header_out) (abfd, execp, exec_bytes);
++ if (myinfo->symbol_format != _MINT_SYMBOL_FORMAT_GNU)
++ PUT_WORD (abfd, 0, exec_bytes->e_syms);
++
++ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
++ return FALSE;
++
++ if (bfd_bwrite (exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
++ != EXEC_BYTES_SIZE)
++ return FALSE;
++
++ /* Override the stack size. */
++ if (myinfo->override_stack_size && myinfo->stkpos)
++ {
++ bfd_byte big_endian_stack_size[4];
++
++ bfd_put_32 (abfd, myinfo->stack_size, &big_endian_stack_size);
++
++ if (bfd_seek (abfd, (file_ptr) myinfo->stkpos, SEEK_SET) != 0)
++ return FALSE;
++
++ if (bfd_bwrite (big_endian_stack_size, 4, abfd) != 4)
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++/* Write an object file.
++ Section contents have already been written. We write the
++ file header, symbols, and relocation. */
++
++#define MY_write_object_contents m68kmint_prg_write_object_contents
++
++static bfd_boolean
++m68kmint_prg_write_object_contents (bfd *abfd)
++{
++ struct external_exec exec_bytes;
++ struct internal_exec *execp = exec_hdr (abfd);
++ bfd_size_type text_size;
++ file_ptr text_end;
++
++ BFD_ASSERT (obj_aout_ext (abfd) != NULL);
++
++ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
++
++ /* Most of the following code come from the WRITE_HEADERS macro
++ found in libaout.h. */
++
++ if (adata(abfd).magic == undecided_magic)
++ NAME (aout, adjust_sizes_and_vmas) (abfd, & text_size, & text_end);
++
++ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;
++ execp->a_entry = bfd_get_start_address (abfd);
++
++ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
++ obj_reloc_entry_size (abfd));
++ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
++ obj_reloc_entry_size (abfd));
++
++ /* Now write out reloc info, followed by syms and strings. */
++
++ if (bfd_get_outsymbols (abfd) != NULL
++ && bfd_get_symcount (abfd) != 0)
++ {
++ if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0)
++ return FALSE;
++
++ if (! NAME (aout, write_syms) (abfd))
++ return FALSE;
++ }
++
++ if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*execp)), SEEK_SET) != 0)
++ return FALSE;
++ if (!NAME (aout, squirt_out_relocs) (abfd, obj_textsec (abfd)))
++ return FALSE;
++
++ if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp)), SEEK_SET) != 0)
++ return FALSE;
++ if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))
++ return FALSE;
++
++ if (write_tparel (abfd, execp) != TRUE)
++ return FALSE;
++
++ if (write_exec_header (abfd, execp, &exec_bytes) != TRUE)
++ return FALSE;
++
++ return TRUE;
++}
++
++/* Print private BFD data. Used by objdump -p. */
++
++#define MY_bfd_print_private_bfd_data m68kmint_prg_print_private_bfd_data
++
++static bfd_boolean
++m68kmint_prg_print_private_bfd_data (bfd *abfd, void *ptr)
++{
++ FILE *file = (FILE *) ptr;
++ struct mint_internal_info *myinfo = obj_aout_ext (abfd);
++ const char* symbol_format;
++ long stksize = 0;
++
++ fprintf (file, "\n");
++
++ fprintf (file, " GEMDOS flags: 0x%08lx\n", (unsigned long) myinfo->prg_flags);
++ fprintf (file, "Start address: 0x%08lx\n", bfd_get_start_address (abfd));
++
++ /* Stack size. */
++ if (myinfo->stkpos != 0)
++ {
++ if (bfd_seek (abfd, myinfo->stkpos, SEEK_SET) != 0
++ || (bfd_bread (&stksize, sizeof(long), abfd) != sizeof(long)))
++ return FALSE;
++
++ stksize = bfd_get_signed_32 (abfd, &stksize);
++ }
++ fprintf (file, " Stack size: %ld\n", stksize);
++
++ /* Symbol format. */
++ switch (myinfo->symbol_format)
++ {
++ case _MINT_SYMBOL_FORMAT_GNU: symbol_format = "stabs"; break;
++ case _MINT_SYMBOL_FORMAT_DRI: symbol_format = "DRI"; break;
++ default: symbol_format = "?"; break;
++ }
++ fprintf (file, "Symbol format: %s\n", symbol_format);
++
++ return TRUE;
++}
++
++/* Special case for NAME (aout, get_section_contents)
++ It is not declared in libaout.h, neither implemented in aoutx.h.
++ Instead, a macro named aout_32_get_section_contents is defined in libaout.h.
++ So the default value of MY_get_section_contents provided by aout-target.h
++ is not correct, it has to be defined here with the right value. */
++
++#define MY_get_section_contents aout_32_get_section_contents
++
++/* The following include will define m68kmint_prg_vec
++ and a default implementation for all the MY_ functions
++ not overriden here. */
++
++#include "aout-target.h"
++
++/* Set the GEMDOS executable flags.
++ It is called by the linker emulation script. */
++
++bfd_boolean
++bfd_m68kmint_set_extended_flags (bfd *abfd, flagword prg_flags)
++{
++ struct mint_internal_info *myinfo;
++
++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec);
++ myinfo = obj_aout_ext (abfd);
++ BFD_ASSERT(myinfo != NULL);
++
++ myinfo->prg_flags = prg_flags;
++
++ return TRUE;
++}
++
++/* Override the stack size.
++ It is called by the linker emulation script. */
++
++bfd_boolean
++bfd_m68kmint_set_stack_size (bfd *abfd, bfd_signed_vma stack_size)
++{
++ struct mint_internal_info *myinfo;
++
++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec);
++ myinfo = obj_aout_ext (abfd);
++ BFD_ASSERT(myinfo != NULL);
++
++ myinfo->stack_size = stack_size;
++ myinfo->override_stack_size = TRUE;
++
++ return TRUE;
++}
++
++/* Add a TPA relocation entry.
++ It is called by BFD when linking the input sections, and by the
++ linker when it generates a reference to an address (in particular,
++ when building the constructors list). */
++
++bfd_boolean
++bfd_m68kmint_add_tpa_relocation_entry (bfd *abfd, bfd_vma address)
++{
++ struct mint_internal_info *myinfo;
++
++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec);
++ myinfo = obj_aout_ext (abfd);
++ BFD_ASSERT(myinfo != NULL);
++
++ /* Enlarge the buffer if necessary. */
++ if (myinfo->relocs_used * sizeof (bfd_vma) >= myinfo->relocs_allocated)
++ {
++ bfd_vma *newbuf;
++ myinfo->relocs_allocated += MINT_RELOC_CHUNKSIZE;
++ newbuf = bfd_realloc (myinfo->relocs, myinfo->relocs_allocated);
++ if (newbuf == NULL)
++ return FALSE;
++
++ myinfo->relocs = newbuf;
++ }
++
++ /* The TPA relative relocation actually just adds the address of
++ the text segment (i. e. beginning of the executable in memory)
++ to the addresses at the specified locations. This allows an
++ executable to be loaded everywhere in the address space without
++ memory management. */
++ myinfo->relocs[myinfo->relocs_used++] = address;
++
++ return TRUE;
++}
+diff -ur --new-file binutils-2.21.51.0.7/bfd/targets.c binutils-2.21.51.0.7-mint/bfd/targets.c
+--- binutils-2.21.51.0.7/bfd/targets.c 2011-01-04 17:51:04.000000000 +0000
++++ binutils-2.21.51.0.7-mint/bfd/targets.c 2011-04-08 10:07:08.000000000 +0000
+@@ -770,6 +770,7 @@
+ extern const bfd_target m68kcoff_vec;
+ extern const bfd_target m68kcoffun_vec;
+ extern const bfd_target m68klinux_vec;
++extern const bfd_target m68kmint_prg_vec;
+ extern const bfd_target m68knetbsd_vec;
+ extern const bfd_target m68ksysvcoff_vec;
+ extern const bfd_target m88kbcs_vec;
+diff -ur --new-file binutils-2.21.51.0.7/binutils/configure binutils-2.21.51.0.7-mint/binutils/configure
+--- binutils-2.21.51.0.7/binutils/configure 2011-03-07 18:05:31.000000000 +0000
++++ binutils-2.21.51.0.7-mint/binutils/configure 2011-04-08 10:07:09.000000000 +0000
+@@ -13041,7 +13041,7 @@
+
+
+ case "${host}" in
+-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*)
+
+ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
+ ;;
+diff -ur --new-file binutils-2.21.51.0.7/binutils/dlltool.c binutils-2.21.51.0.7-mint/binutils/dlltool.c
+--- binutils-2.21.51.0.7/binutils/dlltool.c 2010-12-06 14:23:54.000000000 +0000
++++ binutils-2.21.51.0.7-mint/binutils/dlltool.c 2011-04-08 10:07:09.000000000 +0000
+@@ -4360,7 +4360,7 @@
+ if (*cp == '-')
+ dash = cp;
+ if (
+-#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
++#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) || defined(__MINT__)
+ *cp == ':' || *cp == '\\' ||
+ #endif
+ *cp == '/')
+diff -ur --new-file binutils-2.21.51.0.7/binutils/dllwrap.c binutils-2.21.51.0.7-mint/binutils/dllwrap.c
+--- binutils-2.21.51.0.7/binutils/dllwrap.c 2010-08-11 21:51:51.000000000 +0000
++++ binutils-2.21.51.0.7-mint/binutils/dllwrap.c 2011-04-08 10:07:09.000000000 +0000
+@@ -263,7 +263,7 @@
+ dash = cp;
+
+ if (
+-#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
++#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) || defined(__MINT__)
+ *cp == ':' || *cp == '\\' ||
+ #endif
+ *cp == '/')
+diff -ur --new-file binutils-2.21.51.0.7/binutils/readelf.c binutils-2.21.51.0.7-mint/binutils/readelf.c
+--- binutils-2.21.51.0.7/binutils/readelf.c 2011-04-08 09:37:05.000000000 +0000
++++ binutils-2.21.51.0.7-mint/binutils/readelf.c 2011-04-08 10:07:10.000000000 +0000
+@@ -9903,7 +9903,11 @@
+ #ifndef __MSVCRT__
+ /* PR 11128: Use two separate invocations in order to work
+ around bugs in the Solaris 8 implementation of printf. */
++#if GCC_VERSION < 3000
++ printf (" [%6lx] ", (unsigned long) (data - start));
++#else
+ printf (" [%6tx] ", data - start);
++#endif
+ printf ("%s\n", data);
+ #else
+ printf (" [%6Ix] %s\n", (size_t) (data - start), data);
+diff -ur --new-file binutils-2.21.51.0.7/binutils/resrc.c binutils-2.21.51.0.7-mint/binutils/resrc.c
+--- binutils-2.21.51.0.7/binutils/resrc.c 2010-12-06 14:23:55.000000000 +0000
++++ binutils-2.21.51.0.7-mint/binutils/resrc.c 2011-04-08 10:07:10.000000000 +0000
+@@ -396,7 +396,7 @@
+ *space = 0;
+
+ if (
+-#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
++#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) || defined (__MINT__)
+ strchr (cmd, '\\') ||
+ #endif
+ strchr (cmd, '/'))
+@@ -514,7 +514,7 @@
+ if (*cp == '-')
+ dash = cp;
+ if (
+-#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
++#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) || defined (__MINT__)
+ *cp == ':' || *cp == '\\' ||
+ #endif
+ *cp == '/')
+diff -ur --new-file binutils-2.21.51.0.7/gas/config/te-mint.h binutils-2.21.51.0.7-mint/gas/config/te-mint.h
+--- binutils-2.21.51.0.7/gas/config/te-mint.h 1970-01-01 00:00:00.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/config/te-mint.h 2011-04-08 10:07:10.000000000 +0000
+@@ -0,0 +1,30 @@
++/* Copyright 2008 Free Software Foundation, Inc.
++
++ This file is part of GAS, the GNU Assembler.
++
++ GAS is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 3,
++ or (at your option) any later version.
++
++ GAS is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ the GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with GAS; see the file COPYING. If not, write to the Free
++ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
++ 02110-1301, USA. */
++
++#define TE_MINT
++
++#define LOCAL_LABELS_DOLLAR 1
++#define LOCAL_LABELS_FB 1
++
++/* These define interfaces. */
++#ifdef OBJ_HEADER
++#include OBJ_HEADER
++#else
++#include "obj-format.h"
++#endif
+diff -ur --new-file binutils-2.21.51.0.7/gas/configure.tgt binutils-2.21.51.0.7-mint/gas/configure.tgt
+--- binutils-2.21.51.0.7/gas/configure.tgt 2011-01-04 17:51:04.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/configure.tgt 2011-04-08 10:07:10.000000000 +0000
+@@ -266,6 +266,7 @@
+ m68k-*-linux-*) fmt=elf em=linux ;;
+ m68k-*-uclinux*) fmt=elf em=uclinux ;;
+ m68k-*-gnu*) fmt=elf ;;
++ m68k-*-mint*) fmt=aout em=mint bfd_gas=yes ;;
+ m68k-*-netbsdelf*) fmt=elf em=nbsd ;;
+ m68k-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ m68k-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/all/weakref1u.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/all/weakref1u.d
+--- binutils-2.21.51.0.7/gas/testsuite/gas/all/weakref1u.d 2009-11-11 16:52:57.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/all/weakref1u.d 2011-04-08 10:07:10.000000000 +0000
+@@ -3,7 +3,7 @@
+ #source: weakref1.s
+ # aout turns undefined into *ABS* symbols.
+ # see weakref1.d for comments on the other not-targets
+-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* ns32k-*-netbsd alpha*-*-osf* *-*-ecoff
++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint* ns32k-*-netbsd alpha*-*-osf* *-*-ecoff
+
+ # the rest of this file is generated with the following script:
+ # # script begin
+diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/all.exp binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/all.exp
+--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/all.exp 2011-03-07 18:05:32.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/all.exp 2011-04-08 10:10:06.000000000 +0000
+@@ -71,7 +71,7 @@
+
+ gas_test_error "p11673.s" "-march=isab" "movel immediate with offset unsupported on isab"
+
+- if { [istarget *-*-*aout] || [istarget *-*-netbsd] || [istarget *-*-openbsd*] } then {
++ if { [istarget *-*-*aout] || [istarget *-*-netbsd] || [istarget *-*-openbsd*] || [istarget *-*-mint*] } then {
+ run_dump_test p3041
+ run_dump_test p3041data
+ run_dump_test p3041pcrel
+diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isaa.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isaa.d
+--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isaa.d 2009-11-11 16:52:56.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isaa.d 2011-04-08 10:07:10.000000000 +0000
+@@ -1,7 +1,7 @@
+ #name: br-isaa.d
+ #objdump: -dr
+ #as: -march=isaa -pcrel
+-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd*
++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint*
+
+ .*: file format .*
+
+diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isab.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isab.d
+--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isab.d 2009-11-11 16:52:56.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isab.d 2011-04-08 10:07:10.000000000 +0000
+@@ -1,7 +1,7 @@
+ #name: br-isab.d
+ #objdump: -dr
+ #as: -march=isab -pcrel
+-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd*
++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint*
+
+ .*: file format .*
+
+diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isac.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isac.d
+--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isac.d 2009-11-11 16:52:56.000000000 +0000
++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isac.d 2011-04-08 10:07:10.000000000 +0000
+@@ -1,7 +1,7 @@
+ #name: br-isac.d
+ #objdump: -dr
+ #as: -march=isac -pcrel
+-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd*
++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint*
+
+ .*: file format .*
+
+diff -ur --new-file binutils-2.21.51.0.7/include/filenames.h binutils-2.21.51.0.7-mint/include/filenames.h
+--- binutils-2.21.51.0.7/include/filenames.h 2011-03-07 18:05:32.000000000 +0000
++++ binutils-2.21.51.0.7-mint/include/filenames.h 2011-04-08 10:07:27.000000000 +0000
+@@ -30,7 +30,7 @@
+ extern "C" {
+ #endif
+
+-#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
++#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) || defined (__MINT__)
+ # ifndef HAVE_DOS_BASED_FILE_SYSTEM
+ # define HAVE_DOS_BASED_FILE_SYSTEM 1
+ # endif
+diff -ur --new-file binutils-2.21.51.0.7/include/getopt.h binutils-2.21.51.0.7-mint/include/getopt.h
+--- binutils-2.21.51.0.7/include/getopt.h 2005-05-10 22:46:48.000000000 +0000
++++ binutils-2.21.51.0.7-mint/include/getopt.h 2011-04-08 10:07:27.000000000 +0000
+@@ -106,7 +106,7 @@
+ to find the declaration so provide a fully prototyped one. If it
+ is 1, we found it so don't provide any declaration at all. */
+ #if !HAVE_DECL_GETOPT
+-#if defined (__GNU_LIBRARY__) || defined (HAVE_DECL_GETOPT)
++#if defined (__GNU_LIBRARY__) || defined (__MINT__) || defined (HAVE_DECL_GETOPT)
+ /* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in unistd.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+diff -ur --new-file binutils-2.21.51.0.7/ld/Makefile.am binutils-2.21.51.0.7-mint/ld/Makefile.am
+--- binutils-2.21.51.0.7/ld/Makefile.am 2011-03-07 18:05:32.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/Makefile.am 2011-04-08 10:07:27.000000000 +0000
+@@ -308,6 +308,7 @@
+ em68kelf.c \
+ em68kelfnbsd.c \
+ em68klinux.c \
++ em68kmint.c \
+ em68knbsd.c \
+ em68kpsos.c \
+ em88kbcs.c \
+@@ -1319,6 +1320,10 @@
+ em68klinux.c: $(srcdir)/emulparams/m68klinux.sh \
+ $(srcdir)/emultempl/linux.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} m68klinux "$(tdir_m68klinux)"
++em68kmint.c: $(srcdir)/emulparams/m68kmint.sh \
++ $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/mint.em \
++ $(srcdir)/scripttempl/m68kmint.sc ${GEN_DEPENDS}
++ ${GENSCRIPTS} m68kmint "$(tdir_m68kmint)"
+ em68knbsd.c: $(srcdir)/emulparams/m68knbsd.sh \
+ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} m68knbsd "$(tdir_m68knbsd)"
+diff -ur --new-file binutils-2.21.51.0.7/ld/Makefile.in binutils-2.21.51.0.7-mint/ld/Makefile.in
+--- binutils-2.21.51.0.7/ld/Makefile.in 2011-03-07 18:05:32.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/Makefile.in 2011-04-08 10:07:27.000000000 +0000
+@@ -614,6 +614,7 @@
+ em68kelf.c \
+ em68kelfnbsd.c \
+ em68klinux.c \
++ em68kmint.c \
+ em68knbsd.c \
+ em68kpsos.c \
+ em88kbcs.c \
+@@ -1229,6 +1230,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68klinux.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kmint.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68knbsd.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kpsos.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em88kbcs.Po@am__quote@
+@@ -2762,6 +2764,10 @@
+ em68klinux.c: $(srcdir)/emulparams/m68klinux.sh \
+ $(srcdir)/emultempl/linux.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} m68klinux "$(tdir_m68klinux)"
++em68kmint.c: $(srcdir)/emulparams/m68kmint.sh \
++ $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/mint.em \
++ $(srcdir)/scripttempl/m68kmint.sc ${GEN_DEPENDS}
++ ${GENSCRIPTS} m68kmint "$(tdir_m68kmint)"
+ em68knbsd.c: $(srcdir)/emulparams/m68knbsd.sh \
+ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
+ ${GENSCRIPTS} m68knbsd "$(tdir_m68knbsd)"
+diff -ur --new-file binutils-2.21.51.0.7/ld/configure binutils-2.21.51.0.7-mint/ld/configure
+--- binutils-2.21.51.0.7/ld/configure 2011-03-07 18:05:32.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/configure 2011-04-08 10:07:28.000000000 +0000
+@@ -16557,7 +16557,7 @@
+
+
+ case "${host}" in
+-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*)
+
+ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
+ ;;
+diff -ur --new-file binutils-2.21.51.0.7/ld/configure.tgt binutils-2.21.51.0.7-mint/ld/configure.tgt
+--- binutils-2.21.51.0.7/ld/configure.tgt 2011-01-04 17:51:04.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/configure.tgt 2011-04-08 10:07:28.000000000 +0000
+@@ -344,6 +344,7 @@
+ tdir_m68klinux=`echo ${targ_alias} | sed -e 's/linux/linuxaout/'` ;;
+ m68k-*-uclinux*) targ_emul=m68kelf ;;
+ m68*-*-gnu*) targ_emul=m68kelf ;;
++m68*-*-mint*) targ_emul=m68kmint ;;
+ m68*-*-netbsd*4k*) targ_emul=m68k4knbsd
+ targ_extra_emuls="m68knbsd m68kelfnbsd" ;;
+ m68*-*-netbsdelf*) targ_emul=m68kelfnbsd
+diff -ur --new-file binutils-2.21.51.0.7/ld/emulparams/m68kmint.sh binutils-2.21.51.0.7-mint/ld/emulparams/m68kmint.sh
+--- binutils-2.21.51.0.7/ld/emulparams/m68kmint.sh 1970-01-01 00:00:00.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/emulparams/m68kmint.sh 2011-04-08 10:07:28.000000000 +0000
+@@ -0,0 +1,6 @@
++SCRIPT_NAME=m68kmint
++OUTPUT_FORMAT="a.out-mintprg"
++RELOCATEABLE_OUTPUT_FORMAT="a.out-zero-big"
++TEXT_START_ADDR=0xe4
++ARCH=m68k
++EXTRA_EM_FILE=mint
+diff -ur --new-file binutils-2.21.51.0.7/ld/emultempl/mint.em binutils-2.21.51.0.7-mint/ld/emultempl/mint.em
+--- binutils-2.21.51.0.7/ld/emultempl/mint.em 1970-01-01 00:00:00.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/emultempl/mint.em 2011-04-08 10:07:28.000000000 +0000
+@@ -0,0 +1,330 @@
++# This shell script emits a C file. -*- C -*-
++# Copyright 2006, 2007 Free Software Foundation, Inc.
++#
++# This file is part of the GNU Binutils.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
++# MA 02110-1301, USA.
++#
++
++# This file is sourced from generic.em
++#
++fragment <<EOF
++
++#include "getopt.h"
++#include "ldgram.h"
++
++/* Standard GEMDOS program flags. */
++#define _MINT_F_FASTLOAD 0x01 /* Don't clear heap. */
++#define _MINT_F_ALTLOAD 0x02 /* OK to load in alternate RAM. */
++#define _MINT_F_ALTALLOC 0x04 /* OK to malloc from alt. RAM. */
++#define _MINT_F_BESTFIT 0x08 /* Load with optimal heap size. */
++/* The memory flags are mutually exclusive. */
++#define _MINT_F_MEMPROTECTION 0xf0 /* Masks out protection bits. */
++#define _MINT_F_MEMPRIVATE 0x00 /* Memory is private. */
++#define _MINT_F_MEMGLOBAL 0x10 /* Read/write access to mem allowed. */
++#define _MINT_F_MEMSUPER 0x20 /* Only supervisor access allowed. */
++#define _MINT_F_MEMREADABLE 0x30 /* Any read access OK. */
++#define _MINT_F_SHTEXT 0x800 /* Program's text may be shared */
++
++/* Option flags. */
++static flagword prg_flags = (_MINT_F_FASTLOAD | _MINT_F_ALTLOAD
++ | _MINT_F_ALTALLOC | _MINT_F_MEMPRIVATE);
++
++/* If override_stack_size is TRUE, then the executable stack size
++ * must be overriden with the value of stack_size. */
++static bfd_boolean override_stack_size = FALSE;
++static bfd_signed_vma stack_size;
++
++/* MiNT format extra command line options. */
++
++/* Used for setting flags in the MiNT header. */
++#define OPTION_FASTLOAD (300)
++#define OPTION_NO_FASTLOAD (OPTION_FASTLOAD + 1)
++#define OPTION_FASTRAM (OPTION_NO_FASTLOAD + 1)
++#define OPTION_NO_FASTRAM (OPTION_FASTRAM + 1)
++#define OPTION_FASTALLOC (OPTION_NO_FASTRAM + 1)
++#define OPTION_NO_FASTALLOC (OPTION_FASTALLOC + 1)
++#define OPTION_BESTFIT (OPTION_NO_FASTALLOC + 1)
++#define OPTION_NO_BESTFIT (OPTION_BESTFIT + 1)
++#define OPTION_BASEREL (OPTION_NO_BESTFIT + 1)
++#define OPTION_NO_BASEREL (OPTION_BASEREL + 1)
++#define OPTION_MEM_PRIVATE (OPTION_NO_BASEREL + 1)
++#define OPTION_MEM_GLOBAL (OPTION_MEM_PRIVATE + 1)
++#define OPTION_MEM_SUPER (OPTION_MEM_GLOBAL + 1)
++#define OPTION_MEM_READONLY (OPTION_MEM_SUPER + 1)
++#define OPTION_PRG_FLAGS (OPTION_MEM_READONLY + 1)
++#define OPTION_STACK (OPTION_PRG_FLAGS + 1)
++
++static void
++gld${EMULATION_NAME}_add_options
++ (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
++ struct option **longopts, int nrl ATTRIBUTE_UNUSED,
++ struct option **really_longopts ATTRIBUTE_UNUSED)
++{
++ static const struct option xtra_long[] = {
++ {"mfastload", no_argument, NULL, OPTION_FASTLOAD},
++ {"mno-fastload", no_argument, NULL, OPTION_NO_FASTLOAD},
++ {"mfastram", no_argument, NULL, OPTION_FASTRAM},
++ {"mno-fastram", no_argument, NULL, OPTION_NO_FASTRAM},
++ {"maltram", no_argument, NULL, OPTION_FASTRAM},
++ {"mno-altram", no_argument, NULL, OPTION_NO_FASTRAM},
++ {"mfastalloc", no_argument, NULL, OPTION_FASTALLOC},
++ {"mno-fastalloc", no_argument, NULL, OPTION_NO_FASTALLOC},
++ {"maltalloc", no_argument, NULL, OPTION_FASTALLOC},
++ {"mno-altalloc", no_argument, NULL, OPTION_NO_FASTALLOC},
++ {"mbest-fit", no_argument, NULL, OPTION_BESTFIT},
++ {"mno-best-fit", no_argument, NULL, OPTION_NO_BESTFIT},
++ {"mbaserel", no_argument, NULL, OPTION_BASEREL},
++ {"mno-baserel", no_argument, NULL, OPTION_NO_BASEREL},
++ {"mshared-text", no_argument, NULL, OPTION_BASEREL},
++ {"mno-shared-text", no_argument, NULL, OPTION_NO_BASEREL},
++ {"msharable-text", no_argument, NULL, OPTION_BASEREL},
++ {"mno-sharable-text", no_argument, NULL, OPTION_NO_BASEREL},
++ /* Memory protection bits. */
++ {"mprivate-memory", no_argument, NULL, OPTION_MEM_PRIVATE },
++ {"mglobal-memory", no_argument, NULL, OPTION_MEM_GLOBAL},
++ {"msuper-memory", no_argument, NULL, OPTION_MEM_SUPER},
++ {"mreadable-memory", no_argument, NULL, OPTION_MEM_READONLY},
++ {"mreadonly-memory", no_argument, NULL, OPTION_MEM_READONLY},
++ {"mprg-flags", required_argument, NULL, OPTION_PRG_FLAGS},
++ {"stack", required_argument, NULL, OPTION_STACK},
++ {NULL, no_argument, NULL, 0}
++ };
++
++ *longopts = (struct option *)
++ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
++ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
++}
++
++static bfd_boolean
++gld${EMULATION_NAME}_handle_option (int optc)
++{
++ switch (optc)
++ {
++ default:
++ return FALSE;
++
++ case OPTION_FASTLOAD:
++ prg_flags |= _MINT_F_FASTLOAD;
++ break;
++
++ case OPTION_NO_FASTLOAD:
++ prg_flags &= ~_MINT_F_FASTLOAD;
++ break;
++
++ case OPTION_FASTRAM:
++ prg_flags |= _MINT_F_ALTLOAD;
++ break;
++
++ case OPTION_NO_FASTRAM:
++ prg_flags &= ~_MINT_F_ALTLOAD;
++ break;
++
++ case OPTION_FASTALLOC:
++ prg_flags |= _MINT_F_ALTALLOC;
++ break;
++
++ case OPTION_NO_FASTALLOC:
++ prg_flags &= ~_MINT_F_ALTALLOC;
++ break;
++
++ case OPTION_BESTFIT:
++ prg_flags |= _MINT_F_BESTFIT;
++ break;
++
++ case OPTION_NO_BESTFIT:
++ prg_flags &= ~_MINT_F_BESTFIT;
++ break;
++
++ case OPTION_BASEREL:
++ prg_flags |= _MINT_F_SHTEXT;
++ break;
++
++ case OPTION_NO_BASEREL:
++ prg_flags &= ~_MINT_F_SHTEXT;
++ break;
++
++ case OPTION_MEM_PRIVATE:
++ prg_flags &= ~_MINT_F_MEMPROTECTION;
++ break;
++
++ case OPTION_MEM_GLOBAL:
++ prg_flags &= ~_MINT_F_MEMPROTECTION;
++ prg_flags |= _MINT_F_MEMPRIVATE;
++ break;
++
++ case OPTION_MEM_SUPER:
++ prg_flags &= ~_MINT_F_MEMPROTECTION;
++ prg_flags |= _MINT_F_MEMSUPER;
++ break;
++
++ case OPTION_MEM_READONLY:
++ prg_flags &= ~_MINT_F_MEMPROTECTION;
++ prg_flags |= _MINT_F_MEMREADABLE;
++ break;
++
++ case OPTION_PRG_FLAGS:
++ {
++ char* tail;
++ unsigned long flag_value = strtoul (optarg, &tail, 0);
++
++ if (*tail != '\0')
++ einfo (_("%P: warning: ignoring invalid program flags %s\n"), optarg);
++ else
++ prg_flags = flag_value;
++
++ break;
++ }
++ case OPTION_STACK:
++ {
++ char* tail;
++ long size = strtol (optarg, &tail, 0);
++
++ if (*tail == 'K' || *tail == 'k')
++ {
++ size *= 1024;
++ ++tail;
++ }
++ else if (*tail == 'M' || *tail == 'm')
++ {
++ size *= 1024*1024;
++ ++tail;
++ }
++
++ if (*tail != '\0')
++ einfo (_("%P: warning: ignoring invalid stack size %s\n"), optarg);
++ else
++ {
++ stack_size = (bfd_signed_vma) size;
++ override_stack_size = TRUE;
++ }
++
++ break;
++ }
++ }
++ return TRUE;
++}
++
++/* This callback is called when ld is invoked
++ with the --help and --target-help options. */
++
++static void
++gld_${EMULATION_NAME}_list_options (FILE *file)
++{
++ fprintf (file, _(" --m[no-]fastload Enable/Disable not cleaning the heap on startup\n"));
++ fprintf (file, _(" --m[no-]altram, --m[no-]fastram\n"));
++ fprintf (file, _(" Enable/Disable loading into alternate RAM\n"));
++ fprintf (file, _(" --m[no-]altalloc, --m[no-]fastalloc\n"));
++ fprintf (file, _(" Enable/Disable malloc from alternate RAM\n"));
++ fprintf (file, _(" --m[no-]best-fit Enable/Disable loading with optimal heap size\n"));
++ fprintf (file, _(" --m[no-]sharable-text, --m[no-]shared-text, --m[no-]baserel\n"));
++ fprintf (file, _(" Enable/Disable sharing the text segment\n"));
++ fprintf (file, "\n");
++ fprintf (file, _("The following memory options are mutually exclusive:\n"));
++ fprintf (file, _(" --mprivate-memory Process memory is not accessible\n"));
++ fprintf (file, _(" --mglobal-memory Process memory is readable and writable\n"));
++ fprintf (file, _(" --msuper-memory Process memory is accessible in supervisor mode\n"));
++ fprintf (file, _(" --mreadonly-memory, --mreadable-memory\n"));
++ fprintf (file, _(" Process memory is readable but not writable\n"));
++ fprintf (file, "\n");
++ fprintf (file, _(" --mprg-flags <value> Set all the flags with an integer raw value\n"));
++ fprintf (file, _(" --stack <size> Override the stack size (suffix k or M allowed)\n"));
++}
++
++/* This callback is called by lang_for_each_statement. It checks that the
++ output sections speficied in the linker script are compatible with the MiNT
++ executable format. */
++
++static void
++gld${EMULATION_NAME}_check_output_sections (lang_statement_union_type *s)
++{
++ if (s->header.type == lang_output_section_statement_enum)
++ {
++ lang_output_section_statement_type *oss = &s->output_section_statement;
++
++ if (strcmp(oss->name, ".text") == 0 && oss->bfd_section->vma != ${TEXT_START_ADDR})
++ einfo (_("%F%P: the VMA of section %A must be 0x%V, but actual value is 0x%V\n"),
++ oss->bfd_section, ${TEXT_START_ADDR}, oss->bfd_section->vma);
++ else if (strcmp(oss->name, ".data") == 0 && oss->addr_tree != NULL)
++ einfo (_("%F%P: the VMA of section %A must not be specified\n"),
++ oss->bfd_section);
++ else if (strcmp(oss->name, ".bss") == 0 && oss->addr_tree != NULL)
++ einfo (_("%F%P: the VMA of section %A must not be specified\n"),
++ oss->bfd_section);
++ }
++}
++
++/* This callback is called by lang_for_each_statement. It looks for the data
++ statements of type REL generated by the linker, and adds a TPA relocation
++ entry for them. This is used by the CONSTRUCTORS list. */
++
++static void
++gld${EMULATION_NAME}_add_tpa_relocs (lang_statement_union_type *s)
++{
++ if (s->header.type == lang_data_statement_enum)
++ {
++ lang_data_statement_type *ds = &s->data_statement;
++
++ if (ds->exp->type.node_code == REL)
++ {
++ if (ds->type == LONG)
++ {
++ bfd_vma tpa_address = ds->output_section->vma + ds->output_offset;
++ if (!bfd_m68kmint_add_tpa_relocation_entry(link_info.output_bfd, tpa_address))
++ einfo (_("%F%P:%B: unable to add a relocation entry\n"), link_info.output_bfd);
++ }
++ else
++ {
++ einfo (_("%F%P:%B: invalid size for TPA relocation entry in section %A, offset 0x%V\n"),
++ link_info.output_bfd, ds->output_section, ds->output_offset);
++ }
++ }
++ }
++}
++
++/* Final emulation specific call. */
++
++static void
++gld${EMULATION_NAME}_finish (void)
++{
++ /* Do nothing if we are not generating a MiNT executable (ex: binary). */
++ if (strcmp (bfd_get_target (link_info.output_bfd), "${OUTPUT_FORMAT}") != 0)
++ return;
++
++ /* Check the output sections. */
++ lang_for_each_statement (gld${EMULATION_NAME}_check_output_sections);
++
++ /* Set the GEMDOS executable header flags. */
++ if (!bfd_m68kmint_set_extended_flags (link_info.output_bfd, prg_flags))
++ einfo (_("%F%P:%B: unable to set the header flags\n"), link_info.output_bfd);
++
++ /* Override the stack size. */
++ if (override_stack_size)
++ if (!bfd_m68kmint_set_stack_size (link_info.output_bfd, stack_size))
++ einfo (_("%F%P:%B: unable to set the stack size\n"), link_info.output_bfd);
++
++ /* Generate TPA relocation entries for the data statements. */
++ lang_for_each_statement (gld${EMULATION_NAME}_add_tpa_relocs);
++}
++
++EOF
++
++# Put these extra routines in ld_${EMULATION_NAME}_emulation
++#
++LDEMUL_ADD_OPTIONS=gld${EMULATION_NAME}_add_options
++LDEMUL_HANDLE_OPTION=gld${EMULATION_NAME}_handle_option
++LDEMUL_LIST_OPTIONS=gld_${EMULATION_NAME}_list_options
++LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+diff -ur --new-file binutils-2.21.51.0.7/ld/scripttempl/m68kmint.sc binutils-2.21.51.0.7-mint/ld/scripttempl/m68kmint.sc
+--- binutils-2.21.51.0.7/ld/scripttempl/m68kmint.sc 1970-01-01 00:00:00.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/scripttempl/m68kmint.sc 2011-04-08 10:07:28.000000000 +0000
+@@ -0,0 +1,35 @@
++cat <<EOF
++${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})}
++${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})}
++${RELOCATING+${LIB_SEARCH_DIRS}}
++SECTIONS
++{
++ ${RELOCATING+/* The VMA of the .text section is ${TEXT_START_ADDR} instead of 0
++ because the extended MiNT header is just before,
++ at the beginning of the TEXT segment. */}
++ .text ${RELOCATING+${TEXT_START_ADDR}}:
++ {
++ CREATE_OBJECT_SYMBOLS
++ *(.text)
++ ${CONSTRUCTING+CONSTRUCTORS}
++ ${RELOCATING+_etext = .;}
++ ${RELOCATING+__etext = .;}
++ }
++
++ .data :
++ {
++ *(.data)
++ ${RELOCATING+_edata = .;}
++ ${RELOCATING+__edata = .;}
++ }
++
++ .bss :
++ {
++ ${RELOCATING+__bss_start = .;}
++ *(.bss)
++ *(COMMON)
++ ${RELOCATING+_end = .;}
++ ${RELOCATING+__end = .;}
++ }
++}
++EOF
+diff -ur --new-file binutils-2.21.51.0.7/libiberty/hex.c binutils-2.21.51.0.7-mint/libiberty/hex.c
+--- binutils-2.21.51.0.7/libiberty/hex.c 2007-03-16 15:48:30.000000000 +0000
++++ binutils-2.21.51.0.7-mint/libiberty/hex.c 2011-04-08 10:07:28.000000000 +0000
+@@ -24,7 +24,7 @@
+ #include "libiberty.h"
+ #include "safe-ctype.h" /* for HOST_CHARSET_ASCII */
+
+-#if EOF != -1
++#if !(EOF == -1) /* gcc 2.95.3 has bug in '!=' operator for negative constants */
+ #error "hex.c requires EOF == -1"
+ #endif
+
+diff -ur --new-file binutils-2.21.51.0.7/libiberty/safe-ctype.c binutils-2.21.51.0.7-mint/libiberty/safe-ctype.c
+--- binutils-2.21.51.0.7/libiberty/safe-ctype.c 2005-06-22 20:53:36.000000000 +0000
++++ binutils-2.21.51.0.7-mint/libiberty/safe-ctype.c 2011-04-08 10:07:28.000000000 +0000
+@@ -119,7 +119,7 @@
+ #include <safe-ctype.h>
+ #include <stdio.h> /* for EOF */
+
+-#if EOF != -1
++#if !(EOF == -1) /* gcc 2.95.3 has bug in '!=' operator for negative constants */
+ #error "<safe-ctype.h> requires EOF == -1"
+ #endif
+
+--- binutils-2.21.51.0.7/ld/lexsup.c 2011-04-08 15:39:47.000000000 +0000
++++ binutils-2.21.51.0.7-mint/ld/lexsup.c 2011-04-08 15:39:25.000000000 +0000
+@@ -57,6 +57,9 @@
+ #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+ #endif
+
++/* Report plugin symbols. */
++bfd_boolean report_plugin_symbols;
++
+ static void set_default_dirlist (char *);
+ static void set_section_start (char *, char *);
+ static void set_segment_start (const char *, char *);
+--- binutils-2.22/ld/plugin.c 2011-11-21 09:29:39.000000000 +0000
++++ binutils-2.22-mint/ld/plugin.c 2011-12-07 21:24:05.000000000 +0000
+@@ -36,9 +36,6 @@
+ #include <windows.h>
+ #endif
+
+-/* Report plugin symbols. */
+-bfd_boolean report_plugin_symbols;
+-
+ /* The suffix to append to the name of the real (claimed) object file
+ when generating a dummy BFD to hold the IR symbols sent from the
+ plugin. For cosmetic use only; appears in maps, crefs etc. */
+--- binutils-2.22/libiberty/configure 2011-12-08 00:17:02.000000000 +0000
++++ binutils-2.22-mint/libiberty/configure 2011-12-08 00:17:39.000000000 +0000
+@@ -4888,6 +4888,8 @@
+ i[34567]86-*-* | x86_64-*-*)
+ PICFLAG=-fpic
+ ;;
++ *-*-mint*)
++ ;;
+ m68k-*-*)
+ PICFLAG=-fpic
+ ;;