$NetBSD$ --- bfd/i386minix.c.orig Sat Feb 26 00:58:30 2011 +++ bfd/i386minix.c @@ -0,0 +1,325 @@ +/* BFD back-end for i386 minix a.out binaries. + Copyright 1990, 1991, 1992, 1994, 1996, 1997, 2001, 2002, 2003 + Free Software Foundation, Inc. + +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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/***************/ +/* EXEC FORMAT */ +/***************/ +#include + +#define external_exec exec +#define EXEC_BYTES_SIZE sizeof( struct exec ) + +#define OMAGIC 0407 /* Object file or impure executable. */ +#define NMAGIC 0410 /* Code indicating pure executable. */ +#define ZMAGIC 0x0301 /* Code indicating demand-paged executable. */ +#define BMAGIC 0415 /* Used by a b.out object. */ + +#ifndef QMAGIC +#define QMAGIC 0314 +#endif +# ifndef N_BADMAG +# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ + && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC \ + && N_MAGIC(x) != QMAGIC) +# endif /* N_BADMAG */ + +#define N_HEADER_IN_TEXT(x) 0 + +#define N_TXTOFF(x) EXEC_BYTES_SIZE +#define N_TXTADDR(x) 0 + +#define N_TXTSIZE(x) ((x).a_text) +#ifdef SUPPORT_SEP +#define MINIX_IS_SEP(x) 0 /*-> gcv.c HCLICK STUFF*/ +#define N_DATADDR(x) (MINIX_IS_SEP(x) ? align((x).a_text,HCLICK) : (x).a_text ) +#else +#define N_DATADDR(x) ((x).a_text) +#endif + +/* Are these values correct? */ +#define TARGET_PAGE_SIZE 1 +#define SEGMENT_SIZE 1 + +#define DEFAULT_STACK 5 * 1024 * 1024 /* 5 MB stack */ + +#define DEFAULT_ARCH bfd_arch_i386 + +/* 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 (i386minix_,OP) +#define NAME(a,b) i386minix_32_##b +#define TARGETNAME "a.out-i386-minix" +#define NO_WRITE_HEADER_KLUDGE 1 + +#define ARCH_SIZE 32 + +#include "bfd.h" +#include "sysdep.h" +/*#include "libbfd.h"*/ +#include "aout/aout64.h" +#include "libaout.h" + + +#define i386minix_32_get_section_contents _bfd_generic_get_section_contents + +#define SET_ARCH_MACH(abfd, exec) \ + bfd_set_arch_mach(abfd, DEFAULT_ARCH, 0) + +static bfd_boolean i386minix_write_object_contents PARAMS ((bfd *)); +#define MY_write_object_contents i386minix_write_object_contents + +static int MY(swap_exec_header_in) PARAMS ((bfd *, struct external_exec *, struct internal_exec *)); +static void MY(swap_exec_header_out) PARAMS ((bfd *, struct internal_exec *, struct external_exec *)); + +#define NAME_swap_exec_header_in MY(swap_exec_header_in) +#define NAME_swap_exec_header_out MY(swap_exec_header_out) + +#define MY_object_p MY(object_p) +static const bfd_target * MY(object_p) (bfd *); + + +static bfd_boolean MY (set_sizes) PARAMS ((bfd *)); + +#define MY_backend_data &MY(backend_data) +static const struct aout_backend_data MY(backend_data) = { + 0, /* zmagic contiguous */ + 1, /* text incl header */ + 0, /* entry is text address */ + 0, /* exec_hdr_flags */ + 0, /* text vma? */ + MY(set_sizes), + 1, /* exec header not counted */ + 0, /* add_dynamic_symbols */ + 0, /* add_one_symbol */ + 0, /* link_dynamic_object */ + 0, /* write_dynamic_symbol */ + 0, /* check_dynamic_reloc */ + 0 /* finish_dynamic_link */ +}; + +#include "aoutx.h" + +#include "aout-target.h" + +/****************/ +/* WRITE HEADER */ +/****************/ +static void +MY(swap_exec_header_out) (abfd, execp, bytes) + bfd *abfd; + struct internal_exec *execp; + struct external_exec *bytes; +{ + int total; + int stack; + + /* Now fill in fields in the raw data, from the fields in the exec struct. */ + H_PUT_16 (abfd, N_MAGIC(*execp), bytes->a_magic); + + bytes->a_flags = 0; + if ( bytes->a_syms ) + bytes->a_flags |= A_NSYM; + + bytes->a_cpu = A_I80386; + + bytes->a_hdrlen = EXEC_BYTES_SIZE; + + bytes->a_unused = 0; + bytes->a_version = 0; + + PUT_WORD (abfd, execp->a_text , &bytes->a_text); + PUT_WORD (abfd, execp->a_data , &bytes->a_data); + PUT_WORD (abfd, execp->a_bss , &bytes->a_bss); + PUT_WORD (abfd, execp->a_entry , &bytes->a_entry); + + stack = DEFAULT_STACK; + total = execp->a_data + execp->a_bss + stack; +#if 0 + if ( MINIX_IS_SEP( abfd ) ) + bytes->a_flags |= A_SEP; + else +#endif + total += execp->a_text; + + PUT_WORD (abfd, total , &bytes->a_total); + PUT_WORD (abfd, execp->a_syms , &bytes->a_syms); + PUT_WORD (abfd, execp->a_trsize, &bytes->a_trsize); + PUT_WORD (abfd, execp->a_drsize, &bytes->a_drsize); + + bytes->a_tbase = bytes->a_dbase = 0; +} + +#define i386minix_32_swap_exec_header_out MY(swap_exec_header_out) +/* WRITE_HEADERS calls NAME(aout,swap_exec_header_out) + which I need to overwrite. Unfortunately aoutx.h doesn't have a + NAME_swap_exec_header_out like it does for -_in. + So I have to redefine the outcome of NAME(aout,swap_exec_header_out) to + my own function before using WRITE_HEADERS */ + +/* Set the machine type correctly. */ +static bfd_boolean +i386minix_write_object_contents (abfd) + bfd *abfd; +{ + struct external_exec exec_bytes; + struct internal_exec *execp = exec_hdr (abfd); + + N_SET_MACHTYPE (*execp, M_386); + + obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; + + WRITE_HEADERS (abfd, execp); + + return TRUE; +} +/* undo renaming to be able to include aoutx.h */ +#undef i386minix_32_swap_exec_header_out + +/***************/ +/* READ HEADER */ +/***************/ +/* define if aoutx.h is included: */ +/* UNTRUE: but including it generates a conflict with swap_exe_header_out, so don't include it */ + +/* return -1 if header is wrong + * otherwise return the bytes left to read */ +static int +MY(swap_exec_header_in) (abfd, bytes, execp) + bfd *abfd; + struct external_exec *bytes; + struct internal_exec *execp; +{ + /* The internal_exec structure has some fields that are unused in this + configuration (IE for i960), so ensure that all such uninitialized + fields are zero'd out. There are places where two of these structs + are memcmp'd, and thus the contents do matter. */ + memset ((PTR) execp, 0, sizeof (struct internal_exec)); + /* Now fill in fields in the execp, from the bytes in the raw data. */ + + /*fill a_info*/ + N_SET_MAGIC(*execp, H_GET_16 (abfd, bytes->a_magic)); + N_SET_MACHTYPE(*execp, M_386); + N_SET_FLAGS(*execp, 0); + + /*check integrity*/ + if ( N_BADMAG( *execp ) ) + return -1; + + if ( bytes->a_cpu != A_I80386 ) + return -1; + + if ( bytes->a_hdrlen < A_MINHDR ) + return -1; + +#if 0 + if ( bytes->a_flags & A_SEP ) + dosomething(); +#endif + + /*fill the rest*/ + execp->a_text = GET_WORD (abfd, &bytes->a_text); + execp->a_data = GET_WORD (abfd, &bytes->a_data); + execp->a_bss = GET_WORD (abfd, &bytes->a_bss); + execp->a_syms = GET_WORD (abfd, &bytes->a_syms); + execp->a_entry = GET_WORD (abfd, &bytes->a_entry); + + if ( bytes->a_hdrlen < A_MINHDR + 2 * sizeof(long) ) + return bytes->a_hdrlen - A_MINHDR; + + if (bfd_bread (&bytes->a_trsize, 2 * sizeof(long), abfd) != 2 * sizeof(long)) + return -1; + + execp->a_trsize = GET_WORD (abfd, &bytes->a_trsize); + execp->a_drsize = GET_WORD (abfd, &bytes->a_drsize); + + bfd_seek (abfd, -2 * sizeof(long), SEEK_CUR); + + /*store other fields of external_exec?*/ + return bytes->a_hdrlen - A_MINHDR; +} + +static const bfd_target * +MY(object_p) (abfd) + bfd *abfd; +{ + struct external_exec exec_bytes; /* Raw exec header from file */ + struct internal_exec exec; /* Cleaned-up exec header */ + const bfd_target *target; + int left; + bfd_size_type amt = A_MINHDR; + + if (bfd_bread ((PTR) &exec_bytes, amt, abfd) != amt) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_wrong_format); + + return 0; + } + + /* let MY(swap_exec_header_in) check the header */ + if ( (left = MY(swap_exec_header_in) (abfd, &exec_bytes, &exec)) == -1 ) + { + /* incorrect header */ + return 0; + } + + /* skip rest of header */ + if ( bfd_seek( abfd, left, SEEK_CUR ) ) + return 0; + + target = NAME(aout,some_aout_object_p) (abfd, &exec, MY(callback)); + + int adjust = (A_MINHDR + left) - EXEC_BYTES_SIZE; + + /* adjust file positions with the bytes left to be read from the header */ + obj_textsec (abfd)->filepos += adjust; + obj_datasec (abfd)->filepos += adjust; + + obj_textsec (abfd)->rel_filepos += adjust; + obj_datasec (abfd)->rel_filepos += adjust; + + obj_sym_filepos (abfd) += adjust; + obj_str_filepos (abfd) += adjust; + + adata(abfd).exec_bytes_size = A_MINHDR + left; + +#ifdef ENTRY_CAN_BE_ZERO + /* The NEWSOS3 entry-point is/was 0, which (amongst other lossage) + * means that it isn't obvious if EXEC_P should be set. + * All of the following must be true for an executable: + * There must be no relocations, the bfd can be neither an + * archive nor an archive element, and the file must be executable. */ + + if (exec.a_trsize + exec.a_drsize == 0 + && bfd_get_format(abfd) == bfd_object && abfd->my_archive == NULL) + { + struct stat buf; +#ifndef S_IXUSR +#define S_IXUSR 0100 /* Execute by owner. */ +#endif + if (stat(abfd->filename, &buf) == 0 && (buf.st_mode & S_IXUSR)) + abfd->flags |= EXEC_P; + } +#endif /* ENTRY_CAN_BE_ZERO */ + + return target; +}