#define BYTES_IN_WORD 2
#define BYTES_IN_LONG 4
#define ARCH_SIZE 16
#undef TARGET_IS_BIG_ENDIAN_P
#define TARGET_PAGE_SIZE 1024
#define SEGMENT__SIZE TARGET_PAGE_SIZE
#define DEFAULT_ARCH bfd_arch_pdp11
#define DEFAULT_MID M_PDP11
#define MY(OP) CONCAT2 (pdp11_aout_,OP)
#define TARGETNAME "a.out-pdp11"
#define TEXT_START_ADDR 0
#define N_HEADER_IN_TEXT(x) 0
#define N_SHARED_LIB(x) 0
#define N_FLAGS(exec) 0
#define N_SET_FLAGS(exec, flags) do { } while (0)
#define N_BADMAG(x) (((x).a_info != OMAGIC) && \
((x).a_info != NMAGIC) && \
((x).a_info != A_MAGIC3) && \
((x).a_info != A_MAGIC4) && \
((x).a_info != A_MAGIC5) && \
((x).a_info != A_MAGIC6))
#include "bfd.h"
#define external_exec pdp11_external_exec
struct pdp11_external_exec
{
bfd_byte e_info[2];
bfd_byte e_text[2];
bfd_byte e_data[2];
bfd_byte e_bss[2];
bfd_byte e_syms[2];
bfd_byte e_entry[2];
bfd_byte e_unused[2];
bfd_byte e_flag[2];
bfd_byte e_relocatable;
};
#define EXEC_BYTES_SIZE (8 * 2)
#define A_MAGIC1 OMAGIC
#define OMAGIC 0407
#define A_MAGIC2 NMAGIC
#define NMAGIC 0410
#define ZMAGIC 0413
#define A_MAGIC3 0411
#define A_MAGIC4 0405
#define A_MAGIC5 0430
#define A_MAGIC6 0431
#define QMAGIC 0
#define BMAGIC 0
#define A_FLAG_RELOC_STRIPPED 0x0001
#define external_nlist pdp11_external_nlist
struct pdp11_external_nlist
{
bfd_byte e_unused[2];
bfd_byte e_strx[2];
bfd_byte e_type[1];
bfd_byte e_ovly[1];
bfd_byte e_value[2];
};
#define EXTERNAL_NLIST_SIZE 8
#define N_TXTOFF(x) (EXEC_BYTES_SIZE)
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
#define WRITE_HEADERS(abfd, execp) pdp11_aout_write_headers (abfd, execp)
#include "sysdep.h"
#include "libbfd.h"
#include "libaout.h"
#define SWAP_MAGIC(ext) bfd_getl16 (ext)
#define MY_entry_is_text_address 1
#define MY_write_object_contents MY(write_object_contents)
static bfd_boolean MY(write_object_contents) PARAMS ((bfd *abfd));
#define MY_text_includes_header 1
bfd_vma bfd_getp32 PARAMS ((const bfd_byte *));
bfd_signed_vma bfd_getp_signed_32 PARAMS ((const bfd_byte *));
void bfd_putp32 PARAMS ((bfd_vma, bfd_byte *));
#define MY_BFD_TARGET
#include "aout-target.h"
const bfd_target MY(vec) =
{
TARGETNAME,
bfd_target_aout_flavour,
BFD_ENDIAN_LITTLE,
BFD_ENDIAN_LITTLE,
(HAS_RELOC | EXEC_P |
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | WP_TEXT),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
MY_symbol_leading_char,
AR_PAD_CHAR,
15,
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getp32, bfd_getp_signed_32, bfd_putp32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getp32, bfd_getp_signed_32, bfd_putp32,
bfd_getl16, bfd_getl_signed_16, bfd_putl16,
{_bfd_dummy_target, MY_object_p,
bfd_generic_archive_p, MY_core_file_p},
{bfd_false, MY_mkobject,
_bfd_generic_mkarchive, bfd_false},
{bfd_false, MY_write_object_contents,
_bfd_write_archive_contents, bfd_false},
BFD_JUMP_TABLE_GENERIC (MY),
BFD_JUMP_TABLE_COPY (MY),
BFD_JUMP_TABLE_CORE (MY),
BFD_JUMP_TABLE_ARCHIVE (MY),
BFD_JUMP_TABLE_SYMBOLS (MY),
BFD_JUMP_TABLE_RELOCS (MY),
BFD_JUMP_TABLE_WRITE (MY),
BFD_JUMP_TABLE_LINK (MY),
BFD_JUMP_TABLE_DYNAMIC (MY),
NULL,
(PTR) MY_backend_data,
};
#define KEEPIT udata.i
#include <string.h>
#include "bfd.h"
#include "sysdep.h"
#include "safe-ctype.h"
#include "bfdlink.h"
#include "libaout.h"
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
#include "aout/ar.h"
#undef N_TYPE
#undef N_UNDF
#undef N_ABS
#undef N_TEXT
#undef N_DATA
#undef N_BSS
#undef N_REG
#undef N_FN
#undef N_EXT
#define N_TYPE 0x1f
#define N_UNDF 0x00
#define N_ABS 0x01
#define N_TEXT 0x02
#define N_DATA 0x03
#define N_BSS 0x04
#define N_REG 0x14
#define N_FN 0x1f
#define N_EXT 0x20
#define RELOC_SIZE 2
struct pdp11_aout_reloc_external
{
bfd_byte e_reloc_entry[2];
};
#define RELFLG 0x0001
#define RTYPE 0x000e
#define RIDXMASK 0xfff0
#define RABS 0x00
#define RTEXT 0x02
#define RDATA 0x04
#define RBSS 0x06
#define REXT 0x08
#define RINDEX(x) (((x) & 0xfff0) >> 4)
static bfd_boolean aout_get_external_symbols PARAMS ((bfd *));
static bfd_boolean translate_from_native_sym_flags
PARAMS ((bfd *, aout_symbol_type *));
static bfd_boolean translate_to_native_sym_flags
PARAMS ((bfd *, asymbol *, struct external_nlist *));
static void adjust_o_magic PARAMS ((bfd *, struct internal_exec *));
static void adjust_z_magic PARAMS ((bfd *, struct internal_exec *));
static void adjust_n_magic PARAMS ((bfd *, struct internal_exec *));
static int pdp11_aout_write_headers PARAMS ((bfd *, struct internal_exec *));
void pdp11_aout_swap_reloc_out PARAMS ((bfd *, arelent *, struct pdp11_aout_reloc_external *));
void pdp11_aout_swap_reloc_in
PARAMS ((bfd *, struct pdp11_aout_reloc_external *, arelent *,
bfd_size_type, asymbol **, bfd_size_type));
#ifndef MY_final_link_relocate
#define MY_final_link_relocate _bfd_final_link_relocate
#endif
#ifndef MY_relocate_contents
#define MY_relocate_contents _bfd_relocate_contents
#endif
reloc_howto_type howto_table_pdp11[] =
{
HOWTO( 0, 0, 1, 16, FALSE, 0, complain_overflow_signed,0,"16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
HOWTO( 1, 0, 1, 16, TRUE, 0, complain_overflow_signed,0,"DISP16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
};
#define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0]))
reloc_howto_type *
NAME(aout,reloc_type_lookup) (abfd,code)
bfd * abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
switch (code)
{
case BFD_RELOC_16:
return &howto_table_pdp11[0];
case BFD_RELOC_16_PCREL:
return &howto_table_pdp11[1];
default:
return (reloc_howto_type *)NULL;
}
}
static int
pdp11_aout_write_headers (abfd, execp)
bfd *abfd;
struct internal_exec *execp;
{
struct external_exec exec_bytes;
bfd_size_type text_size;
file_ptr text_end;
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);
if (obj_textsec (abfd)->reloc_count > 0 ||
obj_datasec (abfd)->reloc_count > 0)
{
execp->a_trsize = execp->a_text;
execp->a_drsize = execp->a_data;
}
else
{
execp->a_trsize = 0;
execp->a_drsize = 0;
}
NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
return FALSE;
if (bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
!= EXEC_BYTES_SIZE)
return FALSE;
if (bfd_get_outsymbols (abfd) != (asymbol **) 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 (obj_textsec (abfd)->reloc_count > 0 ||
obj_datasec (abfd)->reloc_count > 0)
{
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;
}
return TRUE;
}
static bfd_boolean
MY(write_object_contents) (abfd)
bfd *abfd;
{
struct internal_exec *execp = exec_hdr (abfd);
if (! abfd->output_has_begun)
{
bfd_size_type text_size;
file_ptr text_end;
NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
}
obj_reloc_entry_size (abfd) = RELOC_SIZE;
return WRITE_HEADERS(abfd, execp);
}
#ifndef NAME_swap_exec_header_in
void
NAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp)
bfd *abfd;
struct external_exec *raw_bytes;
struct internal_exec *execp;
{
struct external_exec *bytes = (struct external_exec *)raw_bytes;
memset ((PTR) execp, 0, sizeof (struct internal_exec));
execp->a_info = GET_MAGIC (abfd, bytes->e_info);
execp->a_text = GET_WORD (abfd, bytes->e_text);
execp->a_data = GET_WORD (abfd, bytes->e_data);
execp->a_bss = GET_WORD (abfd, bytes->e_bss);
execp->a_syms = GET_WORD (abfd, bytes->e_syms);
execp->a_entry = GET_WORD (abfd, bytes->e_entry);
if (GET_WORD (abfd, bytes->e_flag) & A_FLAG_RELOC_STRIPPED)
{
execp->a_trsize = 0;
execp->a_drsize = 0;
}
else
{
execp->a_trsize = execp->a_text;
execp->a_drsize = execp->a_data;
}
}
#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in)
#endif
void
NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes)
bfd *abfd;
struct internal_exec *execp;
struct external_exec *raw_bytes;
{
struct external_exec *bytes = (struct external_exec *)raw_bytes;
PUT_MAGIC (abfd, execp->a_info, bytes->e_info);
PUT_WORD (abfd, execp->a_text, bytes->e_text);
PUT_WORD (abfd, execp->a_data, bytes->e_data);
PUT_WORD (abfd, execp->a_bss, bytes->e_bss);
PUT_WORD (abfd, execp->a_syms, bytes->e_syms);
PUT_WORD (abfd, execp->a_entry, bytes->e_entry);
PUT_WORD (abfd, 0, bytes->e_unused);
if ((execp->a_trsize == 0 || execp->a_text == 0) &&
(execp->a_drsize == 0 || execp->a_data == 0))
PUT_WORD (abfd, A_FLAG_RELOC_STRIPPED, bytes->e_flag);
else if (execp->a_trsize == execp->a_text &&
execp->a_drsize == execp->a_data)
PUT_WORD (abfd, 0, bytes->e_flag);
else
{
fprintf (stderr, "BFD:%s:%d: internal error\n", __FILE__, __LINE__);
PUT_WORD (abfd, 0, bytes->e_flag);
}
}
bfd_boolean
NAME(aout,make_sections) (abfd)
bfd *abfd;
{
if (obj_textsec (abfd) == (asection *) NULL
&& bfd_make_section (abfd, ".text") == (asection *) NULL)
return FALSE;
if (obj_datasec (abfd) == (asection *) NULL
&& bfd_make_section (abfd, ".data") == (asection *) NULL)
return FALSE;
if (obj_bsssec (abfd) == (asection *) NULL
&& bfd_make_section (abfd, ".bss") == (asection *) NULL)
return FALSE;
return TRUE;
}
const bfd_target *
NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
bfd *abfd;
struct internal_exec *execp;
const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *));
{
struct aout_data_struct *rawptr, *oldrawptr;
const bfd_target *result;
bfd_size_type amt = sizeof (struct aout_data_struct);
rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
if (rawptr == NULL)
return 0;
oldrawptr = abfd->tdata.aout_data;
abfd->tdata.aout_data = rawptr;
if (oldrawptr != NULL)
*abfd->tdata.aout_data = *oldrawptr;
abfd->tdata.aout_data->a.hdr = &rawptr->e;
*(abfd->tdata.aout_data->a.hdr) = *execp;
execp = abfd->tdata.aout_data->a.hdr;
abfd->flags = BFD_NO_FLAGS;
if (execp->a_drsize || execp->a_trsize)
abfd->flags |= HAS_RELOC;
if (execp->a_syms)
abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
if (N_DYNAMIC(*execp))
abfd->flags |= DYNAMIC;
if (N_MAGIC (*execp) == ZMAGIC)
{
abfd->flags |= D_PAGED | WP_TEXT;
adata (abfd).magic = z_magic;
}
else if (N_MAGIC (*execp) == QMAGIC)
{
abfd->flags |= D_PAGED | WP_TEXT;
adata (abfd).magic = z_magic;
adata (abfd).subformat = q_magic_format;
}
else if (N_MAGIC (*execp) == NMAGIC)
{
abfd->flags |= WP_TEXT;
adata (abfd).magic = n_magic;
}
else if (N_MAGIC (*execp) == OMAGIC
|| N_MAGIC (*execp) == BMAGIC)
adata (abfd).magic = o_magic;
else
{
abort ();
}
bfd_get_start_address (abfd) = execp->a_entry;
obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
obj_reloc_entry_size (abfd) = RELOC_SIZE;
obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
#ifdef USE_MMAP
bfd_init_window (&obj_aout_sym_window (abfd));
bfd_init_window (&obj_aout_string_window (abfd));
#endif
obj_aout_external_syms (abfd) = NULL;
obj_aout_external_strings (abfd) = NULL;
obj_aout_sym_hashes (abfd) = NULL;
if (! NAME(aout,make_sections) (abfd))
return NULL;
obj_datasec (abfd)->_raw_size = execp->a_data;
obj_bsssec (abfd)->_raw_size = execp->a_bss;
obj_textsec (abfd)->flags =
(execp->a_trsize != 0
? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
: (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
obj_datasec (abfd)->flags =
(execp->a_drsize != 0
? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
: (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
obj_bsssec (abfd)->flags = SEC_ALLOC;
#ifdef THIS_IS_ONLY_DOCUMENTATION
struct exec *execp = exec_hdr (abfd);
obj_textsec (abfd)->size = N_TXTSIZE(*execp);
obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp);
obj_textsec (abfd)->vma = N_TXTADDR(*execp);
obj_datasec (abfd)->vma = N_DATADDR(*execp);
obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
obj_datasec (abfd)->filepos = N_DATOFF(*execp);
obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
obj_str_filepos (abfd) = N_STROFF (*execp);
obj_sym_filepos (abfd) = N_SYMOFF (*execp);
abfd->obj_arch = bfd_arch_obscure;
adata(abfd)->page_size = TARGET_PAGE_SIZE;
adata(abfd)->segment_size = SEGMENT_SIZE;
adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
return abfd->xvec;
#endif
result = (*callback_to_real_object_p)(abfd);
if (execp->a_entry != 0
|| (execp->a_entry >= obj_textsec(abfd)->vma
&& execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
abfd->flags |= EXEC_P;
#ifdef STAT_FOR_EXEC
else
{
struct stat stat_buf;
if (abfd->iostream != NULL
&& (abfd->flags & BFD_IN_MEMORY) == 0
&& (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
&& ((stat_buf.st_mode & 0111) != 0))
abfd->flags |= EXEC_P;
}
#endif
if (result)
{
#if 0
abfd->sections = obj_textsec (abfd);
obj_textsec (abfd)->next = obj_datasec (abfd);
obj_datasec (abfd)->next = obj_bsssec (abfd);
#endif
}
else
{
free (rawptr);
abfd->tdata.aout_data = oldrawptr;
}
return result;
}
bfd_boolean
NAME(aout,mkobject) (abfd)
bfd *abfd;
{
struct aout_data_struct *rawptr;
bfd_size_type amt = sizeof (struct aout_data_struct);
bfd_set_error (bfd_error_system_call);
rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
if (rawptr == NULL)
return FALSE;
abfd->tdata.aout_data = rawptr;
exec_hdr (abfd) = &(rawptr->e);
obj_textsec (abfd) = (asection *)NULL;
obj_datasec (abfd) = (asection *)NULL;
obj_bsssec (abfd) = (asection *)NULL;
return TRUE;
}
enum machine_type
NAME(aout,machine_type) (arch, machine, unknown)
enum bfd_architecture arch;
unsigned long machine;
bfd_boolean *unknown;
{
enum machine_type arch_flags;
arch_flags = M_UNKNOWN;
*unknown = TRUE;
switch (arch)
{
case bfd_arch_sparc:
if (machine == 0
|| machine == bfd_mach_sparc
|| machine == bfd_mach_sparc_sparclite
|| machine == bfd_mach_sparc_v9)
arch_flags = M_SPARC;
else if (machine == bfd_mach_sparc_sparclet)
arch_flags = M_SPARCLET;
break;
case bfd_arch_m68k:
switch (machine)
{
case 0: arch_flags = M_68010; break;
case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = FALSE; break;
case bfd_mach_m68010: arch_flags = M_68010; break;
case bfd_mach_m68020: arch_flags = M_68020; break;
default: arch_flags = M_UNKNOWN; break;
}
break;
case bfd_arch_i386:
if (machine == 0
|| machine == bfd_mach_i386_i386
|| machine == bfd_mach_i386_i386_intel_syntax)
arch_flags = M_386;
break;
case bfd_arch_a29k:
if (machine == 0) arch_flags = M_29K;
break;
case bfd_arch_arm:
if (machine == 0) arch_flags = M_ARM;
break;
case bfd_arch_mips:
switch (machine)
{
case 0:
case 2000:
case bfd_mach_mips3000:
arch_flags = M_MIPS1;
break;
case bfd_mach_mips4000:
case bfd_mach_mips4400:
case bfd_mach_mips8000:
case bfd_mach_mips6000:
arch_flags = M_MIPS2;
break;
default:
arch_flags = M_UNKNOWN;
break;
}
break;
case bfd_arch_ns32k:
switch (machine)
{
case 0: arch_flags = M_NS32532; break;
case 32032: arch_flags = M_NS32032; break;
case 32532: arch_flags = M_NS32532; break;
default: arch_flags = M_UNKNOWN; break;
}
break;
case bfd_arch_pdp11:
*unknown = FALSE;
break;
case bfd_arch_vax:
*unknown = FALSE;
break;
default:
arch_flags = M_UNKNOWN;
}
if (arch_flags != M_UNKNOWN)
*unknown = FALSE;
return arch_flags;
}
bfd_boolean
NAME(aout,set_arch_mach) (abfd, arch, machine)
bfd *abfd;
enum bfd_architecture arch;
unsigned long machine;
{
if (! bfd_default_set_arch_mach (abfd, arch, machine))
return FALSE;
if (arch != bfd_arch_unknown)
{
bfd_boolean unknown;
NAME(aout,machine_type) (arch, machine, &unknown);
if (unknown)
return FALSE;
}
obj_reloc_entry_size (abfd) = RELOC_SIZE;
return (*aout_backend_info(abfd)->set_sizes) (abfd);
}
static void
adjust_o_magic (abfd, execp)
bfd *abfd;
struct internal_exec *execp;
{
file_ptr pos = adata (abfd).exec_bytes_size;
bfd_vma vma = 0;
int pad = 0;
obj_textsec (abfd)->filepos = pos;
if (! obj_textsec (abfd)->user_set_vma)
obj_textsec (abfd)->vma = vma;
else
vma = obj_textsec (abfd)->vma;
pos += obj_textsec (abfd)->_raw_size;
vma += obj_textsec (abfd)->_raw_size;
if (!obj_datasec (abfd)->user_set_vma)
{
#if 0
pad = align_power (vma, obj_datasec (abfd)->alignment_power) - vma;
#endif
obj_textsec (abfd)->_raw_size += pad;
pos += pad;
vma += pad;
obj_datasec (abfd)->vma = vma;
}
else
vma = obj_datasec (abfd)->vma;
obj_datasec (abfd)->filepos = pos;
pos += obj_datasec (abfd)->_raw_size;
vma += obj_datasec (abfd)->_raw_size;
if (! obj_bsssec (abfd)->user_set_vma)
{
#if 0
pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma;
#endif
obj_datasec (abfd)->_raw_size += pad;
pos += pad;
vma += pad;
obj_bsssec (abfd)->vma = vma;
}
else
{
pad = obj_bsssec (abfd)->vma - vma;
if (pad > 0)
{
obj_datasec (abfd)->_raw_size += pad;
pos += pad;
}
}
obj_bsssec (abfd)->filepos = pos;
execp->a_text = obj_textsec (abfd)->_raw_size;
execp->a_data = obj_datasec (abfd)->_raw_size;
execp->a_bss = obj_bsssec (abfd)->_raw_size;
N_SET_MAGIC (*execp, OMAGIC);
}
static void
adjust_z_magic (abfd, execp)
bfd *abfd;
struct internal_exec *execp;
{
bfd_size_type data_pad, text_pad;
file_ptr text_end;
const struct aout_backend_data *abdp;
int ztih;
abdp = aout_backend_info (abfd);
ztih = (abdp != NULL
&& (abdp->text_includes_header
|| obj_aout_subformat (abfd) == q_magic_format));
obj_textsec(abfd)->filepos = (ztih
? adata(abfd).exec_bytes_size
: adata(abfd).zmagic_disk_block_size);
if (! obj_textsec(abfd)->user_set_vma)
{
obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC)
? 0
: (ztih
? (abdp->default_text_vma
+ adata (abfd).exec_bytes_size)
: abdp->default_text_vma));
text_pad = 0;
}
else
{
if (ztih)
text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma)
& (adata (abfd).page_size - 1));
else
text_pad = ((- obj_textsec (abfd)->vma)
& (adata (abfd).page_size - 1));
}
if (ztih)
{
text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size;
text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
}
else
{
text_end = obj_textsec (abfd)->_raw_size;
text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
text_end += obj_textsec (abfd)->filepos;
}
obj_textsec (abfd)->_raw_size += text_pad;
text_end += text_pad;
if (!obj_datasec(abfd)->user_set_vma)
{
bfd_vma vma;
vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size;
obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
}
if (abdp && abdp->zmagic_mapped_contiguous)
{
text_pad = (obj_datasec(abfd)->vma
- obj_textsec(abfd)->vma
- obj_textsec(abfd)->_raw_size);
obj_textsec(abfd)->_raw_size += text_pad;
}
obj_datasec (abfd)->filepos = (obj_textsec (abfd)->filepos
+ obj_textsec (abfd)->_raw_size);
execp->a_text = obj_textsec(abfd)->_raw_size;
if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
execp->a_text += adata(abfd).exec_bytes_size;
if (obj_aout_subformat (abfd) == q_magic_format)
N_SET_MAGIC (*execp, QMAGIC);
else
N_SET_MAGIC (*execp, ZMAGIC);
obj_datasec(abfd)->_raw_size
= align_power (obj_datasec(abfd)->_raw_size,
obj_bsssec(abfd)->alignment_power);
execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size,
adata(abfd).page_size);
data_pad = execp->a_data - obj_datasec(abfd)->_raw_size;
if (!obj_bsssec(abfd)->user_set_vma)
obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma
+ obj_datasec(abfd)->_raw_size);
if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power)
== obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size)
execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 :
obj_bsssec(abfd)->_raw_size - data_pad;
else
execp->a_bss = obj_bsssec(abfd)->_raw_size;
}
static void
adjust_n_magic (abfd, execp)
bfd *abfd;
struct internal_exec *execp;
{
file_ptr pos = adata(abfd).exec_bytes_size;
bfd_vma vma = 0;
int pad;
obj_textsec(abfd)->filepos = pos;
if (!obj_textsec(abfd)->user_set_vma)
obj_textsec(abfd)->vma = vma;
else
vma = obj_textsec(abfd)->vma;
pos += obj_textsec(abfd)->_raw_size;
vma += obj_textsec(abfd)->_raw_size;
obj_datasec(abfd)->filepos = pos;
if (!obj_datasec(abfd)->user_set_vma)
obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
vma = obj_datasec(abfd)->vma;
vma += obj_datasec(abfd)->_raw_size;
pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
obj_datasec(abfd)->_raw_size += pad;
pos += obj_datasec(abfd)->_raw_size;
if (!obj_bsssec(abfd)->user_set_vma)
obj_bsssec(abfd)->vma = vma;
else
vma = obj_bsssec(abfd)->vma;
execp->a_text = obj_textsec(abfd)->_raw_size;
execp->a_data = obj_datasec(abfd)->_raw_size;
execp->a_bss = obj_bsssec(abfd)->_raw_size;
N_SET_MAGIC (*execp, NMAGIC);
}
bfd_boolean
NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end)
bfd *abfd;
bfd_size_type *text_size;
file_ptr * text_end ATTRIBUTE_UNUSED;
{
struct internal_exec *execp = exec_hdr (abfd);
if (! NAME(aout,make_sections) (abfd))
return FALSE;
if (adata(abfd).magic != undecided_magic)
return TRUE;
obj_textsec(abfd)->_raw_size =
align_power(obj_textsec(abfd)->_raw_size,
obj_textsec(abfd)->alignment_power);
*text_size = obj_textsec (abfd)->_raw_size;
if (abfd->flags & WP_TEXT)
adata(abfd).magic = n_magic;
else
adata(abfd).magic = o_magic;
#ifdef BFD_AOUT_DEBUG
#if __GNUC__ >= 2
fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
({ char *str;
switch (adata(abfd).magic) {
case n_magic: str = "NMAGIC"; break;
case o_magic: str = "OMAGIC"; break;
case z_magic: str = "ZMAGIC"; break;
default: abort ();
}
str;
}),
obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
obj_textsec(abfd)->alignment_power,
obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
obj_datasec(abfd)->alignment_power,
obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size,
obj_bsssec(abfd)->alignment_power);
#endif
#endif
switch (adata(abfd).magic)
{
case o_magic:
adjust_o_magic (abfd, execp);
break;
case z_magic:
adjust_z_magic (abfd, execp);
break;
case n_magic:
adjust_n_magic (abfd, execp);
break;
default:
abort ();
}
#ifdef BFD_AOUT_DEBUG
fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
obj_textsec(abfd)->filepos,
obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
obj_datasec(abfd)->filepos,
obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size);
#endif
return TRUE;
}
bfd_boolean
NAME(aout,new_section_hook) (abfd, newsect)
bfd *abfd;
asection *newsect;
{
newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power;
if (bfd_get_format (abfd) == bfd_object)
{
if (obj_textsec (abfd) == NULL
&& ! strcmp (newsect->name, ".text"))
{
obj_textsec(abfd)= newsect;
newsect->target_index = N_TEXT;
return TRUE;
}
if (obj_datasec (abfd) == NULL
&& ! strcmp (newsect->name, ".data"))
{
obj_datasec (abfd) = newsect;
newsect->target_index = N_DATA;
return TRUE;
}
if (obj_bsssec (abfd) == NULL
&& !strcmp (newsect->name, ".bss"))
{
obj_bsssec (abfd) = newsect;
newsect->target_index = N_BSS;
return TRUE;
}
}
return TRUE;
}
bfd_boolean
NAME(aout,set_section_contents) (abfd, section, location, offset, count)
bfd *abfd;
sec_ptr section;
const PTR location;
file_ptr offset;
bfd_size_type count;
{
file_ptr text_end;
bfd_size_type text_size;
if (! abfd->output_has_begun)
{
if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
return FALSE;
}
if (section == obj_bsssec (abfd))
{
bfd_set_error (bfd_error_no_contents);
return FALSE;
}
if (section != obj_textsec (abfd)
&& section != obj_datasec (abfd))
{
(*_bfd_error_handler)
("%s: can not represent section `%s' in a.out object file format",
bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
}
if (count != 0)
{
if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
|| bfd_bwrite (location, count, abfd) != count)
return FALSE;
}
return TRUE;
}
static bfd_boolean
aout_get_external_symbols (abfd)
bfd *abfd;
{
if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL)
{
bfd_size_type count;
struct external_nlist *syms;
count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
#ifdef USE_MMAP
if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd),
exec_hdr (abfd)->a_syms,
&obj_aout_sym_window (abfd), TRUE))
return FALSE;
syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
#else
syms = (struct external_nlist *) bfd_malloc (count * EXTERNAL_NLIST_SIZE);
if (syms == (struct external_nlist *) NULL && count != 0)
return FALSE;
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
|| (bfd_bread (syms, exec_hdr (abfd)->a_syms, abfd)
!= exec_hdr (abfd)->a_syms))
{
free (syms);
return FALSE;
}
#endif
obj_aout_external_syms (abfd) = syms;
obj_aout_external_sym_count (abfd) = count;
}
if (obj_aout_external_strings (abfd) == NULL
&& exec_hdr (abfd)->a_syms != 0)
{
unsigned char string_chars[BYTES_IN_LONG];
bfd_size_type stringsize;
char *strings;
if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
|| (bfd_bread ((PTR) string_chars, (bfd_size_type) BYTES_IN_LONG,
abfd) != BYTES_IN_LONG))
return FALSE;
stringsize = H_GET_32 (abfd, string_chars);
#ifdef USE_MMAP
if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
&obj_aout_string_window (abfd), TRUE))
return FALSE;
strings = (char *) obj_aout_string_window (abfd).data;
#else
strings = (char *) bfd_malloc (stringsize + 1);
if (strings == NULL)
return FALSE;
if (bfd_bread (strings + 4, stringsize - 4, abfd) != stringsize - 4)
{
free (strings);
return FALSE;
}
#endif
strings[0] = '\0';
strings[stringsize - 1] = 0;
obj_aout_external_strings (abfd) = strings;
obj_aout_external_string_size (abfd) = stringsize;
}
return TRUE;
}
static bfd_boolean
translate_from_native_sym_flags (abfd, cache_ptr)
bfd *abfd;
aout_symbol_type *cache_ptr;
{
flagword visible;
if (cache_ptr->type == N_FN)
{
asection *sec;
cache_ptr->symbol.flags = BSF_DEBUGGING;
switch (cache_ptr->type & N_TYPE)
{
case N_TEXT:
case N_FN:
sec = obj_textsec (abfd);
break;
case N_DATA:
sec = obj_datasec (abfd);
break;
case N_BSS:
sec = obj_bsssec (abfd);
break;
default:
case N_ABS:
sec = bfd_abs_section_ptr;
break;
}
cache_ptr->symbol.section = sec;
cache_ptr->symbol.value -= sec->vma;
return TRUE;
}
if ((cache_ptr->type & N_EXT) == 0)
visible = BSF_LOCAL;
else
visible = BSF_GLOBAL;
switch (cache_ptr->type)
{
default:
case N_ABS: case N_ABS | N_EXT:
cache_ptr->symbol.section = bfd_abs_section_ptr;
cache_ptr->symbol.flags = visible;
break;
case N_UNDF | N_EXT:
if (cache_ptr->symbol.value != 0)
{
cache_ptr->symbol.flags = BSF_GLOBAL;
cache_ptr->symbol.section = bfd_com_section_ptr;
}
else
{
cache_ptr->symbol.flags = 0;
cache_ptr->symbol.section = bfd_und_section_ptr;
}
break;
case N_TEXT: case N_TEXT | N_EXT:
cache_ptr->symbol.section = obj_textsec (abfd);
cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
cache_ptr->symbol.flags = visible;
break;
case N_DATA: case N_DATA | N_EXT:
cache_ptr->symbol.section = obj_datasec (abfd);
cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
cache_ptr->symbol.flags = visible;
break;
case N_BSS: case N_BSS | N_EXT:
cache_ptr->symbol.section = obj_bsssec (abfd);
cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
cache_ptr->symbol.flags = visible;
break;
}
return TRUE;
}
static bfd_boolean
translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer)
bfd *abfd;
asymbol *cache_ptr;
struct external_nlist *sym_pointer;
{
bfd_vma value = cache_ptr->value;
asection *sec;
bfd_vma off;
sym_pointer->e_type[0] &= ~N_TYPE;
sec = bfd_get_section (cache_ptr);
off = 0;
if (sec == NULL)
{
(*_bfd_error_handler)
("%s: can not represent section for symbol `%s' in a.out object file format",
bfd_archive_filename (abfd),
cache_ptr->name != NULL ? cache_ptr->name : "*unknown*");
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
}
if (sec->output_section != NULL)
{
off = sec->output_offset;
sec = sec->output_section;
}
if (bfd_is_abs_section (sec))
sym_pointer->e_type[0] |= N_ABS;
else if (sec == obj_textsec (abfd))
sym_pointer->e_type[0] |= N_TEXT;
else if (sec == obj_datasec (abfd))
sym_pointer->e_type[0] |= N_DATA;
else if (sec == obj_bsssec (abfd))
sym_pointer->e_type[0] |= N_BSS;
else if (bfd_is_und_section (sec))
sym_pointer->e_type[0] = N_UNDF | N_EXT;
else if (bfd_is_com_section (sec))
sym_pointer->e_type[0] = N_UNDF | N_EXT;
else
{
(*_bfd_error_handler)
("%s: can not represent section `%s' in a.out object file format",
bfd_archive_filename (abfd), bfd_get_section_name (abfd, sec));
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
}
value += sec->vma + off;
if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
sym_pointer->e_type[0] |= N_EXT;
#if 0
if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
{
int type = ((aout_symbol_type *) cache_ptr)->type;
switch (type)
{
case N_ABS: type = N_SETA; break;
case N_TEXT: type = N_SETT; break;
case N_DATA: type = N_SETD; break;
case N_BSS: type = N_SETB; break;
}
sym_pointer->e_type[0] = type;
}
#endif
#if 0
if ((cache_ptr->flags & BSF_WEAK) != 0)
{
int type;
switch (sym_pointer->e_type[0] & N_TYPE)
{
default:
case N_ABS: type = N_WEAKA; break;
case N_TEXT: type = N_WEAKT; break;
case N_DATA: type = N_WEAKD; break;
case N_BSS: type = N_WEAKB; break;
case N_UNDF: type = N_WEAKU; break;
}
sym_pointer->e_type[0] = type;
}
#endif
PUT_WORD(abfd, value, sym_pointer->e_value);
return TRUE;
}
asymbol *
NAME(aout,make_empty_symbol) (abfd)
bfd *abfd;
{
bfd_size_type amt = sizeof (aout_symbol_type);
aout_symbol_type *new = (aout_symbol_type *) bfd_zalloc (abfd, amt);
if (!new)
return NULL;
new->symbol.the_bfd = abfd;
return &new->symbol;
}
bfd_boolean
NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
bfd *abfd;
aout_symbol_type *in;
struct external_nlist *ext;
bfd_size_type count;
char *str;
bfd_size_type strsize;
bfd_boolean dynamic;
{
struct external_nlist *ext_end;
ext_end = ext + count;
for (; ext < ext_end; ext++, in++)
{
bfd_vma x;
x = GET_WORD (abfd, ext->e_strx);
in->symbol.the_bfd = abfd;
if (x == 0 && ! dynamic)
in->symbol.name = "";
else if (x < strsize)
in->symbol.name = str + x;
else
return FALSE;
in->symbol.value = GET_SWORD (abfd, ext->e_value);
in->desc = 0;
in->other = 0;
in->type = H_GET_8 (abfd, ext->e_type);
in->symbol.udata.p = NULL;
if (! translate_from_native_sym_flags (abfd, in))
return FALSE;
if (dynamic)
in->symbol.flags |= BSF_DYNAMIC;
}
return TRUE;
}
bfd_boolean
NAME(aout,slurp_symbol_table) (abfd)
bfd *abfd;
{
struct external_nlist *old_external_syms;
aout_symbol_type *cached;
bfd_size_type cached_size;
if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
return TRUE;
old_external_syms = obj_aout_external_syms (abfd);
if (! aout_get_external_symbols (abfd))
return FALSE;
cached_size = obj_aout_external_sym_count (abfd);
cached_size *= sizeof (aout_symbol_type);
cached = (aout_symbol_type *) bfd_zmalloc (cached_size);
if (cached == NULL && cached_size != 0)
return FALSE;
if (! (NAME(aout,translate_symbol_table)
(abfd, cached,
obj_aout_external_syms (abfd),
obj_aout_external_sym_count (abfd),
obj_aout_external_strings (abfd),
obj_aout_external_string_size (abfd),
FALSE)))
{
free (cached);
return FALSE;
}
bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
obj_aout_symbols (abfd) = cached;
if (old_external_syms == (struct external_nlist *) NULL
&& obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
{
#ifdef USE_MMAP
bfd_free_window (&obj_aout_sym_window (abfd));
#else
free (obj_aout_external_syms (abfd));
#endif
obj_aout_external_syms (abfd) = NULL;
}
return TRUE;
}
static bfd_size_type add_to_stringtab
PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, bfd_boolean));
static bfd_boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *));
static INLINE bfd_size_type
add_to_stringtab (abfd, tab, str, copy)
bfd *abfd;
struct bfd_strtab_hash *tab;
const char *str;
bfd_boolean copy;
{
bfd_boolean hash;
bfd_size_type index;
if (str == 0 || *str == '\0')
return 0;
hash = TRUE;
if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
hash = FALSE;
index = _bfd_stringtab_add (tab, str, hash, copy);
if (index != (bfd_size_type) -1)
{
index += BYTES_IN_LONG;
}
return index;
}
static bfd_boolean
emit_stringtab (abfd, tab)
register bfd *abfd;
struct bfd_strtab_hash *tab;
{
bfd_byte buffer[BYTES_IN_LONG];
H_PUT_32 (abfd, _bfd_stringtab_size (tab) + BYTES_IN_LONG, buffer);
if (bfd_bwrite ((PTR) buffer, (bfd_size_type) BYTES_IN_LONG, abfd)
!= BYTES_IN_LONG)
return FALSE;
return _bfd_stringtab_emit (abfd, tab);
}
bfd_boolean
NAME(aout,write_syms) (abfd)
bfd *abfd;
{
unsigned int count ;
asymbol **generic = bfd_get_outsymbols (abfd);
struct bfd_strtab_hash *strtab;
strtab = _bfd_stringtab_init ();
if (strtab == NULL)
return FALSE;
for (count = 0; count < bfd_get_symcount (abfd); count++)
{
asymbol *g = generic[count];
bfd_size_type indx;
struct external_nlist nsp;
PUT_WORD (abfd, 0, nsp.e_unused);
indx = add_to_stringtab (abfd, strtab, g->name, FALSE);
if (indx == (bfd_size_type) -1)
goto error_return;
PUT_WORD (abfd, indx, nsp.e_strx);
if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
H_PUT_8 (abfd, aout_symbol(g)->type, nsp.e_type);
else
H_PUT_8 (abfd, 0, nsp.e_type);
if (! translate_to_native_sym_flags (abfd, g, &nsp))
goto error_return;
H_PUT_8 (abfd, 0, nsp.e_ovly);
if (bfd_bwrite ((PTR)&nsp, (bfd_size_type) EXTERNAL_NLIST_SIZE, abfd)
!= EXTERNAL_NLIST_SIZE)
goto error_return;
g->KEEPIT = count;
}
if (! emit_stringtab (abfd, strtab))
goto error_return;
_bfd_stringtab_free (strtab);
return TRUE;
error_return:
_bfd_stringtab_free (strtab);
return FALSE;
}
long
NAME(aout,canonicalize_symtab) (abfd, location)
bfd *abfd;
asymbol **location;
{
unsigned int counter = 0;
aout_symbol_type *symbase;
if (!NAME(aout,slurp_symbol_table)(abfd))
return -1;
for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
*(location++) = (asymbol *)( symbase++);
*location++ =0;
return bfd_get_symcount (abfd);
}
void
pdp11_aout_swap_reloc_out (abfd, g, natptr)
bfd *abfd;
arelent *g;
register struct pdp11_aout_reloc_external *natptr;
{
int r_index;
int r_pcrel;
int reloc_entry;
int r_type;
asymbol *sym = *(g->sym_ptr_ptr);
asection *output_section = sym->section->output_section;
if (g->addend != 0)
fprintf (stderr, "BFD: can't do this reloc addend stuff\n");
r_pcrel = g->howto->pc_relative;
if (bfd_is_abs_section (output_section))
r_type = RABS;
else if (output_section == obj_textsec (abfd))
r_type = RTEXT;
else if (output_section == obj_datasec (abfd))
r_type = RDATA;
else if (output_section == obj_bsssec (abfd))
r_type = RBSS;
else if (bfd_is_und_section (output_section))
r_type = REXT;
else if (bfd_is_com_section (output_section))
r_type = REXT;
else
r_type = -1;
BFD_ASSERT (r_type != -1);
if (r_type == RABS)
r_index = 0;
else
r_index = (*(g->sym_ptr_ptr))->KEEPIT;
#if 0
if (bfd_is_abs_section (bfd_get_section (sym)))
{
r_extern = 0;
r_index = N_ABS;
r_type = RABS;
}
else if ((sym->flags & BSF_SECTION_SYM) == 0)
{
if (bfd_is_und_section (bfd_get_section (sym))
|| (sym->flags & BSF_GLOBAL) != 0)
r_extern = 1;
else
r_extern = 0;
r_index = (*(g->sym_ptr_ptr))->KEEPIT;
}
else
{
r_extern = 0;
r_index = output_section->target_index;
}
#endif
reloc_entry = r_index << 4 | r_type | r_pcrel;
PUT_WORD (abfd, reloc_entry, natptr->e_reloc_entry);
}
#define MOVE_ADDRESS(ad) \
if (r_extern) \
{ \
\
cache_ptr->sym_ptr_ptr = symbols + r_index; \
cache_ptr->addend = ad; \
} \
else \
{ \
\
switch (r_index) \
{ \
case N_TEXT: \
case N_TEXT | N_EXT: \
cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; \
cache_ptr->addend = ad - su->textsec->vma; \
break; \
case N_DATA: \
case N_DATA | N_EXT: \
cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; \
cache_ptr->addend = ad - su->datasec->vma; \
break; \
case N_BSS: \
case N_BSS | N_EXT: \
cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; \
cache_ptr->addend = ad - su->bsssec->vma; \
break; \
default: \
case N_ABS: \
case N_ABS | N_EXT: \
cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
cache_ptr->addend = ad; \
break; \
} \
}
void
pdp11_aout_swap_reloc_in (abfd, bytes, cache_ptr, offset,
symbols, symcount)
bfd *abfd;
struct pdp11_aout_reloc_external *bytes;
arelent *cache_ptr;
bfd_size_type offset;
asymbol **symbols;
bfd_size_type symcount;
{
struct aoutdata *su = &(abfd->tdata.aout_data->a);
unsigned int r_index;
int reloc_entry;
int r_extern;
int r_pcrel;
reloc_entry = GET_WORD (abfd, (PTR)bytes);
r_pcrel = reloc_entry & RELFLG;
cache_ptr->address = offset;
cache_ptr->howto = howto_table_pdp11 + (r_pcrel ? 1 : 0);
if ((reloc_entry & RTYPE) == RABS)
r_index = N_ABS;
else
r_index = RINDEX (reloc_entry);
r_extern = (reloc_entry & RTYPE) == REXT;
if (r_extern && r_index > symcount)
{
r_extern = 0;
r_index = N_ABS;
}
MOVE_ADDRESS(0);
}
bfd_boolean
NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
bfd *abfd;
sec_ptr asect;
asymbol **symbols;
{
struct pdp11_aout_reloc_external *rptr;
bfd_size_type count;
bfd_size_type reloc_size;
PTR relocs;
arelent *reloc_cache;
size_t each_size;
unsigned int counter = 0;
arelent *cache_ptr;
if (asect->relocation)
return TRUE;
if (asect->flags & SEC_CONSTRUCTOR)
return TRUE;
if (asect == obj_datasec (abfd))
reloc_size = exec_hdr(abfd)->a_drsize;
else if (asect == obj_textsec (abfd))
reloc_size = exec_hdr(abfd)->a_trsize;
else if (asect == obj_bsssec (abfd))
reloc_size = 0;
else
{
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
return FALSE;
each_size = obj_reloc_entry_size (abfd);
relocs = bfd_malloc (reloc_size);
if (relocs == NULL && reloc_size != 0)
return FALSE;
if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
{
free (relocs);
return FALSE;
}
count = reloc_size / each_size;
{
unsigned int real_count = 0;
for (counter = 0; counter < count; counter++)
{
int x;
x = GET_WORD (abfd, (char *) relocs + each_size * counter);
if (x != 0)
real_count++;
}
count = real_count;
}
reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
if (reloc_cache == NULL && count != 0)
return FALSE;
cache_ptr = reloc_cache;
rptr = (struct pdp11_aout_reloc_external *) relocs;
for (counter = 0;
counter < count;
counter++, ((char *)rptr) += RELOC_SIZE, cache_ptr++)
{
while (GET_WORD (abfd, (PTR)rptr) == 0)
{
rptr =
(struct pdp11_aout_reloc_external *)
((char *) rptr + RELOC_SIZE);
if ((char *) rptr >= (char *) relocs + reloc_size)
goto done;
}
pdp11_aout_swap_reloc_in (abfd, rptr, cache_ptr,
(bfd_size_type) ((char *) rptr - (char *) relocs),
symbols,
(bfd_size_type) bfd_get_symcount (abfd));
}
done:
BFD_ASSERT (counter == count);
free (relocs);
asect->relocation = reloc_cache;
asect->reloc_count = cache_ptr - reloc_cache;
return TRUE;
}
bfd_boolean
NAME(aout,squirt_out_relocs) (abfd, section)
bfd *abfd;
asection *section;
{
arelent **generic;
unsigned char *native;
unsigned int count = section->reloc_count;
bfd_size_type natsize;
#if 0
if ((count == 0 || section->orelocation == NULL) &&
<writing_executable>)
return TRUE;
#endif
natsize = bfd_get_section_size_before_reloc (section);
native = (unsigned char *) bfd_zalloc (abfd, natsize);
if (!native)
return FALSE;
generic = section->orelocation;
if (generic != NULL)
{
while (count > 0)
{
struct pdp11_aout_reloc_external *r;
r = (struct pdp11_aout_reloc_external *)
(native + (*generic)->address);
pdp11_aout_swap_reloc_out (abfd, *generic, r);
count--;
generic++;
}
}
if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
{
bfd_release (abfd, native);
return FALSE;
}
bfd_release (abfd, native);
return TRUE;
}
long
NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
bfd *abfd;
sec_ptr section;
arelent **relptr;
asymbol **symbols;
{
arelent *tblptr = section->relocation;
unsigned int count;
if (section == obj_bsssec (abfd))
{
*relptr = NULL;
return 0;
}
if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
return -1;
if (section->flags & SEC_CONSTRUCTOR)
{
arelent_chain *chain = section->constructor_chain;
for (count = 0; count < section->reloc_count; count ++)
{
*relptr ++ = &chain->relent;
chain = chain->next;
}
}
else
{
tblptr = section->relocation;
for (count = 0; count++ < section->reloc_count;)
*relptr++ = tblptr++;
}
*relptr = 0;
return section->reloc_count;
}
long
NAME(aout,get_reloc_upper_bound) (abfd, asect)
bfd *abfd;
sec_ptr asect;
{
if (bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
if (asect->flags & SEC_CONSTRUCTOR)
return (sizeof (arelent *) * (asect->reloc_count+1));
if (asect == obj_datasec (abfd))
return (sizeof (arelent *)
* ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
+ 1));
if (asect == obj_textsec (abfd))
return (sizeof (arelent *)
* ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
+ 1));
if (asect == obj_bsssec (abfd))
return sizeof (arelent *);
if (asect == obj_bsssec (abfd))
return 0;
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
long
NAME(aout,get_symtab_upper_bound) (abfd)
bfd *abfd;
{
if (!NAME(aout,slurp_symbol_table)(abfd))
return -1;
return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
}
alent *
NAME(aout,get_lineno) (abfd, symbol)
bfd * abfd ATTRIBUTE_UNUSED;
asymbol * symbol ATTRIBUTE_UNUSED;
{
return (alent *)NULL;
}
void
NAME(aout,get_symbol_info) (abfd, symbol, ret)
bfd * abfd ATTRIBUTE_UNUSED;
asymbol *symbol;
symbol_info *ret;
{
bfd_symbol_info (symbol, ret);
if (ret->type == '?')
{
int type_code = aout_symbol(symbol)->type & 0xff;
const char *stab_name = bfd_get_stab_name (type_code);
static char buf[10];
if (stab_name == NULL)
{
sprintf(buf, "(%d)", type_code);
stab_name = buf;
}
ret->type = '-';
ret->stab_type = type_code;
ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
ret->stab_name = stab_name;
}
}
void
NAME(aout,print_symbol) (abfd, afile, symbol, how)
bfd * abfd;
PTR afile;
asymbol *symbol;
bfd_print_symbol_type how;
{
FILE *file = (FILE *)afile;
switch (how)
{
case bfd_print_symbol_name:
if (symbol->name)
fprintf(file,"%s", symbol->name);
break;
case bfd_print_symbol_more:
fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
(unsigned)(aout_symbol(symbol)->other & 0xff),
(unsigned)(aout_symbol(symbol)->type));
break;
case bfd_print_symbol_all:
{
const char *section_name = symbol->section->name;
bfd_print_symbol_vandf (abfd, (PTR)file, symbol);
fprintf (file," %-5s %04x %02x %02x",
section_name,
(unsigned)(aout_symbol(symbol)->desc & 0xffff),
(unsigned)(aout_symbol(symbol)->other & 0xff),
(unsigned)(aout_symbol(symbol)->type & 0xff));
if (symbol->name)
fprintf(file," %s", symbol->name);
}
break;
}
}
#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
long
NAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep)
bfd *abfd;
bfd_boolean dynamic;
PTR *minisymsp;
unsigned int *sizep;
{
if (dynamic)
{
return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
}
if (! aout_get_external_symbols (abfd))
return -1;
if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
*minisymsp = (PTR) obj_aout_external_syms (abfd);
obj_aout_external_syms (abfd) = NULL;
*sizep = EXTERNAL_NLIST_SIZE;
return obj_aout_external_sym_count (abfd);
}
asymbol *
NAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym)
bfd *abfd;
bfd_boolean dynamic;
const PTR minisym;
asymbol *sym;
{
if (dynamic
|| obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
memset (sym, 0, sizeof (aout_symbol_type));
if (! (NAME(aout,translate_symbol_table)
(abfd,
(aout_symbol_type *) sym,
(struct external_nlist *) minisym,
(bfd_size_type) 1,
obj_aout_external_strings (abfd),
obj_aout_external_string_size (abfd),
FALSE)))
return NULL;
return sym;
}
bfd_boolean
NAME(aout,find_nearest_line)
(abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr)
bfd *abfd;
asection *section;
asymbol **symbols;
bfd_vma offset;
const char **filename_ptr;
const char **functionname_ptr;
unsigned int *line_ptr;
{
asymbol **p;
const char *directory_name = NULL;
const char *main_file_name = NULL;
const char *current_file_name = NULL;
const char *line_file_name = NULL;
bfd_vma low_line_vma = 0;
bfd_vma low_func_vma = 0;
asymbol *func = 0;
size_t filelen, funclen;
char *buf;
*filename_ptr = abfd->filename;
*functionname_ptr = 0;
*line_ptr = 0;
if (symbols != (asymbol **)NULL)
{
for (p = symbols; *p; p++)
{
aout_symbol_type *q = (aout_symbol_type *)(*p);
next:
switch (q->type)
{
case N_TEXT:
if (q->symbol.value <= offset
&& ((q->symbol.value > low_line_vma
&& (line_file_name != NULL
|| *line_ptr != 0))
|| (q->symbol.value > low_func_vma
&& func != NULL)))
{
const char * symname;
symname = q->symbol.name;
if (strcmp (symname + strlen (symname) - 2, ".o") == 0)
{
if (q->symbol.value > low_line_vma)
{
*line_ptr = 0;
line_file_name = NULL;
}
if (q->symbol.value > low_func_vma)
func = NULL;
}
}
break;
case N_SO:
if (q->symbol.value <= offset)
{
if (q->symbol.value > low_line_vma)
{
*line_ptr = 0;
line_file_name = NULL;
}
if (q->symbol.value > low_func_vma)
func = NULL;
}
main_file_name = current_file_name = q->symbol.name;
p++;
if (*p == NULL)
break;
q = (aout_symbol_type *)(*p);
if (q->type != (int)N_SO)
goto next;
directory_name = current_file_name;
main_file_name = current_file_name = q->symbol.name;
if (obj_textsec(abfd) != section)
goto done;
break;
case N_SOL:
current_file_name = q->symbol.name;
break;
case N_SLINE:
case N_DSLINE:
case N_BSLINE:
if (q->symbol.value >= low_line_vma
&& q->symbol.value <= offset)
{
*line_ptr = q->desc;
low_line_vma = q->symbol.value;
line_file_name = current_file_name;
}
break;
case N_FUN:
{
if (q->symbol.value >= low_func_vma &&
q->symbol.value <= offset)
{
low_func_vma = q->symbol.value;
func = (asymbol *)q;
}
else if (q->symbol.value > offset)
goto done;
}
break;
}
}
}
done:
if (*line_ptr != 0)
main_file_name = line_file_name;
if (main_file_name == NULL
|| main_file_name[0] == '/'
|| directory_name == NULL)
filelen = 0;
else
filelen = strlen (directory_name) + strlen (main_file_name);
if (func == NULL)
funclen = 0;
else
funclen = strlen (bfd_asymbol_name (func));
if (adata (abfd).line_buf != NULL)
free (adata (abfd).line_buf);
if (filelen + funclen == 0)
adata (abfd).line_buf = buf = NULL;
else
{
buf = (char *) bfd_malloc ((bfd_size_type) filelen + funclen + 3);
adata (abfd).line_buf = buf;
if (buf == NULL)
return FALSE;
}
if (main_file_name != NULL)
{
if (main_file_name[0] == '/' || directory_name == NULL)
*filename_ptr = main_file_name;
else
{
sprintf (buf, "%s%s", directory_name, main_file_name);
*filename_ptr = buf;
buf += filelen + 1;
}
}
if (func)
{
const char *function = func->name;
char *colon;
if (bfd_get_symbol_leading_char (abfd) == '\0')
strcpy (buf, function);
else
{
buf[0] = bfd_get_symbol_leading_char (abfd);
strcpy (buf + 1, function);
}
colon = strchr (buf, ':');
if (colon != NULL)
*colon = '\0';
*functionname_ptr = buf;
}
return TRUE;
}
int
NAME(aout,sizeof_headers) (abfd, execable)
bfd *abfd;
bfd_boolean execable ATTRIBUTE_UNUSED;
{
return adata(abfd).exec_bytes_size;
}
bfd_boolean
NAME(aout,bfd_free_cached_info) (abfd)
bfd *abfd;
{
asection *o;
if (bfd_get_format (abfd) != bfd_object)
return TRUE;
#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; }
BFCI_FREE (obj_aout_symbols (abfd));
#ifdef USE_MMAP
obj_aout_external_syms (abfd) = 0;
bfd_free_window (&obj_aout_sym_window (abfd));
bfd_free_window (&obj_aout_string_window (abfd));
obj_aout_external_strings (abfd) = 0;
#else
BFCI_FREE (obj_aout_external_syms (abfd));
BFCI_FREE (obj_aout_external_strings (abfd));
#endif
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
BFCI_FREE (o->relocation);
#undef BFCI_FREE
return TRUE;
}
static bfd_boolean aout_link_add_object_symbols
PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean aout_link_check_archive_element
PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *));
static bfd_boolean aout_link_free_symbols PARAMS ((bfd *));
static bfd_boolean aout_link_check_ar_symbols
PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
static bfd_boolean aout_link_add_symbols
PARAMS ((bfd *, struct bfd_link_info *));
struct bfd_hash_entry *
NAME(aout,link_hash_newfunc) (entry, table, string)
struct bfd_hash_entry *entry;
struct bfd_hash_table *table;
const char *string;
{
struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry;
if (ret == (struct aout_link_hash_entry *) NULL)
ret = ((struct aout_link_hash_entry *)
bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
if (ret == (struct aout_link_hash_entry *) NULL)
return (struct bfd_hash_entry *) ret;
ret = ((struct aout_link_hash_entry *)
_bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
if (ret)
{
ret->written = FALSE;
ret->indx = -1;
}
return (struct bfd_hash_entry *) ret;
}
bfd_boolean
NAME(aout,link_hash_table_init) (table, abfd, newfunc)
struct aout_link_hash_table *table;
bfd *abfd;
struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *));
{
return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
}
struct bfd_link_hash_table *
NAME(aout,link_hash_table_create) (abfd)
bfd *abfd;
{
struct aout_link_hash_table *ret;
bfd_size_type amt = sizeof (struct aout_link_hash_table);
ret = ((struct aout_link_hash_table *) bfd_alloc (abfd, amt));
if (ret == NULL)
return (struct bfd_link_hash_table *) NULL;
if (! NAME(aout,link_hash_table_init) (ret, abfd,
NAME(aout,link_hash_newfunc)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
}
return &ret->root;
}
bfd_boolean
NAME(aout,link_add_symbols) (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
switch (bfd_get_format (abfd))
{
case bfd_object:
return aout_link_add_object_symbols (abfd, info);
case bfd_archive:
return _bfd_generic_link_add_archive_symbols
(abfd, info, aout_link_check_archive_element);
default:
bfd_set_error (bfd_error_wrong_format);
return FALSE;
}
}
static bfd_boolean
aout_link_add_object_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
if (! aout_get_external_symbols (abfd))
return FALSE;
if (! aout_link_add_symbols (abfd, info))
return FALSE;
if (! info->keep_memory)
{
if (! aout_link_free_symbols (abfd))
return FALSE;
}
return TRUE;
}
static bfd_boolean
aout_link_check_archive_element (abfd, info, pneeded)
bfd *abfd;
struct bfd_link_info *info;
bfd_boolean *pneeded;
{
if (! aout_get_external_symbols (abfd))
return FALSE;
if (! aout_link_check_ar_symbols (abfd, info, pneeded))
return FALSE;
if (*pneeded)
{
if (! aout_link_add_symbols (abfd, info))
return FALSE;
}
if (! info->keep_memory || ! *pneeded)
{
if (! aout_link_free_symbols (abfd))
return FALSE;
}
return TRUE;
}
static bfd_boolean
aout_link_free_symbols (abfd)
bfd *abfd;
{
if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
{
#ifdef USE_MMAP
bfd_free_window (&obj_aout_sym_window (abfd));
#else
free ((PTR) obj_aout_external_syms (abfd));
#endif
obj_aout_external_syms (abfd) = (struct external_nlist *) NULL;
}
if (obj_aout_external_strings (abfd) != (char *) NULL)
{
#ifdef USE_MMAP
bfd_free_window (&obj_aout_string_window (abfd));
#else
free ((PTR) obj_aout_external_strings (abfd));
#endif
obj_aout_external_strings (abfd) = (char *) NULL;
}
return TRUE;
}
static bfd_boolean
aout_link_check_ar_symbols (abfd, info, pneeded)
bfd *abfd;
struct bfd_link_info *info;
bfd_boolean *pneeded;
{
register struct external_nlist *p;
struct external_nlist *pend;
char *strings;
*pneeded = FALSE;
p = obj_aout_external_syms (abfd);
pend = p + obj_aout_external_sym_count (abfd);
strings = obj_aout_external_strings (abfd);
for (; p < pend; p++)
{
int type = H_GET_8 (abfd, p->e_type);
const char *name;
struct bfd_link_hash_entry *h;
if ((type & N_EXT) == 0
|| type == N_FN)
continue;
name = strings + GET_WORD (abfd, p->e_strx);
h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL
|| (h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common))
continue;
if (type == (N_TEXT | N_EXT)
|| type == (N_DATA | N_EXT)
|| type == (N_BSS | N_EXT)
|| type == (N_ABS | N_EXT))
{
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
return FALSE;
*pneeded = TRUE;
return TRUE;
}
if (type == (N_UNDF | N_EXT))
{
bfd_vma value;
value = GET_WORD (abfd, p->e_value);
if (value != 0)
{
if (h->type == bfd_link_hash_undefined)
{
bfd *symbfd;
unsigned int power;
symbfd = h->u.undef.abfd;
if (symbfd == (bfd *) NULL)
{
if (! (*info->callbacks->add_archive_element) (info,
abfd,
name))
return FALSE;
*pneeded = TRUE;
return TRUE;
}
h->type = bfd_link_hash_common;
h->u.c.p = ((struct bfd_link_hash_common_entry *)
bfd_hash_allocate (&info->hash->table,
sizeof (struct bfd_link_hash_common_entry)));
if (h->u.c.p == NULL)
return FALSE;
h->u.c.size = value;
power = bfd_log2 (value);
if (power > bfd_get_arch_info (abfd)->section_align_power)
power = bfd_get_arch_info (abfd)->section_align_power;
h->u.c.p->alignment_power = power;
h->u.c.p->section = bfd_make_section_old_way (symbfd,
"COMMON");
}
else
{
if (value > h->u.c.size)
h->u.c.size = value;
}
}
}
}
return TRUE;
}
static bfd_boolean
aout_link_add_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
bfd_boolean (*add_one_symbol)
PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
bfd_vma, const char *, bfd_boolean, bfd_boolean,
struct bfd_link_hash_entry **));
struct external_nlist *syms;
bfd_size_type sym_count;
char *strings;
bfd_boolean copy;
struct aout_link_hash_entry **sym_hash;
register struct external_nlist *p;
struct external_nlist *pend;
syms = obj_aout_external_syms (abfd);
sym_count = obj_aout_external_sym_count (abfd);
strings = obj_aout_external_strings (abfd);
if (info->keep_memory)
copy = FALSE;
else
copy = TRUE;
if (aout_backend_info (abfd)->add_dynamic_symbols != NULL)
{
if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
(abfd, info, &syms, &sym_count, &strings)))
return FALSE;
}
sym_hash = ((struct aout_link_hash_entry **)
bfd_alloc (abfd,
sym_count * sizeof (struct aout_link_hash_entry *)));
if (sym_hash == NULL && sym_count != 0)
return FALSE;
obj_aout_sym_hashes (abfd) = sym_hash;
add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
if (add_one_symbol == NULL)
add_one_symbol = _bfd_generic_link_add_one_symbol;
p = syms;
pend = p + sym_count;
for (; p < pend; p++, sym_hash++)
{
int type;
const char *name;
bfd_vma value;
asection *section;
flagword flags;
const char *string;
*sym_hash = NULL;
type = H_GET_8 (abfd, p->e_type);
#if 0
if ((type & N_STAB) != 0)
continue;
#endif
name = strings + GET_WORD (abfd, p->e_strx);
value = GET_WORD (abfd, p->e_value);
flags = BSF_GLOBAL;
string = NULL;
switch (type)
{
default:
abort ();
case N_UNDF:
case N_ABS:
case N_TEXT:
case N_DATA:
case N_BSS:
case N_REG:
case N_FN:
continue;
case N_UNDF | N_EXT:
if (value == 0)
{
section = bfd_und_section_ptr;
flags = 0;
}
else
section = bfd_com_section_ptr;
break;
case N_ABS | N_EXT:
section = bfd_abs_section_ptr;
break;
case N_TEXT | N_EXT:
section = obj_textsec (abfd);
value -= bfd_get_section_vma (abfd, section);
break;
case N_DATA | N_EXT:
section = obj_datasec (abfd);
value -= bfd_get_section_vma (abfd, section);
break;
case N_BSS | N_EXT:
section = obj_bsssec (abfd);
value -= bfd_get_section_vma (abfd, section);
break;
}
if (! ((*add_one_symbol)
(info, abfd, name, flags, section, value, string, copy, FALSE,
(struct bfd_link_hash_entry **) sym_hash)))
return FALSE;
if ((*sym_hash)->root.type == bfd_link_hash_common
&& ((*sym_hash)->root.u.c.p->alignment_power >
bfd_get_arch_info (abfd)->section_align_power))
(*sym_hash)->root.u.c.p->alignment_power =
bfd_get_arch_info (abfd)->section_align_power;
if ((*sym_hash)->root.type == bfd_link_hash_new)
{
BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
*sym_hash = NULL;
}
}
return TRUE;
}
struct aout_link_includes_table
{
struct bfd_hash_table root;
};
struct aout_link_includes_totals
{
struct aout_link_includes_totals *next;
bfd_vma total;
};
struct aout_link_includes_entry
{
struct bfd_hash_entry root;
struct aout_link_includes_totals *totals;
};
#define aout_link_includes_lookup(table, string, create, copy) \
((struct aout_link_includes_entry *) \
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
struct aout_final_link_info
{
struct bfd_link_info *info;
bfd *output_bfd;
file_ptr treloff, dreloff;
file_ptr symoff;
struct bfd_strtab_hash *strtab;
struct aout_link_includes_table includes;
bfd_byte *contents;
PTR relocs;
int *symbol_map;
struct external_nlist *output_syms;
};
static struct bfd_hash_entry *aout_link_includes_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static bfd_boolean aout_link_input_bfd
PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
static bfd_boolean aout_link_write_symbols
PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
static bfd_boolean aout_link_write_other_symbol
PARAMS ((struct aout_link_hash_entry *, PTR));
static bfd_boolean aout_link_input_section
PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
asection *input_section, file_ptr *reloff_ptr,
bfd_size_type rel_size));
static INLINE asection *aout_reloc_type_to_section
PARAMS ((bfd *, int));
static bfd_boolean aout_link_reloc_link_order
PARAMS ((struct aout_final_link_info *, asection *,
struct bfd_link_order *));
static bfd_boolean pdp11_aout_link_input_section
PARAMS ((struct aout_final_link_info *finfo,
bfd *input_bfd,
asection *input_section,
struct pdp11_aout_reloc_external *relocs,
bfd_size_type rel_size,
bfd_byte *contents));
static struct bfd_hash_entry *
aout_link_includes_newfunc (entry, table, string)
struct bfd_hash_entry *entry;
struct bfd_hash_table *table;
const char *string;
{
struct aout_link_includes_entry *ret =
(struct aout_link_includes_entry *) entry;
if (ret == (struct aout_link_includes_entry *) NULL)
ret = ((struct aout_link_includes_entry *)
bfd_hash_allocate (table,
sizeof (struct aout_link_includes_entry)));
if (ret == (struct aout_link_includes_entry *) NULL)
return (struct bfd_hash_entry *) ret;
ret = ((struct aout_link_includes_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
if (ret)
{
ret->totals = NULL;
}
return (struct bfd_hash_entry *) ret;
}
bfd_boolean
NAME(aout,final_link) (abfd, info, callback)
bfd *abfd;
struct bfd_link_info *info;
void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
{
struct aout_final_link_info aout_info;
bfd_boolean includes_hash_initialized = FALSE;
register bfd *sub;
bfd_size_type trsize, drsize;
bfd_size_type max_contents_size;
bfd_size_type max_relocs_size;
bfd_size_type max_sym_count;
bfd_size_type text_size;
file_ptr text_end;
register struct bfd_link_order *p;
asection *o;
bfd_boolean have_link_order_relocs;
if (info->shared)
abfd->flags |= DYNAMIC;
aout_info.info = info;
aout_info.output_bfd = abfd;
aout_info.contents = NULL;
aout_info.relocs = NULL;
aout_info.symbol_map = NULL;
aout_info.output_syms = NULL;
if (! bfd_hash_table_init_n (&aout_info.includes.root,
aout_link_includes_newfunc,
251))
goto error_return;
includes_hash_initialized = TRUE;
trsize = 0;
drsize = 0;
max_contents_size = 0;
max_relocs_size = 0;
max_sym_count = 0;
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
size_t sz;
if (info->relocatable)
{
if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
{
trsize += exec_hdr (sub)->a_trsize;
drsize += exec_hdr (sub)->a_drsize;
}
else
{
(*_bfd_error_handler)
("%s: relocatable link from %s to %s not supported",
bfd_get_filename (abfd),
sub->xvec->name, abfd->xvec->name);
bfd_set_error (bfd_error_invalid_operation);
goto error_return;
}
}
if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
{
sz = bfd_section_size (sub, obj_textsec (sub));
if (sz > max_contents_size)
max_contents_size = sz;
sz = bfd_section_size (sub, obj_datasec (sub));
if (sz > max_contents_size)
max_contents_size = sz;
sz = exec_hdr (sub)->a_trsize;
if (sz > max_relocs_size)
max_relocs_size = sz;
sz = exec_hdr (sub)->a_drsize;
if (sz > max_relocs_size)
max_relocs_size = sz;
sz = obj_aout_external_sym_count (sub);
if (sz > max_sym_count)
max_sym_count = sz;
}
}
if (info->relocatable)
{
if (obj_textsec (abfd) != (asection *) NULL)
trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
->link_order_head)
* obj_reloc_entry_size (abfd));
if (obj_datasec (abfd) != (asection *) NULL)
drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
->link_order_head)
* obj_reloc_entry_size (abfd));
}
exec_hdr (abfd)->a_trsize = trsize;
exec_hdr (abfd)->a_drsize = drsize;
exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
goto error_return;
(*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
&aout_info.symoff);
obj_textsec (abfd)->rel_filepos = aout_info.treloff;
obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
obj_sym_filepos (abfd) = aout_info.symoff;
obj_aout_external_sym_count (abfd) = 0;
aout_info.strtab = _bfd_stringtab_init ();
if (aout_info.strtab == NULL)
goto error_return;
aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size);
aout_info.relocs = (PTR) bfd_malloc (max_relocs_size);
aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *));
aout_info.output_syms = ((struct external_nlist *)
bfd_malloc ((max_sym_count + 1)
* sizeof (struct external_nlist)));
if ((aout_info.contents == NULL && max_contents_size != 0)
|| (aout_info.relocs == NULL && max_relocs_size != 0)
|| (aout_info.symbol_map == NULL && max_sym_count != 0)
|| aout_info.output_syms == NULL)
goto error_return;
{
struct aout_link_hash_entry *h;
h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
FALSE, FALSE, FALSE);
if (h != NULL)
aout_link_write_other_symbol (h, &aout_info);
}
for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
sub->output_has_begun = FALSE;
for (o = abfd->sections; o != NULL; o = o->next)
{
for (p = o->link_order_head; p != NULL; p = p->next)
{
if (p->type == bfd_indirect_link_order)
p->u.indirect.section->linker_mark = TRUE;
}
}
have_link_order_relocs = FALSE;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL;
p = p->next)
{
if (p->type == bfd_indirect_link_order
&& (bfd_get_flavour (p->u.indirect.section->owner)
== bfd_target_aout_flavour))
{
bfd *input_bfd;
input_bfd = p->u.indirect.section->owner;
if (! input_bfd->output_has_begun)
{
if (! aout_link_input_bfd (&aout_info, input_bfd))
goto error_return;
input_bfd->output_has_begun = TRUE;
}
}
else if (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order)
{
have_link_order_relocs = TRUE;
}
else
{
if (! _bfd_default_link_order (abfd, info, o, p))
goto error_return;
}
}
}
aout_link_hash_traverse (aout_hash_table (info),
aout_link_write_other_symbol,
(PTR) &aout_info);
if (have_link_order_relocs)
{
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL;
p = p->next)
{
if (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order)
{
if (! aout_link_reloc_link_order (&aout_info, o, p))
goto error_return;
}
}
}
}
if (aout_info.contents != NULL)
{
free (aout_info.contents);
aout_info.contents = NULL;
}
if (aout_info.relocs != NULL)
{
free (aout_info.relocs);
aout_info.relocs = NULL;
}
if (aout_info.symbol_map != NULL)
{
free (aout_info.symbol_map);
aout_info.symbol_map = NULL;
}
if (aout_info.output_syms != NULL)
{
free (aout_info.output_syms);
aout_info.output_syms = NULL;
}
if (includes_hash_initialized)
{
bfd_hash_table_free (&aout_info.includes.root);
includes_hash_initialized = FALSE;
}
if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
{
if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
goto error_return;
}
abfd->symcount = obj_aout_external_sym_count (abfd);
exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms;
obj_textsec (abfd)->reloc_count =
exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
obj_datasec (abfd)->reloc_count =
exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
if (abfd->symcount > 0)
{
if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
|| ! emit_stringtab (abfd, aout_info.strtab))
goto error_return;
}
else if (obj_textsec (abfd)->reloc_count == 0
&& obj_datasec (abfd)->reloc_count == 0)
{
bfd_byte b;
b = 0;
if (bfd_seek (abfd,
(file_ptr) (obj_datasec (abfd)->filepos
+ exec_hdr (abfd)->a_data
- 1),
SEEK_SET) != 0
|| bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
goto error_return;
}
return TRUE;
error_return:
if (aout_info.contents != NULL)
free (aout_info.contents);
if (aout_info.relocs != NULL)
free (aout_info.relocs);
if (aout_info.symbol_map != NULL)
free (aout_info.symbol_map);
if (aout_info.output_syms != NULL)
free (aout_info.output_syms);
if (includes_hash_initialized)
bfd_hash_table_free (&aout_info.includes.root);
return FALSE;
}
static bfd_boolean
aout_link_input_bfd (finfo, input_bfd)
struct aout_final_link_info *finfo;
bfd *input_bfd;
{
bfd_size_type sym_count;
BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
if ((input_bfd->flags & DYNAMIC) != 0
&& aout_backend_info (input_bfd)->link_dynamic_object != NULL)
{
return ((*aout_backend_info (input_bfd)->link_dynamic_object)
(finfo->info, input_bfd));
}
if (! aout_get_external_symbols (input_bfd))
return FALSE;
sym_count = obj_aout_external_sym_count (input_bfd);
if (! aout_link_write_symbols (finfo, input_bfd))
return FALSE;
if (obj_textsec (input_bfd)->linker_mark)
{
if (! aout_link_input_section (finfo, input_bfd,
obj_textsec (input_bfd),
&finfo->treloff,
exec_hdr (input_bfd)->a_trsize))
return FALSE;
}
if (obj_datasec (input_bfd)->linker_mark)
{
if (! aout_link_input_section (finfo, input_bfd,
obj_datasec (input_bfd),
&finfo->dreloff,
exec_hdr (input_bfd)->a_drsize))
return FALSE;
}
if (! finfo->info->keep_memory)
{
if (! aout_link_free_symbols (input_bfd))
return FALSE;
}
return TRUE;
}
static bfd_boolean
aout_link_write_symbols (finfo, input_bfd)
struct aout_final_link_info *finfo;
bfd *input_bfd;
{
bfd *output_bfd;
bfd_size_type sym_count;
char *strings;
enum bfd_link_strip strip;
enum bfd_link_discard discard;
struct external_nlist *outsym;
bfd_size_type strtab_index;
register struct external_nlist *sym;
struct external_nlist *sym_end;
struct aout_link_hash_entry **sym_hash;
int *symbol_map;
bfd_boolean pass;
bfd_boolean skip_next;
output_bfd = finfo->output_bfd;
sym_count = obj_aout_external_sym_count (input_bfd);
strings = obj_aout_external_strings (input_bfd);
strip = finfo->info->strip;
discard = finfo->info->discard;
outsym = finfo->output_syms;
if (strip != strip_all
&& (strip != strip_some
|| bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename,
FALSE, FALSE) != NULL)
&& discard != discard_all)
{
H_PUT_8 (output_bfd, N_TEXT, outsym->e_type);
strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
input_bfd->filename, FALSE);
if (strtab_index == (bfd_size_type) -1)
return FALSE;
PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
PUT_WORD (output_bfd,
(bfd_get_section_vma (output_bfd,
obj_textsec (input_bfd)->output_section)
+ obj_textsec (input_bfd)->output_offset),
outsym->e_value);
++obj_aout_external_sym_count (output_bfd);
++outsym;
}
pass = FALSE;
skip_next = FALSE;
sym = obj_aout_external_syms (input_bfd);
sym_end = sym + sym_count;
sym_hash = obj_aout_sym_hashes (input_bfd);
symbol_map = finfo->symbol_map;
memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map);
for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
{
const char *name;
int type;
struct aout_link_hash_entry *h;
bfd_boolean skip;
asection *symsec;
bfd_vma val = 0;
bfd_boolean copy;
if (*symbol_map == -1)
continue;
*symbol_map = -1;
type = H_GET_8 (input_bfd, sym->e_type);
name = strings + GET_WORD (input_bfd, sym->e_strx);
h = NULL;
if (pass)
{
val = GET_WORD (input_bfd, sym->e_value);
pass = FALSE;
}
else if (skip_next)
{
skip_next = FALSE;
continue;
}
else
{
struct aout_link_hash_entry *hresolve;
h = *sym_hash;
if (h != NULL)
name = h->root.root.string;
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);
*sym_hash = hresolve;
}
if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type != bfd_link_hash_warning
&& h->written)
{
if ((type & N_TYPE) == N_INDR
|| type == N_WARNING)
skip_next = TRUE;
*symbol_map = h->indx;
continue;
}
skip = FALSE;
switch (strip)
{
case strip_none:
break;
case strip_debugger:
if ((type & N_STAB) != 0)
skip = TRUE;
break;
case strip_some:
if (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE)
== NULL)
skip = TRUE;
break;
case strip_all:
skip = TRUE;
break;
}
if (skip)
{
if (h != (struct aout_link_hash_entry *) NULL)
h->written = TRUE;
continue;
}
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 == (struct aout_link_hash_entry *) 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 = TRUE;
val = GET_WORD (input_bfd, sym->e_value);
symsec = NULL;
}
else if ((type & N_STAB) != 0)
{
val = GET_WORD (input_bfd, sym->e_value);
symsec = NULL;
}
else
{
if ((type & N_TYPE) == N_INDR)
skip_next = TRUE;
symsec = NULL;
if (h == (struct aout_link_hash_entry *) 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;
input_section = hresolve->root.u.def.section;
output_section = input_section->output_section;
BFD_ASSERT (bfd_is_abs_section (output_section)
|| output_section->owner == output_bfd);
val = (hresolve->root.u.def.value
+ bfd_get_section_vma (output_bfd, output_section)
+ input_section->output_offset);
if (type == N_SETT
|| type == N_SETD
|| type == N_SETB
|| type == N_SETA)
type |= N_EXT;
type &=~ N_TYPE;
if (output_section == obj_textsec (output_bfd))
type |= (hresolve->root.type == bfd_link_hash_defined
? N_TEXT
: N_WEAKT);
else if (output_section == obj_datasec (output_bfd))
type |= (hresolve->root.type == bfd_link_hash_defined
? N_DATA
: N_WEAKD);
else if (output_section == obj_bsssec (output_bfd))
type |= (hresolve->root.type == bfd_link_hash_defined
? N_BSS
: N_WEAKB);
else
type |= (hresolve->root.type == bfd_link_hash_defined
? N_ABS
: N_WEAKA);
}
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_WEAKU;
}
else
val = 0;
}
if (symsec != (asection *) NULL)
val = (symsec->output_section->vma
+ symsec->output_offset
+ (GET_WORD (input_bfd, sym->e_value)
- symsec->vma));
if (h != (struct aout_link_hash_entry *) NULL)
{
h->written = TRUE;
h->indx = obj_aout_external_sym_count (output_bfd);
}
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 ((type & N_STAB) == 0
&& bfd_is_local_label_name (input_bfd, name))
skip = TRUE;
break;
case discard_all:
skip = TRUE;
break;
}
if (skip)
{
pass = FALSE;
continue;
}
}
if (type == N_BINCL)
{
struct external_nlist *incl_sym;
int nest;
struct aout_link_includes_entry *incl_entry;
struct aout_link_includes_totals *t;
val = 0;
nest = 0;
for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
{
int incl_type;
incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
if (incl_type == N_EINCL)
{
if (nest == 0)
break;
--nest;
}
else if (incl_type == N_BINCL)
++nest;
else if (nest == 0)
{
const char *s;
s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
for (; *s != '\0'; s++)
{
val += *s;
if (*s == '(')
{
++s;
while (ISDIGIT (*s))
++s;
--s;
}
}
}
}
copy = ! finfo->info->keep_memory;
incl_entry = aout_link_includes_lookup (&finfo->includes,
name, TRUE, copy);
if (incl_entry == NULL)
return FALSE;
for (t = incl_entry->totals; t != NULL; t = t->next)
if (t->total == val)
break;
if (t == NULL)
{
t = ((struct aout_link_includes_totals *)
bfd_hash_allocate (&finfo->includes.root,
sizeof *t));
if (t == NULL)
return FALSE;
t->total = val;
t->next = incl_entry->totals;
incl_entry->totals = t;
}
else
{
int *incl_map;
type = N_EXCL;
nest = 0;
for (incl_sym = sym + 1, incl_map = symbol_map + 1;
incl_sym < sym_end;
incl_sym++, incl_map++)
{
int incl_type;
incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
if (incl_type == N_EINCL)
{
if (nest == 0)
{
*incl_map = -1;
break;
}
--nest;
}
else if (incl_type == N_BINCL)
++nest;
else if (nest == 0)
*incl_map = -1;
}
}
}
}
H_PUT_8 (output_bfd, type, outsym->e_type);
copy = FALSE;
if (! finfo->info->keep_memory)
{
if (h != (struct aout_link_hash_entry *) NULL)
name = h->root.root.string;
else
copy = TRUE;
}
strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
name, copy);
if (strtab_index == (bfd_size_type) -1)
return FALSE;
PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
PUT_WORD (output_bfd, val, outsym->e_value);
*symbol_map = obj_aout_external_sym_count (output_bfd);
++obj_aout_external_sym_count (output_bfd);
++outsym;
}
if (outsym > finfo->output_syms)
{
bfd_size_type size;
if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
return FALSE;
size = outsym - finfo->output_syms;
size *= EXTERNAL_NLIST_SIZE;
if (bfd_bwrite ((PTR) finfo->output_syms, size, output_bfd) != size)
return FALSE;
finfo->symoff += size;
}
return TRUE;
}
static bfd_boolean
aout_link_write_other_symbol (h, data)
struct aout_link_hash_entry *h;
PTR data;
{
struct aout_final_link_info *finfo = (struct aout_final_link_info *) data;
bfd *output_bfd;
int type;
bfd_vma val;
struct external_nlist outsym;
bfd_size_type indx;
bfd_size_type amt;
if (h->root.type == bfd_link_hash_warning)
{
h = (struct aout_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_new)
return TRUE;
}
output_bfd = finfo->output_bfd;
if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
{
if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
(output_bfd, finfo->info, h)))
{
abort ();
}
}
if (h->written)
return TRUE;
h->written = TRUE;
if (h->indx != -2
&& (finfo->info->strip == strip_all
|| (finfo->info->strip == strip_some
&& bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
FALSE, FALSE) == NULL)))
return TRUE;
switch (h->root.type)
{
default:
abort ();
return TRUE;
case bfd_link_hash_new:
return TRUE;
case bfd_link_hash_undefined:
type = N_UNDF | N_EXT;
val = 0;
break;
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
{
asection *sec;
sec = h->root.u.def.section->output_section;
BFD_ASSERT (bfd_is_abs_section (sec)
|| sec->owner == output_bfd);
if (sec == obj_textsec (output_bfd))
type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
else if (sec == obj_datasec (output_bfd))
type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
else if (sec == obj_bsssec (output_bfd))
type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
else
type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
type |= N_EXT;
val = (h->root.u.def.value
+ sec->vma
+ h->root.u.def.section->output_offset);
}
break;
case bfd_link_hash_common:
type = N_UNDF | N_EXT;
val = h->root.u.c.size;
break;
case bfd_link_hash_undefweak:
type = N_WEAKU;
val = 0;
case bfd_link_hash_indirect:
case bfd_link_hash_warning:
return TRUE;
}
H_PUT_8 (output_bfd, type, outsym.e_type);
indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
FALSE);
if (indx == (bfd_size_type) -1)
{
abort ();
}
PUT_WORD (output_bfd, indx, outsym.e_strx);
PUT_WORD (output_bfd, val, outsym.e_value);
amt = EXTERNAL_NLIST_SIZE;
if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
|| bfd_bwrite ((PTR) &outsym, amt, output_bfd) != amt)
{
abort ();
}
finfo->symoff += amt;
h->indx = obj_aout_external_sym_count (output_bfd);
++obj_aout_external_sym_count (output_bfd);
return TRUE;
}
static bfd_boolean
aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
rel_size)
struct aout_final_link_info *finfo;
bfd *input_bfd;
asection *input_section;
file_ptr *reloff_ptr;
bfd_size_type rel_size;
{
bfd_size_type input_size;
PTR relocs;
input_size = bfd_section_size (input_bfd, input_section);
if (! bfd_get_section_contents (input_bfd, input_section,
(PTR) finfo->contents,
(file_ptr) 0, input_size))
return FALSE;
if (aout_section_data (input_section) != NULL
&& aout_section_data (input_section)->relocs != NULL)
relocs = aout_section_data (input_section)->relocs;
else
{
relocs = finfo->relocs;
if (rel_size > 0)
{
if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
|| bfd_bread (relocs, rel_size, input_bfd) != rel_size)
return FALSE;
}
}
if (! pdp11_aout_link_input_section (finfo, input_bfd, input_section,
(struct pdp11_aout_reloc_external *) relocs,
rel_size, finfo->contents))
return FALSE;
if (! bfd_set_section_contents (finfo->output_bfd,
input_section->output_section,
(PTR) finfo->contents,
(file_ptr) input_section->output_offset,
input_size))
return FALSE;
if (finfo->info->relocatable && rel_size > 0)
{
if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
return FALSE;
if (bfd_bwrite (relocs, rel_size, finfo->output_bfd) != rel_size)
return FALSE;
*reloff_ptr += rel_size;
BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
&& (reloff_ptr != &finfo->treloff
|| (*reloff_ptr
<= obj_datasec (finfo->output_bfd)->rel_filepos)));
}
return TRUE;
}
static INLINE asection *
aout_reloc_type_to_section (abfd, type)
bfd *abfd;
int type;
{
switch (type)
{
case RTEXT:
return obj_textsec (abfd);
case RDATA:
return obj_datasec (abfd);
case RBSS:
return obj_bsssec (abfd);
case RABS:
return bfd_abs_section_ptr;
case REXT:
return bfd_und_section_ptr;
default:
abort ();
}
}
static bfd_boolean
pdp11_aout_link_input_section (finfo, input_bfd, input_section, relocs,
rel_size, contents)
struct aout_final_link_info *finfo;
bfd *input_bfd;
asection *input_section;
struct pdp11_aout_reloc_external *relocs;
bfd_size_type rel_size;
bfd_byte *contents;
{
bfd_boolean (*check_dynamic_reloc)
PARAMS ((struct bfd_link_info *, bfd *, asection *,
struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *,
bfd_vma *));
bfd *output_bfd;
bfd_boolean relocatable;
struct external_nlist *syms;
char *strings;
struct aout_link_hash_entry **sym_hashes;
int *symbol_map;
bfd_size_type reloc_count;
register struct pdp11_aout_reloc_external *rel;
struct pdp11_aout_reloc_external *rel_end;
output_bfd = finfo->output_bfd;
check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_SIZE);
BFD_ASSERT (input_bfd->xvec->header_byteorder
== output_bfd->xvec->header_byteorder);
relocatable = finfo->info->relocatable;
syms = obj_aout_external_syms (input_bfd);
strings = obj_aout_external_strings (input_bfd);
sym_hashes = obj_aout_sym_hashes (input_bfd);
symbol_map = finfo->symbol_map;
reloc_count = rel_size / RELOC_SIZE;
rel = relocs;
rel_end = (struct pdp11_aout_reloc_external *)(((char *)rel) + rel_size);
for (; rel < rel_end; ((char *)rel) += RELOC_SIZE)
{
bfd_vma r_addr;
int r_index;
int r_type;
int r_pcrel;
int r_extern;
reloc_howto_type *howto;
struct aout_link_hash_entry *h = NULL;
bfd_vma relocation;
bfd_reloc_status_type r;
int reloc_entry;
reloc_entry = GET_WORD (input_bfd, (PTR)rel);
if (reloc_entry == 0)
continue;
{
unsigned int howto_idx;
r_index = (reloc_entry & RIDXMASK) >> 4;
r_type = reloc_entry & RTYPE;
r_pcrel = reloc_entry & RELFLG;
r_addr = (char *)rel - (char *)relocs;
r_extern = (r_type == REXT);
howto_idx = r_pcrel;
BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_pdp11));
howto = howto_table_pdp11 + howto_idx;
}
if (relocatable)
{
if (r_extern)
{
h = sym_hashes[r_index];
if (h != (struct aout_link_hash_entry *) NULL
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
asection *output_section;
output_section = h->root.u.def.section->output_section;
if (output_section == obj_textsec (output_bfd))
r_type = N_TEXT;
else if (output_section == obj_datasec (output_bfd))
r_type = N_DATA;
else if (output_section == obj_bsssec (output_bfd))
r_type = N_BSS;
else
r_type = N_ABS;
relocation = (h->root.u.def.value
+ output_section->vma
+ h->root.u.def.section->output_offset);
}
else
{
r_index = symbol_map[r_index];
if (r_index == -1)
{
if (h != NULL)
{
if (h->indx < 0)
{
h->indx = -2;
h->written = FALSE;
if (! aout_link_write_other_symbol (h,
(PTR) finfo))
return FALSE;
}
r_index = h->indx;
}
else
{
const char *name;
name = strings + GET_WORD (input_bfd,
syms[r_index].e_strx);
if (! ((*finfo->info->callbacks->unattached_reloc)
(finfo->info, name, input_bfd, input_section,
r_addr)))
return FALSE;
r_index = 0;
}
}
relocation = 0;
}
reloc_entry = GET_WORD (input_bfd, rel->e_reloc_entry);
reloc_entry &= RIDXMASK;
reloc_entry |= r_index << 4;
PUT_WORD (input_bfd, reloc_entry, rel->e_reloc_entry);
}
else
{
asection *section;
section = aout_reloc_type_to_section (input_bfd, r_type);
relocation = (section->output_section->vma
+ section->output_offset
- section->vma);
}
#if 0
PUT_WORD (output_bfd,
r_addr + input_section->output_offset,
rel->r_address);
#else
fprintf (stderr, "TODO: change the address of the relocation\n");
#endif
if (r_pcrel)
relocation -= (input_section->output_section->vma
+ input_section->output_offset
- input_section->vma);
#ifdef MY_relocatable_reloc
MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
#endif
if (relocation == 0)
r = bfd_reloc_ok;
else
r = MY_relocate_contents (howto,
input_bfd, relocation,
contents + r_addr);
}
else
{
bfd_boolean hundef;
hundef = FALSE;
if (r_extern)
{
h = sym_hashes[r_index];
if (h != (struct aout_link_hash_entry *) NULL
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
relocation = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
}
else if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_undefweak)
relocation = 0;
else
{
hundef = TRUE;
relocation = 0;
}
}
else
{
asection *section;
section = aout_reloc_type_to_section (input_bfd, r_type);
relocation = (section->output_section->vma
+ section->output_offset
- section->vma);
if (r_pcrel)
relocation += input_section->vma;
}
if (check_dynamic_reloc != NULL)
{
bfd_boolean skip;
if (! ((*check_dynamic_reloc)
(finfo->info, input_bfd, input_section, h,
(PTR) rel, contents, &skip, &relocation)))
return FALSE;
if (skip)
continue;
}
if (hundef && ! finfo->info->shared)
{
const char *name;
if (h != NULL)
name = h->root.root.string;
else
name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
if (! ((*finfo->info->callbacks->undefined_symbol)
(finfo->info, name, input_bfd, input_section,
r_addr, TRUE)))
return FALSE;
}
r = MY_final_link_relocate (howto,
input_bfd, input_section,
contents, r_addr, relocation,
(bfd_vma) 0);
}
if (r != bfd_reloc_ok)
{
switch (r)
{
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
{
const char *name;
if (h != NULL)
name = h->root.root.string;
else if (r_extern)
name = strings + GET_WORD (input_bfd,
syms[r_index].e_strx);
else
{
asection *s;
s = aout_reloc_type_to_section (input_bfd, r_type);
name = bfd_section_name (input_bfd, s);
}
if (! ((*finfo->info->callbacks->reloc_overflow)
(finfo->info, name, howto->name,
(bfd_vma) 0, input_bfd, input_section, r_addr)))
return FALSE;
}
break;
}
}
}
return TRUE;
}
static bfd_boolean
aout_link_reloc_link_order (finfo, o, p)
struct aout_final_link_info *finfo;
asection *o;
struct bfd_link_order *p;
{
struct bfd_link_order_reloc *pr;
int r_index;
int r_extern;
reloc_howto_type *howto;
file_ptr *reloff_ptr;
struct reloc_std_external srel;
PTR rel_ptr;
bfd_size_type rel_size;
pr = p->u.reloc.p;
if (p->type == bfd_section_reloc_link_order)
{
r_extern = 0;
if (bfd_is_abs_section (pr->u.section))
r_index = N_ABS | N_EXT;
else
{
BFD_ASSERT (pr->u.section->owner == finfo->output_bfd);
r_index = pr->u.section->target_index;
}
}
else
{
struct aout_link_hash_entry *h;
BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
r_extern = 1;
h = ((struct aout_link_hash_entry *)
bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info,
pr->u.name, FALSE, FALSE, TRUE));
if (h != (struct aout_link_hash_entry *) NULL
&& h->indx >= 0)
r_index = h->indx;
else if (h != NULL)
{
h->indx = -2;
h->written = FALSE;
if (! aout_link_write_other_symbol (h, (PTR) finfo))
return FALSE;
r_index = h->indx;
}
else
{
if (! ((*finfo->info->callbacks->unattached_reloc)
(finfo->info, pr->u.name, (bfd *) NULL,
(asection *) NULL, (bfd_vma) 0)))
return FALSE;
r_index = 0;
}
}
howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc);
if (howto == 0)
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
if (o == obj_textsec (finfo->output_bfd))
reloff_ptr = &finfo->treloff;
else if (o == obj_datasec (finfo->output_bfd))
reloff_ptr = &finfo->dreloff;
else
abort ();
#ifdef MY_put_reloc
MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto,
&srel);
#else
{
int r_pcrel;
int r_baserel;
int r_jmptable;
int r_relative;
int r_length;
fprintf (stderr, "TODO: line %d in bfd/pdp11.c\n", __LINE__);
r_pcrel = howto->pc_relative;
r_baserel = (howto->type & 8) != 0;
r_jmptable = (howto->type & 16) != 0;
r_relative = (howto->type & 32) != 0;
r_length = howto->size;
PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
if (bfd_header_big_endian (finfo->output_bfd))
{
srel.r_index[0] = r_index >> 16;
srel.r_index[1] = r_index >> 8;
srel.r_index[2] = r_index;
srel.r_type[0] =
((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
}
else
{
srel.r_index[2] = r_index >> 16;
srel.r_index[1] = r_index >> 8;
srel.r_index[0] = r_index;
srel.r_type[0] =
((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
}
}
#endif
rel_ptr = (PTR) &srel;
if (pr->addend != 0)
{
bfd_size_type size;
bfd_reloc_status_type r;
bfd_byte *buf;
bfd_boolean ok;
size = bfd_get_reloc_size (howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == (bfd_byte *) NULL)
return FALSE;
r = MY_relocate_contents (howto, finfo->output_bfd,
pr->addend, buf);
switch (r)
{
case bfd_reloc_ok:
break;
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
if (! ((*finfo->info->callbacks->reloc_overflow)
(finfo->info,
(p->type == bfd_section_reloc_link_order
? bfd_section_name (finfo->output_bfd,
pr->u.section)
: pr->u.name),
howto->name, pr->addend, (bfd *) NULL,
(asection *) NULL, (bfd_vma) 0)))
{
free (buf);
return FALSE;
}
break;
}
ok = bfd_set_section_contents (finfo->output_bfd, o,
(PTR) buf,
(file_ptr) p->offset,
size);
free (buf);
if (! ok)
return FALSE;
}
rel_size = obj_reloc_entry_size (finfo->output_bfd);
if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
|| bfd_bwrite (rel_ptr, rel_size, finfo->output_bfd) != rel_size)
return FALSE;
*reloff_ptr += rel_size;
BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
&& (reloff_ptr != &finfo->treloff
|| (*reloff_ptr
<= obj_datasec (finfo->output_bfd)->rel_filepos)));
return TRUE;
}
bfd_vma
bfd_getp32 (addr)
const bfd_byte *addr;
{
return (((((bfd_vma)addr[1] << 8) | addr[0]) << 8)
| addr[3]) << 8 | addr[2];
}
#define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000)
bfd_signed_vma
bfd_getp_signed_32 (addr)
const bfd_byte *addr;
{
return COERCE32((((((bfd_vma)addr[1] << 8) | addr[0]) << 8)
| addr[3]) << 8 | addr[2]);
}
void
bfd_putp32 (data, addr)
bfd_vma data;
bfd_byte *addr;
{
addr[0] = (bfd_byte)(data >> 16);
addr[1] = (bfd_byte)(data >> 24);
addr[2] = (bfd_byte)data;
addr[3] = (bfd_byte)(data >> 8);
}