1130561Sobrien/* BFD back-end for Intel 960 b.out binaries. 2130561Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3218822Sdim 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4130561Sobrien Free Software Foundation, Inc. 5130561Sobrien Written by Cygnus Support. 6130561Sobrien 7218822Sdim This file is part of BFD, the Binary File Descriptor library. 8130561Sobrien 9218822Sdim This program is free software; you can redistribute it and/or modify 10218822Sdim it under the terms of the GNU General Public License as published by 11218822Sdim the Free Software Foundation; either version 2 of the License, or 12218822Sdim (at your option) any later version. 13130561Sobrien 14218822Sdim This program is distributed in the hope that it will be useful, 15218822Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 16218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17218822Sdim GNU General Public License for more details. 18130561Sobrien 19218822Sdim You should have received a copy of the GNU General Public License 20218822Sdim along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 22130561Sobrien 23218822Sdim#include "sysdep.h" 24130561Sobrien#include "bfd.h" 25130561Sobrien#include "libbfd.h" 26130561Sobrien#include "bfdlink.h" 27130561Sobrien#include "genlink.h" 28130561Sobrien#include "bout.h" 29218822Sdim#include "libiberty.h" 30130561Sobrien 31130561Sobrien#include "aout/stab_gnu.h" 32130561Sobrien#include "libaout.h" /* BFD a.out internal data structures. */ 33130561Sobrien 34218822Sdim#define ABS32CODE 0 35218822Sdim#define ABS32CODE_SHRUNK 1 36218822Sdim#define PCREL24 2 37218822Sdim#define CALLJ 3 38218822Sdim#define ABS32 4 39218822Sdim#define PCREL13 5 40218822Sdim#define ABS32_MAYBE_RELAXABLE 1 41218822Sdim#define ABS32_WAS_RELAXABLE 2 42130561Sobrien 43218822Sdim#define ALIGNER 10 44218822Sdim#define ALIGNDONE 11 45130561Sobrien 46218822Sdimstatic reloc_howto_type howto_reloc_callj = 47218822Sdim HOWTO (CALLJ, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE); 48218822Sdimstatic reloc_howto_type howto_reloc_abs32 = 49218822Sdim HOWTO (ABS32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"abs32", TRUE, 0xffffffff,0xffffffff,FALSE); 50218822Sdimstatic reloc_howto_type howto_reloc_pcrel24 = 51218822Sdim HOWTO (PCREL24, 0, 2, 24, TRUE, 0, complain_overflow_signed,0,"pcrel24", TRUE, 0x00ffffff,0x00ffffff,FALSE); 52218822Sdimstatic reloc_howto_type howto_reloc_pcrel13 = 53218822Sdim HOWTO (PCREL13, 0, 2, 13, TRUE, 0, complain_overflow_signed,0,"pcrel13", TRUE, 0x00001fff,0x00001fff,FALSE); 54218822Sdimstatic reloc_howto_type howto_reloc_abs32codeshrunk = 55218822Sdim HOWTO (ABS32CODE_SHRUNK, 0, 2, 24, TRUE, 0, complain_overflow_signed, 0,"callx->callj", TRUE, 0x00ffffff, 0x00ffffff,FALSE); 56218822Sdimstatic reloc_howto_type howto_reloc_abs32code = 57218822Sdim HOWTO (ABS32CODE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"callx", TRUE, 0xffffffff,0xffffffff,FALSE); 58218822Sdim 59218822Sdimstatic reloc_howto_type howto_align_table[] = 60218822Sdim{ 61218822Sdim HOWTO (ALIGNER, 0, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "align16", FALSE, 0, 0, FALSE), 62218822Sdim HOWTO (ALIGNER, 0, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "align32", FALSE, 0, 0, FALSE), 63218822Sdim HOWTO (ALIGNER, 0, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "align64", FALSE, 0, 0, FALSE), 64218822Sdim HOWTO (ALIGNER, 0, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "align128", FALSE, 0, 0, FALSE), 65218822Sdim}; 66218822Sdim 67218822Sdimstatic reloc_howto_type howto_done_align_table[] = 68218822Sdim{ 69218822Sdim HOWTO (ALIGNDONE, 0x1, 0x1, 0, FALSE, 0, complain_overflow_dont, 0, "donealign16", FALSE, 0, 0, FALSE), 70218822Sdim HOWTO (ALIGNDONE, 0x3, 0x3, 0, FALSE, 0, complain_overflow_dont, 0, "donealign32", FALSE, 0, 0, FALSE), 71218822Sdim HOWTO (ALIGNDONE, 0x7, 0x7, 0, FALSE, 0, complain_overflow_dont, 0, "donealign64", FALSE, 0, 0, FALSE), 72218822Sdim HOWTO (ALIGNDONE, 0xf, 0xf, 0, FALSE, 0, complain_overflow_dont, 0, "donealign128", FALSE, 0, 0, FALSE), 73218822Sdim}; 74218822Sdim 75130561Sobrien/* Swaps the information in an executable header taken from a raw byte 76130561Sobrien stream memory image, into the internal exec_header structure. */ 77130561Sobrien 78218822Sdimstatic void 79218822Sdimbout_swap_exec_header_in (bfd *abfd, 80218822Sdim struct external_exec *bytes, 81218822Sdim struct internal_exec *execp) 82130561Sobrien{ 83130561Sobrien /* Now fill in fields in the execp, from the bytes in the raw data. */ 84218822Sdim execp->a_info = H_GET_32 (abfd, bytes->e_info); 85218822Sdim execp->a_text = GET_WORD (abfd, bytes->e_text); 86218822Sdim execp->a_data = GET_WORD (abfd, bytes->e_data); 87218822Sdim execp->a_bss = GET_WORD (abfd, bytes->e_bss); 88218822Sdim execp->a_syms = GET_WORD (abfd, bytes->e_syms); 89218822Sdim execp->a_entry = GET_WORD (abfd, bytes->e_entry); 90218822Sdim execp->a_trsize = GET_WORD (abfd, bytes->e_trsize); 91218822Sdim execp->a_drsize = GET_WORD (abfd, bytes->e_drsize); 92218822Sdim execp->a_tload = GET_WORD (abfd, bytes->e_tload); 93218822Sdim execp->a_dload = GET_WORD (abfd, bytes->e_dload); 94218822Sdim execp->a_talign = bytes->e_talign[0]; 95218822Sdim execp->a_dalign = bytes->e_dalign[0]; 96218822Sdim execp->a_balign = bytes->e_balign[0]; 97130561Sobrien execp->a_relaxable = bytes->e_relaxable[0]; 98130561Sobrien} 99130561Sobrien 100130561Sobrien/* Swaps the information in an internal exec header structure into the 101130561Sobrien supplied buffer ready for writing to disk. */ 102130561Sobrien 103218822Sdimstatic void 104218822Sdimbout_swap_exec_header_out (bfd *abfd, 105218822Sdim struct internal_exec *execp, 106218822Sdim struct external_exec *bytes) 107130561Sobrien{ 108130561Sobrien /* Now fill in fields in the raw data, from the fields in the exec struct. */ 109130561Sobrien H_PUT_32 (abfd, execp->a_info , bytes->e_info); 110130561Sobrien PUT_WORD (abfd, execp->a_text , bytes->e_text); 111130561Sobrien PUT_WORD (abfd, execp->a_data , bytes->e_data); 112130561Sobrien PUT_WORD (abfd, execp->a_bss , bytes->e_bss); 113130561Sobrien PUT_WORD (abfd, execp->a_syms , bytes->e_syms); 114130561Sobrien PUT_WORD (abfd, execp->a_entry , bytes->e_entry); 115130561Sobrien PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize); 116130561Sobrien PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize); 117130561Sobrien PUT_WORD (abfd, execp->a_tload , bytes->e_tload); 118130561Sobrien PUT_WORD (abfd, execp->a_dload , bytes->e_dload); 119218822Sdim bytes->e_talign[0] = execp->a_talign; 120218822Sdim bytes->e_dalign[0] = execp->a_dalign; 121218822Sdim bytes->e_balign[0] = execp->a_balign; 122130561Sobrien bytes->e_relaxable[0] = execp->a_relaxable; 123130561Sobrien} 124130561Sobrien 125130561Sobrien/* Finish up the opening of a b.out file for reading. Fill in all the 126130561Sobrien fields that are not handled by common code. */ 127130561Sobrien 128130561Sobrienstatic const bfd_target * 129218822Sdimb_out_callback (bfd *abfd) 130130561Sobrien{ 131130561Sobrien struct internal_exec *execp = exec_hdr (abfd); 132130561Sobrien unsigned long bss_start; 133130561Sobrien 134130561Sobrien /* Architecture and machine type. */ 135218822Sdim bfd_set_arch_mach (abfd, 136218822Sdim bfd_arch_i960, /* B.out only used on i960. */ 137218822Sdim bfd_mach_i960_core /* Default. */ 138218822Sdim ); 139130561Sobrien 140130561Sobrien /* The positions of the string table and symbol table. */ 141130561Sobrien obj_str_filepos (abfd) = N_STROFF (*execp); 142130561Sobrien obj_sym_filepos (abfd) = N_SYMOFF (*execp); 143130561Sobrien 144130561Sobrien /* The alignments of the sections. */ 145130561Sobrien obj_textsec (abfd)->alignment_power = execp->a_talign; 146130561Sobrien obj_datasec (abfd)->alignment_power = execp->a_dalign; 147130561Sobrien obj_bsssec (abfd)->alignment_power = execp->a_balign; 148130561Sobrien 149130561Sobrien /* The starting addresses of the sections. */ 150130561Sobrien obj_textsec (abfd)->vma = execp->a_tload; 151130561Sobrien obj_datasec (abfd)->vma = execp->a_dload; 152130561Sobrien 153130561Sobrien obj_textsec (abfd)->lma = obj_textsec (abfd)->vma; 154130561Sobrien obj_datasec (abfd)->lma = obj_datasec (abfd)->vma; 155130561Sobrien 156130561Sobrien /* And reload the sizes, since the aout module zaps them. */ 157218822Sdim obj_textsec (abfd)->size = execp->a_text; 158130561Sobrien 159218822Sdim bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section. */ 160130561Sobrien obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign); 161130561Sobrien 162130561Sobrien obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma; 163130561Sobrien 164130561Sobrien /* The file positions of the sections. */ 165218822Sdim obj_textsec (abfd)->filepos = N_TXTOFF (*execp); 166218822Sdim obj_datasec (abfd)->filepos = N_DATOFF (*execp); 167130561Sobrien 168130561Sobrien /* The file positions of the relocation info. */ 169218822Sdim obj_textsec (abfd)->rel_filepos = N_TROFF (*execp); 170218822Sdim obj_datasec (abfd)->rel_filepos = N_DROFF (*execp); 171130561Sobrien 172218822Sdim adata (abfd).page_size = 1; /* Not applicable. */ 173218822Sdim adata (abfd).segment_size = 1; /* Not applicable. */ 174218822Sdim adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE; 175130561Sobrien 176130561Sobrien if (execp->a_relaxable) 177130561Sobrien abfd->flags |= BFD_IS_RELAXABLE; 178130561Sobrien return abfd->xvec; 179130561Sobrien} 180130561Sobrien 181218822Sdimstatic const bfd_target * 182218822Sdimb_out_object_p (bfd *abfd) 183218822Sdim{ 184218822Sdim struct internal_exec anexec; 185218822Sdim struct external_exec exec_bytes; 186218822Sdim bfd_size_type amt = EXEC_BYTES_SIZE; 187218822Sdim 188218822Sdim if (bfd_bread ((void *) &exec_bytes, amt, abfd) != amt) 189218822Sdim { 190218822Sdim if (bfd_get_error () != bfd_error_system_call) 191218822Sdim bfd_set_error (bfd_error_wrong_format); 192218822Sdim return 0; 193218822Sdim } 194218822Sdim 195218822Sdim anexec.a_info = H_GET_32 (abfd, exec_bytes.e_info); 196218822Sdim 197218822Sdim if (N_BADMAG (anexec)) 198218822Sdim { 199218822Sdim bfd_set_error (bfd_error_wrong_format); 200218822Sdim return 0; 201218822Sdim } 202218822Sdim 203218822Sdim bout_swap_exec_header_in (abfd, &exec_bytes, &anexec); 204218822Sdim return aout_32_some_aout_object_p (abfd, &anexec, b_out_callback); 205218822Sdim} 206218822Sdim 207130561Sobrienstruct bout_data_struct 208130561Sobrien { 209130561Sobrien struct aoutdata a; 210130561Sobrien struct internal_exec e; 211130561Sobrien }; 212130561Sobrien 213130561Sobrienstatic bfd_boolean 214218822Sdimb_out_mkobject (bfd *abfd) 215130561Sobrien{ 216130561Sobrien struct bout_data_struct *rawptr; 217130561Sobrien bfd_size_type amt = sizeof (struct bout_data_struct); 218130561Sobrien 219218822Sdim rawptr = bfd_zalloc (abfd, amt); 220130561Sobrien if (rawptr == NULL) 221130561Sobrien return FALSE; 222130561Sobrien 223130561Sobrien abfd->tdata.bout_data = rawptr; 224130561Sobrien exec_hdr (abfd) = &rawptr->e; 225130561Sobrien 226218822Sdim obj_textsec (abfd) = NULL; 227218822Sdim obj_datasec (abfd) = NULL; 228218822Sdim obj_bsssec (abfd) = NULL; 229130561Sobrien 230130561Sobrien return TRUE; 231130561Sobrien} 232130561Sobrien 233130561Sobrienstatic int 234218822Sdimb_out_symbol_cmp (const void * a_ptr, const void * b_ptr) 235130561Sobrien{ 236130561Sobrien struct aout_symbol ** a = (struct aout_symbol **) a_ptr; 237130561Sobrien struct aout_symbol ** b = (struct aout_symbol **) b_ptr; 238130561Sobrien asection *sec; 239130561Sobrien bfd_vma av, bv; 240130561Sobrien 241130561Sobrien /* Primary key is address. */ 242130561Sobrien sec = bfd_get_section (&(*a)->symbol); 243130561Sobrien av = sec->output_section->vma + sec->output_offset + (*a)->symbol.value; 244130561Sobrien sec = bfd_get_section (&(*b)->symbol); 245130561Sobrien bv = sec->output_section->vma + sec->output_offset + (*b)->symbol.value; 246130561Sobrien 247130561Sobrien if (av < bv) 248130561Sobrien return -1; 249130561Sobrien if (av > bv) 250130561Sobrien return 1; 251130561Sobrien 252218822Sdim /* Secondary key puts CALLNAME syms last and BALNAME syms first, 253218822Sdim so that they have the best chance of being contiguous. */ 254130561Sobrien if (IS_BALNAME ((*a)->other) || IS_CALLNAME ((*b)->other)) 255130561Sobrien return -1; 256130561Sobrien if (IS_CALLNAME ((*a)->other) || IS_BALNAME ((*b)->other)) 257130561Sobrien return 1; 258130561Sobrien 259130561Sobrien return 0; 260130561Sobrien} 261130561Sobrien 262130561Sobrienstatic bfd_boolean 263218822Sdimb_out_squirt_out_relocs (bfd *abfd, asection *section) 264130561Sobrien{ 265218822Sdim arelent **generic; 266218822Sdim int r_extern = 0; 267218822Sdim int r_idx; 268218822Sdim int incode_mask; 269218822Sdim int len_1; 270218822Sdim unsigned int count = section->reloc_count; 271218822Sdim struct relocation_info *native, *natptr; 272218822Sdim bfd_size_type natsize; 273218822Sdim int extern_mask, pcrel_mask, len_2, callj_mask; 274218822Sdim 275218822Sdim if (count == 0) 276218822Sdim return TRUE; 277218822Sdim 278218822Sdim generic = section->orelocation; 279218822Sdim natsize = (bfd_size_type) count * sizeof (struct relocation_info); 280218822Sdim native = bfd_malloc (natsize); 281218822Sdim if (!native && natsize != 0) 282218822Sdim return FALSE; 283218822Sdim 284218822Sdim if (bfd_header_big_endian (abfd)) 285218822Sdim { 286218822Sdim /* Big-endian bit field allocation order. */ 287218822Sdim pcrel_mask = 0x80; 288218822Sdim extern_mask = 0x10; 289218822Sdim len_2 = 0x40; 290218822Sdim len_1 = 0x20; 291218822Sdim callj_mask = 0x02; 292218822Sdim incode_mask = 0x08; 293218822Sdim } 294218822Sdim else 295218822Sdim { 296218822Sdim /* Little-endian bit field allocation order. */ 297218822Sdim pcrel_mask = 0x01; 298218822Sdim extern_mask = 0x08; 299218822Sdim len_2 = 0x04; 300218822Sdim len_1 = 0x02; 301218822Sdim callj_mask = 0x40; 302218822Sdim incode_mask = 0x10; 303218822Sdim } 304218822Sdim 305218822Sdim for (natptr = native; count > 0; --count, ++natptr, ++generic) 306218822Sdim { 307218822Sdim arelent *g = *generic; 308218822Sdim unsigned char *raw = (unsigned char *) natptr; 309218822Sdim asymbol *sym = *(g->sym_ptr_ptr); 310218822Sdim asection *output_section = sym->section->output_section; 311218822Sdim 312218822Sdim H_PUT_32 (abfd, g->address, raw); 313218822Sdim /* Find a type in the output format which matches the input howto - 314218822Sdim at the moment we assume input format == output format FIXME!! */ 315218822Sdim r_idx = 0; 316218822Sdim /* FIXME: Need callj stuff here, and to check the howto entries to 317218822Sdim be sure they are real for this architecture. */ 318218822Sdim if (g->howto== &howto_reloc_callj) 319218822Sdim raw[7] = callj_mask + pcrel_mask + len_2; 320218822Sdim else if (g->howto == &howto_reloc_pcrel24) 321218822Sdim raw[7] = pcrel_mask + len_2; 322218822Sdim else if (g->howto == &howto_reloc_pcrel13) 323218822Sdim raw[7] = pcrel_mask + len_1; 324218822Sdim else if (g->howto == &howto_reloc_abs32code) 325218822Sdim raw[7] = len_2 + incode_mask; 326218822Sdim else if (g->howto >= howto_align_table 327218822Sdim && g->howto <= (howto_align_table + ARRAY_SIZE (howto_align_table) - 1)) 328218822Sdim { 329218822Sdim /* symnum == -2; extern_mask not set, pcrel_mask set. */ 330218822Sdim r_idx = -2; 331218822Sdim r_extern = 0; 332218822Sdim raw[7] = (pcrel_mask 333218822Sdim | ((g->howto - howto_align_table) << 1)); 334218822Sdim } 335218822Sdim else 336218822Sdim raw[7] = len_2; 337218822Sdim 338218822Sdim if (r_idx != 0) 339218822Sdim /* Already mucked with r_extern, r_idx. */; 340218822Sdim else if (bfd_is_com_section (output_section) 341218822Sdim || bfd_is_abs_section (output_section) 342218822Sdim || bfd_is_und_section (output_section)) 343218822Sdim { 344218822Sdim if (bfd_abs_section_ptr->symbol == sym) 345218822Sdim { 346218822Sdim /* Whoops, looked like an abs symbol, but is really an offset 347218822Sdim from the abs section. */ 348218822Sdim r_idx = 0; 349218822Sdim r_extern = 0; 350218822Sdim } 351218822Sdim else 352218822Sdim { 353218822Sdim /* Fill in symbol. */ 354218822Sdim r_extern = 1; 355218822Sdim r_idx = (*g->sym_ptr_ptr)->udata.i; 356218822Sdim } 357218822Sdim } 358218822Sdim else 359218822Sdim { 360218822Sdim /* Just an ordinary section. */ 361218822Sdim r_extern = 0; 362218822Sdim r_idx = output_section->target_index; 363218822Sdim } 364218822Sdim 365218822Sdim if (bfd_header_big_endian (abfd)) 366218822Sdim { 367218822Sdim raw[4] = (unsigned char) (r_idx >> 16); 368218822Sdim raw[5] = (unsigned char) (r_idx >> 8); 369218822Sdim raw[6] = (unsigned char) (r_idx ); 370218822Sdim } 371218822Sdim else 372218822Sdim { 373218822Sdim raw[6] = (unsigned char) (r_idx >> 16); 374218822Sdim raw[5] = (unsigned char) (r_idx>> 8); 375218822Sdim raw[4] = (unsigned char) (r_idx ); 376218822Sdim } 377218822Sdim 378218822Sdim if (r_extern) 379218822Sdim raw[7] |= extern_mask; 380218822Sdim } 381218822Sdim 382218822Sdim if (bfd_bwrite ((void *) native, natsize, abfd) != natsize) 383218822Sdim { 384218822Sdim free (native); 385218822Sdim return FALSE; 386218822Sdim } 387218822Sdim 388218822Sdim free (native); 389218822Sdim 390218822Sdim return TRUE; 391218822Sdim} 392218822Sdim 393218822Sdimstatic bfd_boolean 394218822Sdimb_out_write_object_contents (bfd *abfd) 395218822Sdim{ 396130561Sobrien struct external_exec swapped_hdr; 397130561Sobrien bfd_size_type amt; 398130561Sobrien 399130561Sobrien if (! aout_32_make_sections (abfd)) 400130561Sobrien return FALSE; 401130561Sobrien 402130561Sobrien exec_hdr (abfd)->a_info = BMAGIC; 403130561Sobrien 404218822Sdim exec_hdr (abfd)->a_text = obj_textsec (abfd)->size; 405218822Sdim exec_hdr (abfd)->a_data = obj_datasec (abfd)->size; 406218822Sdim exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->size; 407218822Sdim exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * 12; 408130561Sobrien exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd); 409218822Sdim exec_hdr (abfd)->a_trsize = (obj_textsec (abfd)->reloc_count) * 8; 410218822Sdim exec_hdr (abfd)->a_drsize = (obj_datasec (abfd)->reloc_count) * 8; 411130561Sobrien 412130561Sobrien exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power; 413130561Sobrien exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power; 414130561Sobrien exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power; 415130561Sobrien 416130561Sobrien exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma; 417130561Sobrien exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma; 418130561Sobrien 419130561Sobrien bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr); 420130561Sobrien 421130561Sobrien amt = EXEC_BYTES_SIZE; 422130561Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 423218822Sdim || bfd_bwrite ((void *) &swapped_hdr, amt, abfd) != amt) 424130561Sobrien return FALSE; 425130561Sobrien 426130561Sobrien /* Now write out reloc info, followed by syms and strings */ 427130561Sobrien if (bfd_get_symcount (abfd) != 0) 428130561Sobrien { 429130561Sobrien /* Make sure {CALL,BAL}NAME symbols remain adjacent on output 430130561Sobrien by sorting. This is complicated by the fact that stabs are 431130561Sobrien also ordered. Solve this by shifting all stabs to the end 432130561Sobrien in order, then sorting the rest. */ 433130561Sobrien 434130561Sobrien asymbol **outsyms, **p, **q; 435130561Sobrien 436130561Sobrien outsyms = bfd_get_outsymbols (abfd); 437130561Sobrien p = outsyms + bfd_get_symcount (abfd); 438130561Sobrien 439130561Sobrien for (q = p--; p >= outsyms; p--) 440130561Sobrien { 441130561Sobrien if ((*p)->flags & BSF_DEBUGGING) 442130561Sobrien { 443130561Sobrien asymbol *t = *--q; 444130561Sobrien *q = *p; 445130561Sobrien *p = t; 446130561Sobrien } 447130561Sobrien } 448130561Sobrien 449130561Sobrien if (q > outsyms) 450130561Sobrien qsort (outsyms, (size_t) (q - outsyms), sizeof (asymbol*), 451130561Sobrien b_out_symbol_cmp); 452130561Sobrien 453130561Sobrien /* Back to your regularly scheduled program. */ 454218822Sdim if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET) 455130561Sobrien != 0) 456130561Sobrien return FALSE; 457130561Sobrien 458130561Sobrien if (! aout_32_write_syms (abfd)) 459130561Sobrien return FALSE; 460130561Sobrien 461218822Sdim if (bfd_seek (abfd, (file_ptr) (N_TROFF (*exec_hdr (abfd))), SEEK_SET) 462130561Sobrien != 0) 463130561Sobrien return FALSE; 464130561Sobrien 465130561Sobrien if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd))) 466130561Sobrien return FALSE; 467218822Sdim if (bfd_seek (abfd, (file_ptr) (N_DROFF (*exec_hdr (abfd))), SEEK_SET) 468130561Sobrien != 0) 469130561Sobrien return FALSE; 470130561Sobrien 471130561Sobrien if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd))) 472130561Sobrien return FALSE; 473130561Sobrien } 474130561Sobrien return TRUE; 475130561Sobrien} 476130561Sobrien 477130561Sobrien/* Some reloc hackery. */ 478130561Sobrien 479130561Sobrien#define CALLS 0x66003800 /* Template for 'calls' instruction */ 480130561Sobrien#define BAL 0x0b000000 /* Template for 'bal' instruction */ 481130561Sobrien#define BAL_MASK 0x00ffffff 482130561Sobrien#define BALX 0x85f00000 /* Template for 'balx' instruction */ 483130561Sobrien#define BALX_MASK 0x0007ffff 484130561Sobrien#define CALL 0x09000000 485130561Sobrien#define PCREL13_MASK 0x1fff 486130561Sobrien 487130561Sobrien#define output_addr(sec) ((sec)->output_offset+(sec)->output_section->vma) 488130561Sobrien 489218822Sdimstatic bfd_vma 490218822Sdimget_value (arelent *reloc, 491218822Sdim struct bfd_link_info *link_info, 492218822Sdim asection *input_section) 493218822Sdim{ 494218822Sdim bfd_vma value; 495218822Sdim asymbol *symbol = *(reloc->sym_ptr_ptr); 496218822Sdim 497218822Sdim /* A symbol holds a pointer to a section, and an offset from the 498218822Sdim base of the section. To relocate, we find where the section will 499218822Sdim live in the output and add that in. */ 500218822Sdim if (bfd_is_und_section (symbol->section)) 501218822Sdim { 502218822Sdim struct bfd_link_hash_entry *h; 503218822Sdim 504218822Sdim /* The symbol is undefined in this BFD. Look it up in the 505218822Sdim global linker hash table. FIXME: This should be changed when 506218822Sdim we convert b.out to use a specific final_link function and 507218822Sdim change the interface to bfd_relax_section to not require the 508218822Sdim generic symbols. */ 509218822Sdim h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info, 510218822Sdim bfd_asymbol_name (symbol), 511218822Sdim FALSE, FALSE, TRUE); 512218822Sdim if (h != (struct bfd_link_hash_entry *) NULL 513218822Sdim && (h->type == bfd_link_hash_defined 514218822Sdim || h->type == bfd_link_hash_defweak)) 515218822Sdim value = h->u.def.value + output_addr (h->u.def.section); 516218822Sdim else if (h != (struct bfd_link_hash_entry *) NULL 517218822Sdim && h->type == bfd_link_hash_common) 518218822Sdim value = h->u.c.size; 519218822Sdim else 520218822Sdim { 521218822Sdim if (! ((*link_info->callbacks->undefined_symbol) 522218822Sdim (link_info, bfd_asymbol_name (symbol), 523218822Sdim input_section->owner, input_section, reloc->address, 524218822Sdim TRUE))) 525218822Sdim abort (); 526218822Sdim value = 0; 527218822Sdim } 528218822Sdim } 529218822Sdim else 530218822Sdim value = symbol->value + output_addr (symbol->section); 531218822Sdim 532218822Sdim /* Add the value contained in the relocation. */ 533218822Sdim value += reloc->addend; 534218822Sdim 535218822Sdim return value; 536218822Sdim} 537218822Sdim 538130561Sobrien/* Magic to turn callx into calljx. */ 539130561Sobrien 540130561Sobrienstatic bfd_reloc_status_type 541218822Sdimcalljx_callback (bfd *abfd, 542218822Sdim struct bfd_link_info *link_info, 543218822Sdim arelent *reloc_entry, 544218822Sdim void * src, 545218822Sdim void * dst, 546218822Sdim asection *input_section) 547130561Sobrien{ 548130561Sobrien int word = bfd_get_32 (abfd, src); 549130561Sobrien asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr); 550130561Sobrien aout_symbol_type *symbol = aout_symbol (symbol_in); 551130561Sobrien bfd_vma value; 552130561Sobrien 553130561Sobrien value = get_value (reloc_entry, link_info, input_section); 554130561Sobrien 555130561Sobrien if (IS_CALLNAME (symbol->other)) 556130561Sobrien { 557130561Sobrien aout_symbol_type *balsym = symbol+1; 558130561Sobrien int inst = bfd_get_32 (abfd, (bfd_byte *) src-4); 559218822Sdim 560130561Sobrien /* The next symbol should be an N_BALNAME. */ 561130561Sobrien BFD_ASSERT (IS_BALNAME (balsym->other)); 562130561Sobrien inst &= BALX_MASK; 563130561Sobrien inst |= BALX; 564130561Sobrien bfd_put_32 (abfd, (bfd_vma) inst, (bfd_byte *) dst-4); 565130561Sobrien symbol = balsym; 566130561Sobrien value = (symbol->symbol.value 567130561Sobrien + output_addr (symbol->symbol.section)); 568130561Sobrien } 569130561Sobrien 570130561Sobrien word += value + reloc_entry->addend; 571130561Sobrien 572130561Sobrien bfd_put_32 (abfd, (bfd_vma) word, dst); 573130561Sobrien return bfd_reloc_ok; 574130561Sobrien} 575130561Sobrien 576130561Sobrien/* Magic to turn call into callj. */ 577130561Sobrien 578130561Sobrienstatic bfd_reloc_status_type 579218822Sdimcallj_callback (bfd *abfd, 580218822Sdim struct bfd_link_info *link_info, 581218822Sdim arelent *reloc_entry, 582218822Sdim void * data, 583218822Sdim unsigned int srcidx, 584218822Sdim unsigned int dstidx, 585218822Sdim asection *input_section, 586218822Sdim bfd_boolean shrinking) 587130561Sobrien{ 588130561Sobrien int word = bfd_get_32 (abfd, (bfd_byte *) data + srcidx); 589130561Sobrien asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr); 590130561Sobrien aout_symbol_type *symbol = aout_symbol (symbol_in); 591130561Sobrien bfd_vma value; 592130561Sobrien 593130561Sobrien value = get_value (reloc_entry, link_info, input_section); 594130561Sobrien 595218822Sdim if (IS_OTHER (symbol->other)) 596218822Sdim /* Call to a system procedure - replace code with system 597218822Sdim procedure number. */ 598218822Sdim word = CALLS | (symbol->other - 1); 599218822Sdim 600218822Sdim else if (IS_CALLNAME (symbol->other)) 601130561Sobrien { 602130561Sobrien aout_symbol_type *balsym = symbol+1; 603130561Sobrien 604130561Sobrien /* The next symbol should be an N_BALNAME. */ 605218822Sdim BFD_ASSERT (IS_BALNAME (balsym->other)); 606130561Sobrien 607130561Sobrien /* We are calling a leaf, so replace the call instruction with a 608130561Sobrien bal. */ 609130561Sobrien word = BAL | ((word 610130561Sobrien + output_addr (balsym->symbol.section) 611130561Sobrien + balsym->symbol.value + reloc_entry->addend 612130561Sobrien - dstidx 613130561Sobrien - output_addr (input_section)) 614130561Sobrien & BAL_MASK); 615130561Sobrien } 616130561Sobrien else if ((symbol->symbol.flags & BSF_SECTION_SYM) != 0) 617130561Sobrien { 618130561Sobrien /* A callj against a symbol in the same section is a fully 619130561Sobrien resolved relative call. We don't need to do anything here. 620130561Sobrien If the symbol is not in the same section, I'm not sure what 621130561Sobrien to do; fortunately, this case will probably never arise. */ 622130561Sobrien BFD_ASSERT (! shrinking); 623130561Sobrien BFD_ASSERT (symbol->symbol.section == input_section); 624130561Sobrien } 625130561Sobrien else 626218822Sdim word = CALL | (((word & BAL_MASK) 627218822Sdim + value 628218822Sdim + reloc_entry->addend 629218822Sdim - (shrinking ? dstidx : 0) 630218822Sdim - output_addr (input_section)) 631218822Sdim & BAL_MASK); 632218822Sdim 633130561Sobrien bfd_put_32 (abfd, (bfd_vma) word, (bfd_byte *) data + dstidx); 634130561Sobrien return bfd_reloc_ok; 635130561Sobrien} 636130561Sobrien 637130561Sobrienstatic reloc_howto_type * 638218822Sdimb_out_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 639218822Sdim bfd_reloc_code_real_type code) 640130561Sobrien{ 641130561Sobrien switch (code) 642130561Sobrien { 643130561Sobrien default: 644130561Sobrien return 0; 645130561Sobrien case BFD_RELOC_I960_CALLJ: 646130561Sobrien return &howto_reloc_callj; 647130561Sobrien case BFD_RELOC_32: 648130561Sobrien case BFD_RELOC_CTOR: 649130561Sobrien return &howto_reloc_abs32; 650130561Sobrien case BFD_RELOC_24_PCREL: 651130561Sobrien return &howto_reloc_pcrel24; 652130561Sobrien } 653130561Sobrien} 654130561Sobrien 655218822Sdimstatic reloc_howto_type * 656218822Sdimb_out_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 657218822Sdim const char *r_name) 658218822Sdim{ 659218822Sdim if (strcasecmp (howto_reloc_callj.name, r_name) == 0) 660218822Sdim return &howto_reloc_callj; 661218822Sdim if (strcasecmp (howto_reloc_abs32.name, r_name) == 0) 662218822Sdim return &howto_reloc_abs32; 663218822Sdim if (strcasecmp (howto_reloc_pcrel24.name, r_name) == 0) 664218822Sdim return &howto_reloc_pcrel24; 665218822Sdim 666218822Sdim return NULL; 667218822Sdim} 668218822Sdim 669130561Sobrien/* Allocate enough room for all the reloc entries, plus pointers to them all. */ 670130561Sobrien 671130561Sobrienstatic bfd_boolean 672218822Sdimb_out_slurp_reloc_table (bfd *abfd, sec_ptr asect, asymbol **symbols) 673130561Sobrien{ 674218822Sdim struct relocation_info *rptr; 675130561Sobrien unsigned int counter; 676130561Sobrien arelent *cache_ptr; 677130561Sobrien int extern_mask, pcrel_mask, callj_mask, length_shift; 678130561Sobrien int incode_mask; 679130561Sobrien int size_mask; 680130561Sobrien bfd_vma prev_addr = 0; 681130561Sobrien unsigned int count; 682130561Sobrien bfd_size_type reloc_size, amt; 683130561Sobrien struct relocation_info *relocs; 684130561Sobrien arelent *reloc_cache; 685130561Sobrien 686130561Sobrien if (asect->relocation) 687130561Sobrien return TRUE; 688130561Sobrien 689130561Sobrien if (!aout_32_slurp_symbol_table (abfd)) 690130561Sobrien return FALSE; 691130561Sobrien 692130561Sobrien if (asect == obj_datasec (abfd)) 693218822Sdim reloc_size = exec_hdr (abfd)->a_drsize; 694218822Sdim else if (asect == obj_textsec (abfd)) 695218822Sdim reloc_size = exec_hdr (abfd)->a_trsize; 696218822Sdim else if (asect == obj_bsssec (abfd)) 697218822Sdim reloc_size = 0; 698218822Sdim else 699130561Sobrien { 700218822Sdim bfd_set_error (bfd_error_invalid_operation); 701218822Sdim return FALSE; 702130561Sobrien } 703130561Sobrien 704130561Sobrien if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) 705130561Sobrien return FALSE; 706130561Sobrien count = reloc_size / sizeof (struct relocation_info); 707130561Sobrien 708218822Sdim relocs = bfd_malloc (reloc_size); 709130561Sobrien if (!relocs && reloc_size != 0) 710130561Sobrien return FALSE; 711130561Sobrien 712130561Sobrien amt = ((bfd_size_type) count + 1) * sizeof (arelent); 713218822Sdim reloc_cache = bfd_malloc (amt); 714130561Sobrien if (!reloc_cache) 715130561Sobrien { 716130561Sobrien if (relocs != NULL) 717130561Sobrien free (relocs); 718130561Sobrien return FALSE; 719130561Sobrien } 720130561Sobrien 721218822Sdim if (bfd_bread ((void *) relocs, reloc_size, abfd) != reloc_size) 722130561Sobrien { 723130561Sobrien free (reloc_cache); 724130561Sobrien if (relocs != NULL) 725130561Sobrien free (relocs); 726130561Sobrien return FALSE; 727130561Sobrien } 728130561Sobrien 729130561Sobrien if (bfd_header_big_endian (abfd)) 730130561Sobrien { 731130561Sobrien /* Big-endian bit field allocation order. */ 732130561Sobrien pcrel_mask = 0x80; 733130561Sobrien extern_mask = 0x10; 734130561Sobrien incode_mask = 0x08; 735130561Sobrien callj_mask = 0x02; 736130561Sobrien size_mask = 0x20; 737130561Sobrien length_shift = 5; 738130561Sobrien } 739130561Sobrien else 740130561Sobrien { 741130561Sobrien /* Little-endian bit field allocation order. */ 742130561Sobrien pcrel_mask = 0x01; 743130561Sobrien extern_mask = 0x08; 744130561Sobrien incode_mask = 0x10; 745130561Sobrien callj_mask = 0x40; 746130561Sobrien size_mask = 0x02; 747130561Sobrien length_shift = 1; 748130561Sobrien } 749130561Sobrien 750130561Sobrien for (rptr = relocs, cache_ptr = reloc_cache, counter = 0; 751130561Sobrien counter < count; 752130561Sobrien counter++, rptr++, cache_ptr++) 753130561Sobrien { 754130561Sobrien unsigned char *raw = (unsigned char *)rptr; 755130561Sobrien unsigned int symnum; 756130561Sobrien 757130561Sobrien cache_ptr->address = H_GET_32 (abfd, raw + 0); 758130561Sobrien cache_ptr->howto = 0; 759130561Sobrien 760130561Sobrien if (bfd_header_big_endian (abfd)) 761130561Sobrien symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6]; 762130561Sobrien else 763130561Sobrien symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4]; 764130561Sobrien 765130561Sobrien if (raw[7] & extern_mask) 766130561Sobrien { 767130561Sobrien /* If this is set then the r_index is an index into the symbol table; 768130561Sobrien if the bit is not set then r_index contains a section map. 769130561Sobrien We either fill in the sym entry with a pointer to the symbol, 770130561Sobrien or point to the correct section. */ 771130561Sobrien cache_ptr->sym_ptr_ptr = symbols + symnum; 772130561Sobrien cache_ptr->addend = 0; 773130561Sobrien } 774130561Sobrien else 775130561Sobrien { 776130561Sobrien /* In a.out symbols are relative to the beginning of the 777130561Sobrien file rather than sections ? 778130561Sobrien (look in translate_from_native_sym_flags) 779130561Sobrien The reloc entry addend has added to it the offset into the 780130561Sobrien file of the data, so subtract the base to make the reloc 781130561Sobrien section relative. */ 782130561Sobrien int s; 783130561Sobrien 784130561Sobrien /* Sign-extend symnum from 24 bits to whatever host uses. */ 785130561Sobrien s = symnum; 786130561Sobrien if (s & (1 << 23)) 787130561Sobrien s |= (~0) << 24; 788130561Sobrien 789130561Sobrien cache_ptr->sym_ptr_ptr = (asymbol **)NULL; 790130561Sobrien switch (s) 791130561Sobrien { 792130561Sobrien case N_TEXT: 793130561Sobrien case N_TEXT | N_EXT: 794130561Sobrien cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; 795130561Sobrien cache_ptr->addend = - obj_textsec (abfd)->vma; 796130561Sobrien break; 797130561Sobrien case N_DATA: 798130561Sobrien case N_DATA | N_EXT: 799130561Sobrien cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; 800130561Sobrien cache_ptr->addend = - obj_datasec (abfd)->vma; 801130561Sobrien break; 802130561Sobrien case N_BSS: 803130561Sobrien case N_BSS | N_EXT: 804130561Sobrien cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; 805130561Sobrien cache_ptr->addend = - obj_bsssec (abfd)->vma; 806130561Sobrien break; 807130561Sobrien case N_ABS: 808130561Sobrien case N_ABS | N_EXT: 809130561Sobrien cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; 810130561Sobrien cache_ptr->addend = 0; 811130561Sobrien break; 812130561Sobrien case -2: /* .align */ 813130561Sobrien if (raw[7] & pcrel_mask) 814130561Sobrien { 815130561Sobrien cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3]; 816130561Sobrien cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 817130561Sobrien } 818130561Sobrien else 819130561Sobrien { 820130561Sobrien /* .org? */ 821130561Sobrien abort (); 822130561Sobrien } 823130561Sobrien cache_ptr->addend = 0; 824130561Sobrien break; 825130561Sobrien default: 826218822Sdim BFD_ASSERT (FALSE); 827130561Sobrien break; 828130561Sobrien } 829130561Sobrien } 830130561Sobrien 831130561Sobrien /* The i960 only has a few relocation types: 832130561Sobrien abs 32-bit and pcrel 24bit. except for callj's! */ 833130561Sobrien if (cache_ptr->howto != 0) 834130561Sobrien ; 835130561Sobrien else if (raw[7] & callj_mask) 836130561Sobrien { 837130561Sobrien cache_ptr->howto = &howto_reloc_callj; 838130561Sobrien } 839130561Sobrien else if ( raw[7] & pcrel_mask) 840130561Sobrien { 841130561Sobrien if (raw[7] & size_mask) 842130561Sobrien cache_ptr->howto = &howto_reloc_pcrel13; 843130561Sobrien else 844130561Sobrien cache_ptr->howto = &howto_reloc_pcrel24; 845130561Sobrien } 846130561Sobrien else 847130561Sobrien { 848130561Sobrien if (raw[7] & incode_mask) 849130561Sobrien cache_ptr->howto = &howto_reloc_abs32code; 850130561Sobrien else 851130561Sobrien cache_ptr->howto = &howto_reloc_abs32; 852130561Sobrien } 853130561Sobrien 854130561Sobrien if (cache_ptr->address < prev_addr) 855130561Sobrien { 856130561Sobrien /* Ouch! this reloc is out of order, insert into the right place. */ 857130561Sobrien arelent tmp; 858130561Sobrien arelent *cursor = cache_ptr-1; 859130561Sobrien bfd_vma stop = cache_ptr->address; 860130561Sobrien 861130561Sobrien tmp = *cache_ptr; 862130561Sobrien while (cursor->address > stop && cursor >= reloc_cache) 863130561Sobrien { 864130561Sobrien cursor[1] = cursor[0]; 865130561Sobrien cursor--; 866130561Sobrien } 867130561Sobrien 868130561Sobrien cursor[1] = tmp; 869130561Sobrien } 870130561Sobrien else 871218822Sdim prev_addr = cache_ptr->address; 872130561Sobrien } 873130561Sobrien 874130561Sobrien if (relocs != NULL) 875130561Sobrien free (relocs); 876130561Sobrien asect->relocation = reloc_cache; 877130561Sobrien asect->reloc_count = count; 878130561Sobrien 879130561Sobrien return TRUE; 880130561Sobrien} 881130561Sobrien 882130561Sobrien/* This is stupid. This function should be a boolean predicate. */ 883130561Sobrien 884130561Sobrienstatic long 885218822Sdimb_out_canonicalize_reloc (bfd *abfd, 886218822Sdim sec_ptr section, 887218822Sdim arelent **relptr, 888218822Sdim asymbol **symbols) 889130561Sobrien{ 890130561Sobrien arelent *tblptr; 891130561Sobrien unsigned int count; 892130561Sobrien 893130561Sobrien if ((section->flags & SEC_CONSTRUCTOR) != 0) 894130561Sobrien { 895130561Sobrien arelent_chain *chain = section->constructor_chain; 896130561Sobrien 897130561Sobrien for (count = 0; count < section->reloc_count; count++) 898130561Sobrien { 899130561Sobrien *relptr++ = &chain->relent; 900130561Sobrien chain = chain->next; 901130561Sobrien } 902130561Sobrien } 903130561Sobrien else 904130561Sobrien { 905130561Sobrien if (section->relocation == NULL 906130561Sobrien && ! b_out_slurp_reloc_table (abfd, section, symbols)) 907130561Sobrien return -1; 908130561Sobrien 909130561Sobrien tblptr = section->relocation; 910130561Sobrien for (count = 0; count++ < section->reloc_count;) 911130561Sobrien *relptr++ = tblptr++; 912130561Sobrien } 913130561Sobrien 914130561Sobrien *relptr = NULL; 915130561Sobrien 916130561Sobrien return section->reloc_count; 917130561Sobrien} 918130561Sobrien 919130561Sobrienstatic long 920218822Sdimb_out_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) 921130561Sobrien{ 922130561Sobrien if (bfd_get_format (abfd) != bfd_object) 923130561Sobrien { 924130561Sobrien bfd_set_error (bfd_error_invalid_operation); 925130561Sobrien return -1; 926130561Sobrien } 927130561Sobrien 928130561Sobrien if (asect->flags & SEC_CONSTRUCTOR) 929130561Sobrien return sizeof (arelent *) * (asect->reloc_count + 1); 930130561Sobrien 931130561Sobrien if (asect == obj_datasec (abfd)) 932130561Sobrien return (sizeof (arelent *) * 933218822Sdim ((exec_hdr (abfd)->a_drsize / sizeof (struct relocation_info)) 934218822Sdim + 1)); 935130561Sobrien 936130561Sobrien if (asect == obj_textsec (abfd)) 937130561Sobrien return (sizeof (arelent *) * 938218822Sdim ((exec_hdr (abfd)->a_trsize / sizeof (struct relocation_info)) 939218822Sdim + 1)); 940130561Sobrien 941130561Sobrien if (asect == obj_bsssec (abfd)) 942130561Sobrien return 0; 943130561Sobrien 944130561Sobrien bfd_set_error (bfd_error_invalid_operation); 945130561Sobrien return -1; 946130561Sobrien} 947130561Sobrien 948130561Sobrien 949130561Sobrienstatic bfd_boolean 950218822Sdimb_out_set_section_contents (bfd *abfd, 951218822Sdim asection *section, 952218822Sdim const void * location, 953218822Sdim file_ptr offset, 954218822Sdim bfd_size_type count) 955130561Sobrien{ 956130561Sobrien if (! abfd->output_has_begun) 957130561Sobrien { 958130561Sobrien /* Set by bfd.c handler. */ 959130561Sobrien if (! aout_32_make_sections (abfd)) 960130561Sobrien return FALSE; 961130561Sobrien 962218822Sdim obj_textsec (abfd)->filepos = sizeof (struct external_exec); 963218822Sdim obj_datasec (abfd)->filepos = obj_textsec (abfd)->filepos 964218822Sdim + obj_textsec (abfd)->size; 965130561Sobrien } 966130561Sobrien 967130561Sobrien /* Regardless, once we know what we're doing, we might as well get going. */ 968130561Sobrien if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0) 969130561Sobrien return FALSE; 970130561Sobrien 971130561Sobrien if (count == 0) 972130561Sobrien return TRUE; 973130561Sobrien 974218822Sdim return bfd_bwrite ((void *) location, count, abfd) == count; 975130561Sobrien} 976130561Sobrien 977130561Sobrienstatic bfd_boolean 978218822Sdimb_out_set_arch_mach (bfd *abfd, 979218822Sdim enum bfd_architecture arch, 980218822Sdim unsigned long machine) 981130561Sobrien{ 982218822Sdim bfd_default_set_arch_mach (abfd, arch, machine); 983130561Sobrien 984130561Sobrien if (arch == bfd_arch_unknown) /* Unknown machine arch is OK. */ 985130561Sobrien return TRUE; 986130561Sobrien 987130561Sobrien if (arch == bfd_arch_i960) /* i960 default is OK. */ 988130561Sobrien switch (machine) 989130561Sobrien { 990130561Sobrien case bfd_mach_i960_core: 991130561Sobrien case bfd_mach_i960_kb_sb: 992130561Sobrien case bfd_mach_i960_mc: 993130561Sobrien case bfd_mach_i960_xa: 994130561Sobrien case bfd_mach_i960_ca: 995130561Sobrien case bfd_mach_i960_ka_sa: 996130561Sobrien case bfd_mach_i960_jx: 997130561Sobrien case bfd_mach_i960_hx: 998130561Sobrien case 0: 999130561Sobrien return TRUE; 1000130561Sobrien default: 1001130561Sobrien return FALSE; 1002130561Sobrien } 1003130561Sobrien 1004130561Sobrien return FALSE; 1005130561Sobrien} 1006130561Sobrien 1007130561Sobrienstatic int 1008218822Sdimb_out_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED, 1009218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 1010130561Sobrien{ 1011218822Sdim return sizeof (struct external_exec); 1012130561Sobrien} 1013130561Sobrien 1014130561Sobrienstatic void 1015218822Sdimperform_slip (bfd *abfd, 1016218822Sdim unsigned int slip, 1017218822Sdim asection *input_section, 1018218822Sdim bfd_vma value) 1019130561Sobrien{ 1020130561Sobrien asymbol **s; 1021130561Sobrien 1022130561Sobrien s = _bfd_generic_link_get_symbols (abfd); 1023130561Sobrien BFD_ASSERT (s != (asymbol **) NULL); 1024130561Sobrien 1025130561Sobrien /* Find all symbols past this point, and make them know 1026130561Sobrien what's happened. */ 1027130561Sobrien while (*s) 1028130561Sobrien { 1029130561Sobrien asymbol *p = *s; 1030130561Sobrien 1031130561Sobrien if (p->section == input_section) 1032130561Sobrien { 1033130561Sobrien /* This was pointing into this section, so mangle it. */ 1034130561Sobrien if (p->value > value) 1035130561Sobrien { 1036130561Sobrien p->value -=slip; 1037130561Sobrien 1038130561Sobrien if (p->udata.p != NULL) 1039130561Sobrien { 1040130561Sobrien struct generic_link_hash_entry *h; 1041130561Sobrien 1042130561Sobrien h = (struct generic_link_hash_entry *) p->udata.p; 1043130561Sobrien BFD_ASSERT (h->root.type == bfd_link_hash_defined); 1044130561Sobrien h->root.u.def.value -= slip; 1045130561Sobrien BFD_ASSERT (h->root.u.def.value == p->value); 1046130561Sobrien } 1047130561Sobrien } 1048130561Sobrien } 1049130561Sobrien s++; 1050130561Sobrien } 1051130561Sobrien} 1052130561Sobrien 1053130561Sobrien/* This routine works out if the thing we want to get to can be 1054130561Sobrien reached with a 24bit offset instead of a 32 bit one. 1055130561Sobrien If it can, then it changes the amode. */ 1056130561Sobrien 1057130561Sobrienstatic int 1058218822Sdimabs32code (bfd *abfd, 1059218822Sdim asection *input_section, 1060218822Sdim arelent *r, 1061218822Sdim unsigned int shrink, 1062218822Sdim struct bfd_link_info *link_info) 1063130561Sobrien{ 1064130561Sobrien bfd_vma value = get_value (r, link_info, input_section); 1065130561Sobrien bfd_vma dot = output_addr (input_section) + r->address; 1066130561Sobrien bfd_vma gap; 1067130561Sobrien 1068130561Sobrien /* See if the address we're looking at within 2^23 bytes of where 1069130561Sobrien we are, if so then we can use a small branch rather than the 1070130561Sobrien jump we were going to. */ 1071130561Sobrien gap = value - (dot - shrink); 1072130561Sobrien 1073130561Sobrien if (-1 << 23 < (long)gap && (long)gap < 1 << 23) 1074130561Sobrien { 1075130561Sobrien /* Change the reloc type from 32bitcode possible 24, to 24bit 1076130561Sobrien possible 32. */ 1077130561Sobrien r->howto = &howto_reloc_abs32codeshrunk; 1078130561Sobrien /* The place to relc moves back by four bytes. */ 1079130561Sobrien r->address -=4; 1080130561Sobrien 1081130561Sobrien /* This will be four bytes smaller in the long run. */ 1082130561Sobrien shrink += 4 ; 1083130561Sobrien perform_slip (abfd, 4, input_section, r->address-shrink + 4); 1084130561Sobrien } 1085130561Sobrien 1086130561Sobrien return shrink; 1087130561Sobrien} 1088130561Sobrien 1089130561Sobrienstatic int 1090218822Sdimaligncode (bfd *abfd, 1091218822Sdim asection *input_section, 1092218822Sdim arelent *r, 1093218822Sdim unsigned int shrink) 1094130561Sobrien{ 1095130561Sobrien bfd_vma dot = output_addr (input_section) + r->address; 1096130561Sobrien bfd_vma gap; 1097130561Sobrien bfd_vma old_end; 1098130561Sobrien bfd_vma new_end; 1099130561Sobrien unsigned int shrink_delta; 1100130561Sobrien int size = r->howto->size; 1101130561Sobrien 1102130561Sobrien /* Reduce the size of the alignment so that it's still aligned but 1103130561Sobrien smaller - the current size is already the same size as or bigger 1104130561Sobrien than the alignment required. */ 1105130561Sobrien 1106130561Sobrien /* Calculate the first byte following the padding before we optimize. */ 1107130561Sobrien old_end = ((dot + size ) & ~size) + size+1; 1108130561Sobrien /* Work out where the new end will be - remember that we're smaller 1109130561Sobrien than we used to be. */ 1110130561Sobrien new_end = ((dot - shrink + size) & ~size); 1111130561Sobrien 1112130561Sobrien /* This is the new end. */ 1113130561Sobrien gap = old_end - ((dot + size) & ~size); 1114130561Sobrien 1115130561Sobrien shrink_delta = (old_end - new_end) - shrink; 1116130561Sobrien 1117130561Sobrien if (shrink_delta) 1118130561Sobrien { 1119130561Sobrien /* Change the reloc so that it knows how far to align to. */ 1120130561Sobrien r->howto = howto_done_align_table + (r->howto - howto_align_table); 1121130561Sobrien 1122130561Sobrien /* Encode the stuff into the addend - for future use we need to 1123130561Sobrien know how big the reloc used to be. */ 1124130561Sobrien r->addend = old_end - dot + r->address; 1125130561Sobrien 1126130561Sobrien /* This will be N bytes smaller in the long run, adjust all the symbols. */ 1127130561Sobrien perform_slip (abfd, shrink_delta, input_section, r->address - shrink); 1128130561Sobrien shrink += shrink_delta; 1129130561Sobrien } 1130130561Sobrien 1131130561Sobrien return shrink; 1132130561Sobrien} 1133130561Sobrien 1134130561Sobrienstatic bfd_boolean 1135218822Sdimb_out_bfd_relax_section (bfd *abfd, 1136218822Sdim asection *i, 1137218822Sdim struct bfd_link_info *link_info, 1138218822Sdim bfd_boolean *again) 1139130561Sobrien{ 1140130561Sobrien /* Get enough memory to hold the stuff. */ 1141130561Sobrien bfd *input_bfd = i->owner; 1142130561Sobrien asection *input_section = i; 1143130561Sobrien unsigned int shrink = 0 ; 1144130561Sobrien arelent **reloc_vector = NULL; 1145218822Sdim long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); 1146130561Sobrien 1147130561Sobrien if (reloc_size < 0) 1148130561Sobrien return FALSE; 1149130561Sobrien 1150130561Sobrien /* We only run this relaxation once. It might work to run it 1151130561Sobrien multiple times, but it hasn't been tested. */ 1152130561Sobrien *again = FALSE; 1153130561Sobrien 1154130561Sobrien if (reloc_size) 1155130561Sobrien { 1156130561Sobrien long reloc_count; 1157130561Sobrien 1158218822Sdim reloc_vector = bfd_malloc ((bfd_size_type) reloc_size); 1159130561Sobrien if (reloc_vector == NULL && reloc_size != 0) 1160130561Sobrien goto error_return; 1161130561Sobrien 1162130561Sobrien /* Get the relocs and think about them. */ 1163130561Sobrien reloc_count = 1164130561Sobrien bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, 1165130561Sobrien _bfd_generic_link_get_symbols (input_bfd)); 1166130561Sobrien if (reloc_count < 0) 1167130561Sobrien goto error_return; 1168130561Sobrien if (reloc_count > 0) 1169130561Sobrien { 1170130561Sobrien arelent **parent; 1171130561Sobrien 1172130561Sobrien for (parent = reloc_vector; *parent; parent++) 1173130561Sobrien { 1174130561Sobrien arelent *r = *parent; 1175130561Sobrien 1176130561Sobrien switch (r->howto->type) 1177130561Sobrien { 1178130561Sobrien case ALIGNER: 1179130561Sobrien /* An alignment reloc. */ 1180130561Sobrien shrink = aligncode (abfd, input_section, r, shrink); 1181130561Sobrien break; 1182130561Sobrien case ABS32CODE: 1183130561Sobrien /* A 32bit reloc in an addressing mode. */ 1184130561Sobrien shrink = abs32code (input_bfd, input_section, r, shrink, 1185130561Sobrien link_info); 1186130561Sobrien break; 1187130561Sobrien case ABS32CODE_SHRUNK: 1188130561Sobrien shrink += 4; 1189130561Sobrien break; 1190130561Sobrien } 1191130561Sobrien } 1192130561Sobrien } 1193130561Sobrien } 1194218822Sdim input_section->size -= shrink; 1195130561Sobrien 1196130561Sobrien if (reloc_vector != NULL) 1197130561Sobrien free (reloc_vector); 1198130561Sobrien return TRUE; 1199130561Sobrien error_return: 1200130561Sobrien if (reloc_vector != NULL) 1201130561Sobrien free (reloc_vector); 1202130561Sobrien return FALSE; 1203130561Sobrien} 1204130561Sobrien 1205130561Sobrienstatic bfd_byte * 1206218822Sdimb_out_bfd_get_relocated_section_contents (bfd *output_bfd, 1207218822Sdim struct bfd_link_info *link_info, 1208218822Sdim struct bfd_link_order *link_order, 1209218822Sdim bfd_byte *data, 1210218822Sdim bfd_boolean relocatable, 1211218822Sdim asymbol **symbols) 1212130561Sobrien{ 1213130561Sobrien /* Get enough memory to hold the stuff. */ 1214130561Sobrien bfd *input_bfd = link_order->u.indirect.section->owner; 1215130561Sobrien asection *input_section = link_order->u.indirect.section; 1216218822Sdim long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); 1217130561Sobrien arelent **reloc_vector = NULL; 1218130561Sobrien long reloc_count; 1219130561Sobrien 1220130561Sobrien if (reloc_size < 0) 1221130561Sobrien goto error_return; 1222130561Sobrien 1223130561Sobrien /* If producing relocatable output, don't bother to relax. */ 1224130561Sobrien if (relocatable) 1225130561Sobrien return bfd_generic_get_relocated_section_contents (output_bfd, link_info, 1226130561Sobrien link_order, 1227130561Sobrien data, relocatable, 1228130561Sobrien symbols); 1229130561Sobrien 1230218822Sdim reloc_vector = bfd_malloc ((bfd_size_type) reloc_size); 1231130561Sobrien if (reloc_vector == NULL && reloc_size != 0) 1232130561Sobrien goto error_return; 1233130561Sobrien 1234130561Sobrien /* Read in the section. */ 1235130561Sobrien BFD_ASSERT (bfd_get_section_contents (input_bfd, 1236130561Sobrien input_section, 1237130561Sobrien data, 1238130561Sobrien (bfd_vma) 0, 1239218822Sdim input_section->size)); 1240130561Sobrien 1241130561Sobrien reloc_count = bfd_canonicalize_reloc (input_bfd, 1242130561Sobrien input_section, 1243130561Sobrien reloc_vector, 1244130561Sobrien symbols); 1245130561Sobrien if (reloc_count < 0) 1246130561Sobrien goto error_return; 1247130561Sobrien if (reloc_count > 0) 1248130561Sobrien { 1249130561Sobrien arelent **parent = reloc_vector; 1250130561Sobrien arelent *reloc ; 1251130561Sobrien unsigned int dst_address = 0; 1252130561Sobrien unsigned int src_address = 0; 1253130561Sobrien unsigned int run; 1254130561Sobrien unsigned int idx; 1255130561Sobrien 1256130561Sobrien /* Find how long a run we can do. */ 1257130561Sobrien while (dst_address < link_order->size) 1258130561Sobrien { 1259130561Sobrien reloc = *parent; 1260130561Sobrien if (reloc) 1261130561Sobrien { 1262130561Sobrien /* Note that the relaxing didn't tie up the addresses in the 1263130561Sobrien relocation, so we use the original address to work out the 1264130561Sobrien run of non-relocated data. */ 1265130561Sobrien BFD_ASSERT (reloc->address >= src_address); 1266130561Sobrien run = reloc->address - src_address; 1267130561Sobrien parent++; 1268130561Sobrien } 1269130561Sobrien else 1270218822Sdim run = link_order->size - dst_address; 1271130561Sobrien 1272130561Sobrien /* Copy the bytes. */ 1273130561Sobrien for (idx = 0; idx < run; idx++) 1274130561Sobrien data[dst_address++] = data[src_address++]; 1275130561Sobrien 1276130561Sobrien /* Now do the relocation. */ 1277130561Sobrien if (reloc) 1278130561Sobrien { 1279130561Sobrien switch (reloc->howto->type) 1280130561Sobrien { 1281130561Sobrien case ABS32CODE: 1282130561Sobrien calljx_callback (input_bfd, link_info, reloc, 1283130561Sobrien src_address + data, dst_address + data, 1284130561Sobrien input_section); 1285130561Sobrien src_address += 4; 1286130561Sobrien dst_address += 4; 1287130561Sobrien break; 1288130561Sobrien case ABS32: 1289130561Sobrien bfd_put_32 (input_bfd, 1290130561Sobrien (bfd_get_32 (input_bfd, data + src_address) 1291130561Sobrien + get_value (reloc, link_info, input_section)), 1292130561Sobrien data + dst_address); 1293130561Sobrien src_address += 4; 1294130561Sobrien dst_address += 4; 1295130561Sobrien break; 1296130561Sobrien case CALLJ: 1297130561Sobrien callj_callback (input_bfd, link_info, reloc, data, 1298130561Sobrien src_address, dst_address, input_section, 1299130561Sobrien FALSE); 1300130561Sobrien src_address += 4; 1301130561Sobrien dst_address += 4; 1302130561Sobrien break; 1303130561Sobrien case ALIGNDONE: 1304130561Sobrien BFD_ASSERT (reloc->addend >= src_address); 1305130561Sobrien BFD_ASSERT ((bfd_vma) reloc->addend 1306218822Sdim <= input_section->size); 1307130561Sobrien src_address = reloc->addend; 1308130561Sobrien dst_address = ((dst_address + reloc->howto->size) 1309130561Sobrien & ~reloc->howto->size); 1310130561Sobrien break; 1311130561Sobrien case ABS32CODE_SHRUNK: 1312130561Sobrien /* This used to be a callx, but we've found out that a 1313130561Sobrien callj will reach, so do the right thing. */ 1314130561Sobrien callj_callback (input_bfd, link_info, reloc, data, 1315130561Sobrien src_address + 4, dst_address, input_section, 1316130561Sobrien TRUE); 1317130561Sobrien dst_address += 4; 1318130561Sobrien src_address += 8; 1319130561Sobrien break; 1320130561Sobrien case PCREL24: 1321130561Sobrien { 1322130561Sobrien long int word = bfd_get_32 (input_bfd, 1323130561Sobrien data + src_address); 1324130561Sobrien bfd_vma value; 1325130561Sobrien 1326130561Sobrien value = get_value (reloc, link_info, input_section); 1327130561Sobrien word = ((word & ~BAL_MASK) 1328130561Sobrien | (((word & BAL_MASK) 1329130561Sobrien + value 1330130561Sobrien - output_addr (input_section) 1331130561Sobrien + reloc->addend) 1332130561Sobrien & BAL_MASK)); 1333130561Sobrien 1334130561Sobrien bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address); 1335130561Sobrien dst_address += 4; 1336130561Sobrien src_address += 4; 1337130561Sobrien 1338130561Sobrien } 1339130561Sobrien break; 1340130561Sobrien case PCREL13: 1341130561Sobrien { 1342130561Sobrien long int word = bfd_get_32 (input_bfd, 1343130561Sobrien data + src_address); 1344130561Sobrien bfd_vma value; 1345130561Sobrien 1346130561Sobrien value = get_value (reloc, link_info, input_section); 1347130561Sobrien word = ((word & ~PCREL13_MASK) 1348130561Sobrien | (((word & PCREL13_MASK) 1349130561Sobrien + value 1350130561Sobrien + reloc->addend 1351130561Sobrien - output_addr (input_section)) 1352130561Sobrien & PCREL13_MASK)); 1353130561Sobrien 1354130561Sobrien bfd_put_32 (input_bfd, (bfd_vma) word, data + dst_address); 1355130561Sobrien dst_address += 4; 1356130561Sobrien src_address += 4; 1357130561Sobrien } 1358130561Sobrien break; 1359130561Sobrien 1360130561Sobrien default: 1361130561Sobrien abort (); 1362130561Sobrien } 1363130561Sobrien } 1364130561Sobrien } 1365130561Sobrien } 1366130561Sobrien if (reloc_vector != NULL) 1367130561Sobrien free (reloc_vector); 1368130561Sobrien return data; 1369130561Sobrien error_return: 1370130561Sobrien if (reloc_vector != NULL) 1371130561Sobrien free (reloc_vector); 1372130561Sobrien return NULL; 1373130561Sobrien} 1374130561Sobrien 1375130561Sobrien 1376130561Sobrien/* Build the transfer vectors for Big and Little-Endian B.OUT files. */ 1377130561Sobrien 1378218822Sdim#define aout_32_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 1379218822Sdim#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info 1380218822Sdim#define b_out_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 1381218822Sdim#define b_out_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 1382218822Sdim#define b_out_bfd_link_add_symbols _bfd_generic_link_add_symbols 1383218822Sdim#define b_out_bfd_link_just_syms _bfd_generic_link_just_syms 1384218822Sdim#define b_out_bfd_final_link _bfd_generic_final_link 1385218822Sdim#define b_out_bfd_link_split_section _bfd_generic_link_split_section 1386218822Sdim#define b_out_bfd_gc_sections bfd_generic_gc_sections 1387218822Sdim#define b_out_bfd_merge_sections bfd_generic_merge_sections 1388218822Sdim#define b_out_bfd_is_group_section bfd_generic_is_group_section 1389218822Sdim#define b_out_bfd_discard_group bfd_generic_discard_group 1390218822Sdim#define b_out_section_already_linked _bfd_generic_section_already_linked 1391218822Sdim#define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 1392130561Sobrien 1393130561Sobrienextern const bfd_target b_out_vec_little_host; 1394130561Sobrien 1395130561Sobrienconst bfd_target b_out_vec_big_host = 1396130561Sobrien{ 1397218822Sdim "b.out.big", /* Name. */ 1398130561Sobrien bfd_target_aout_flavour, 1399218822Sdim BFD_ENDIAN_LITTLE, /* Data byte order. */ 1400218822Sdim BFD_ENDIAN_BIG, /* Header byte order. */ 1401218822Sdim (HAS_RELOC | EXEC_P | /* Object flags. */ 1402130561Sobrien HAS_LINENO | HAS_DEBUG | 1403130561Sobrien HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ), 1404130561Sobrien (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 1405218822Sdim '_', /* Symbol leading char. */ 1406218822Sdim ' ', /* AR_pad_char. */ 1407218822Sdim 16, /* AR_max_namelen. */ 1408130561Sobrien 1409130561Sobrien bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1410130561Sobrien bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1411218822Sdim bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 1412130561Sobrien bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1413130561Sobrien bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1414218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 1415218822Sdim {_bfd_dummy_target, b_out_object_p, /* bfd_check_format. */ 1416130561Sobrien bfd_generic_archive_p, _bfd_dummy_target}, 1417218822Sdim {bfd_false, b_out_mkobject, /* bfd_set_format. */ 1418130561Sobrien _bfd_generic_mkarchive, bfd_false}, 1419218822Sdim {bfd_false, b_out_write_object_contents, /* bfd_write_contents. */ 1420130561Sobrien _bfd_write_archive_contents, bfd_false}, 1421130561Sobrien 1422130561Sobrien BFD_JUMP_TABLE_GENERIC (aout_32), 1423130561Sobrien BFD_JUMP_TABLE_COPY (_bfd_generic), 1424130561Sobrien BFD_JUMP_TABLE_CORE (_bfd_nocore), 1425130561Sobrien BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd), 1426130561Sobrien BFD_JUMP_TABLE_SYMBOLS (aout_32), 1427130561Sobrien BFD_JUMP_TABLE_RELOCS (b_out), 1428130561Sobrien BFD_JUMP_TABLE_WRITE (b_out), 1429130561Sobrien BFD_JUMP_TABLE_LINK (b_out), 1430130561Sobrien BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1431130561Sobrien 1432130561Sobrien & b_out_vec_little_host, 1433130561Sobrien 1434218822Sdim NULL 1435130561Sobrien}; 1436130561Sobrien 1437130561Sobrienconst bfd_target b_out_vec_little_host = 1438130561Sobrien{ 1439218822Sdim "b.out.little", /* Name. */ 1440130561Sobrien bfd_target_aout_flavour, 1441218822Sdim BFD_ENDIAN_LITTLE, /* Data byte order. */ 1442218822Sdim BFD_ENDIAN_LITTLE, /* Header byte order. */ 1443218822Sdim (HAS_RELOC | EXEC_P | /* Object flags. */ 1444130561Sobrien HAS_LINENO | HAS_DEBUG | 1445130561Sobrien HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ), 1446130561Sobrien (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 1447218822Sdim '_', /* Symbol leading char. */ 1448218822Sdim ' ', /* AR_pad_char. */ 1449218822Sdim 16, /* AR_max_namelen. */ 1450130561Sobrien bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1451130561Sobrien bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1452218822Sdim bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 1453130561Sobrien bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1454130561Sobrien bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1455218822Sdim bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Headers. */ 1456130561Sobrien 1457218822Sdim {_bfd_dummy_target, b_out_object_p, /* bfd_check_format. */ 1458130561Sobrien bfd_generic_archive_p, _bfd_dummy_target}, 1459218822Sdim {bfd_false, b_out_mkobject, /* bfd_set_format. */ 1460130561Sobrien _bfd_generic_mkarchive, bfd_false}, 1461218822Sdim {bfd_false, b_out_write_object_contents, /* bfd_write_contents. */ 1462130561Sobrien _bfd_write_archive_contents, bfd_false}, 1463130561Sobrien 1464130561Sobrien BFD_JUMP_TABLE_GENERIC (aout_32), 1465130561Sobrien BFD_JUMP_TABLE_COPY (_bfd_generic), 1466130561Sobrien BFD_JUMP_TABLE_CORE (_bfd_nocore), 1467130561Sobrien BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd), 1468130561Sobrien BFD_JUMP_TABLE_SYMBOLS (aout_32), 1469130561Sobrien BFD_JUMP_TABLE_RELOCS (b_out), 1470130561Sobrien BFD_JUMP_TABLE_WRITE (b_out), 1471130561Sobrien BFD_JUMP_TABLE_LINK (b_out), 1472130561Sobrien BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1473130561Sobrien 1474130561Sobrien & b_out_vec_big_host, 1475130561Sobrien 1476218822Sdim NULL 1477130561Sobrien}; 1478