diff --git a/CMakeLists.txt b/CMakeLists.txt index 4479765e42..32f12fdf39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,4 +52,6 @@ add_subdirectory(ResourceFiles) add_subdirectory(MakeAPPL) add_subdirectory(Rez) +add_subdirectory(MakePEF) + endif() diff --git a/MakePEF/CMakeLists.txt b/MakePEF/CMakeLists.txt new file mode 100644 index 0000000000..0aee5a4f0d --- /dev/null +++ b/MakePEF/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(MakePEF MakePEF.cc xcoff.h powerpc.h external.h) diff --git a/MakePEF/MakePEF.cc b/MakePEF/MakePEF.cc new file mode 100755 index 0000000000..cc6b2d6883 --- /dev/null +++ b/MakePEF/MakePEF.cc @@ -0,0 +1,658 @@ +#include +#include +#include +#include +#include +#include + +#include +#include /* PEFBinaryFormat.h */ +#include "powerpc.h" + +typedef unsigned bfd_size_type; +typedef unsigned bfd_vma; +#define SYMNMLEN 8 +#define PARAMS(x) x +struct bfd_link_hash_entry {}; +struct bfd_link_hash_table {}; +typedef int bfd; +typedef int asection; +typedef int bfd_boolean; +typedef char bfd_byte; + +#include "xcoff.h" + + /* n_sclass storage classes: */ +#define C_EFCN 0xFFU /* physical end of function */ +#define C_NULL 0U /* */ +#define C_AUTO 1U /* automatic variable */ +#define C_EXT 2U /* external symbol */ +#define C_STAT 3U /* static symbol */ +#define C_REG 4U /* register variable */ +#define C_EXTDEF 5U /* external definition */ +#define C_LABEL 6U /* label */ +#define C_ULABEL 7U /* undefined label */ +#define C_MOS 8U /* structure member */ +#define C_ARG 9U /* function argument */ +#define C_STRTAG 10U /* structure tag */ +#define C_MOU 11U /* union member */ +#define C_UNTAG 12U /* union tag */ +#define C_TPDEF 13U /* type definition */ +#define C_USTATIC 14U /* uninitialized static */ +#define C_ENTAG 15U /* enumeration tag */ +#define C_MOE 16U /* enumeration member */ +#define C_REGPARM 17U /* register argument */ +#define C_FIELD 18U /* bit field */ +#define C_BLOCK 100U /* ".bb" or ".eb" */ +#define C_FCN 101U /* ".bf" or ".ef" */ +#define C_EOS 102U /* end of structure */ +#define C_FILE 103U /* file name */ +#define C_LINE 104U /* utility program use (?) */ +#define C_ALIAS 105U /* duplicate tag */ +#define C_HIDDEN 106U /* unnamed static symbol */ +#define C_HIDEXT 107U /* unnamed external symbol */ +#define C_BINCL 108U /* beginning of include file */ +#define C_EINCL 109U /* end of include file */ +//#define C_INFO 110U /* special information */ + + +bool verboseFlag = false; + +inline int getI16(char *x) +{ + return *(short*)x; +} + +inline int getI32(char *x) +{ + return *(int*)x; +} + +class ImportLib +{ +public: + std::string path, base, mem; + std::vector imports; + + int nameOffset; + bool weak; + + std::vector symNameOffsets; + + ImportLib(std::string path, std::string base, std::string mem) + : path(path), base(base), mem(mem), weak(false) + { + } +}; + +void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__start" ) +{ + external_filehdr xcoffHeader; + //external_aouthdr xcoffAoutHeader; + + in.read((char*) &xcoffHeader, sizeof(xcoffHeader)); + //assert(getI16(xcoffHeader.f_opthdr) == sizeof(xcoffAoutHeader)); + //in.read((char*) &xcoffAoutHeader, sizeof(xcoffAoutHeader)); + in.seekg(getI16(xcoffHeader.f_opthdr),std::ios_base::cur); + + if(verboseFlag) + std::cerr << "flags: " << std::hex << getI16(xcoffHeader.f_flags) << std::dec << std::endl; + //return; + int nSections = getI16(xcoffHeader.f_nscns); + + PEFContainerHeader pefHeader; + + memset(&pefHeader,0,sizeof(pefHeader)); + + pefHeader.tag1 = kPEFTag1; + pefHeader.tag2 = kPEFTag2; + pefHeader.architecture = 'pwpc'; + pefHeader.formatVersion = kPEFVersion; + pefHeader.sectionCount = 3; // .text, .data, .loader + pefHeader.instSectionCount = 2; // .text, .data + + std::map xcoffSections; + std::map xcoffSectionNumbers; + std::map xcoffSectionNames; + std::map pefSectionNumbers; + + pefSectionNumbers[".text"] = 0; + pefSectionNumbers[".data"] = 1; + + for(int i=0;i importLibs; + std::vector relocInstructions; + //std::vector importIndices; + std::map importSources; + std::map importedSymbolIndices; + std::set importedSymbolSet; + int totalImportedSyms = 0; + { + external_scnhdr xcoffLoaderSection = xcoffSections[".loader"]; + internal_ldhdr xcoffLoaderHeader; + + char * loaderSectionPtr = (char*)alloca(getI32(xcoffLoaderSection.s_size)); + in.seekg(getI32(xcoffLoaderSection.s_scnptr)); + in.read(loaderSectionPtr, getI32(xcoffLoaderSection.s_size)); + + xcoffLoaderHeader = *(internal_ldhdr*)loaderSectionPtr; + + char *p = loaderSectionPtr + xcoffLoaderHeader.l_impoff; + for(unsigned i=0; il_smtype & 0xF8) == L_IMPORT) + { + int importIndex = importIndices[relocs[i].l_symndx]; + assert(importIndex != -1); + relocInstructions.push_back( + PEFRelocComposeLgByImport_1st(importIndex)); + relocInstructions.push_back( + PEFRelocComposeLgByImport_2nd(importIndex)); + } + else + { + if(verboseFlag) + std::cerr << "symbol from sect: " << sym->l_scnum << std::endl; + if(sym->l_scnum == 1) + { + relocInstructions.push_back(PEFRelocComposeBySectC(1)); + } + else if(sym->l_scnum == 2) + { + relocInstructions.push_back(PEFRelocComposeBySectD(1)); + } + else + assert(false); + } + } +#endif + } + + PEFLoaderInfoHeader loaderInfoHeader; + memset(&loaderInfoHeader, 0, sizeof(loaderInfoHeader)); + + loaderInfoHeader.mainSection = -1; + loaderInfoHeader.initSection = -1; + loaderInfoHeader.termSection = -1; + + { + + in.seekg(getI32(xcoffHeader.f_symptr) + + getI32(xcoffHeader.f_nsyms) * sizeof(external_syment)); + int stringTableLen = 0; + + if(verboseFlag) + std::cerr << "tell: " << in.tellg() << std::endl; + in.read((char*)&stringTableLen, 4); + if(verboseFlag) + std::cerr << "string table len: " << stringTableLen << std::endl; + char *stringTable = new char[stringTableLen+1]; + if(stringTableLen != 0) + { + *(int*)stringTable = stringTableLen; + if(stringTableLen > 4) + in.read(stringTable+4, stringTableLen-5); + stringTable[stringTableLen-1] = 0; + } + + if(verboseFlag) + { + std::cerr << "tell: " << in.tellg() << std::endl; + std::cerr << "seeking to symptr: " << getI32(xcoffHeader.f_symptr) << std::endl; + } + in.seekg(getI32(xcoffHeader.f_symptr),std::ios::beg); + + if(verboseFlag) + std::cerr << "tell: " << in.tellg() << std::endl; + + int nSymEntries = getI32(xcoffHeader.f_nsyms); + std::vector syms(nSymEntries); + in.read((char*) &syms[0], sizeof(external_syment)*nSymEntries); + + std::vector symNames; + + for(int i=0; i < nSymEntries; i++) + { + external_syment ent = syms[i]; + + std::string name; + if(getI32(ent.e.e.e_zeroes) == 0) + { + /*char buf[256]; + sprintf(buf, "offset: %08x", getI32(ent.e.e.e_offset)); + name = buf; + //loaderSectionPtr + xcoffLoaderHeader.l_stoff + // + syms[i]._l._l_l._l_offset;*/ + //std::cerr << "name offset = " << std::hex + // << getI32(ent.e.e.e_offset) << std::dec << std::endl; + if(getI16(ent.e_scnum) == -2) + name = "#debug#"; + else + name = stringTable + getI32(ent.e.e.e_offset); + + } + else + name = ent.e.e_name; + if(verboseFlag) + { + std::cerr << "[" << i << "] Symbol: " << name << std::hex + << " e_value: " << getI32(ent.e_value) + << " e_scnum: " << getI16(ent.e_scnum) + << " e_type: " << getI16(ent.e_type) + << " e_sclass: " << (int)ent.e_sclass[0] + << std::dec << std::endl; + } + symNames.push_back(name); + for(int j=0; j loaderStringTable; + int loaderStringTableSize = 0; + + for(unsigned i=1;i 6) + { + if(name.substr(name.length()-6,6) == "__weak") + { + name = name.substr(0,name.length()-6); + imp.weak = true; + } + } + + if(verboseFlag) + { + std::cerr << "PEF name \"" << name << '"'; + if(imp.weak) + std::cerr << " (weak)"; + std::cerr << " at " << std::hex << loaderStringTableSize << std::dec + << std::endl; + } + importLibs[i].nameOffset = loaderStringTableSize; + loaderStringTable.push_back(name); + loaderStringTableSize += name.length() + 1; + + for(unsigned j=0;j= argc) + { + std::cerr << "makepef: -o requires an argument.\n"; + return 1; + } + if(hadOutput) + { + std::cerr << "makepef: -o can only be used once.\n"; + return 1; + } + outputFn = argv[i]; + hadOutput = true; + } + else + { + if(hadInput) + { + std::cerr << "makepef: can only handle one input file.\n"; + return 1; + } + inputFn = argv[i]; + hadInput = true; + } + } + if(!hadInput) + { + std::cerr << "makepef: no input file specified.\n"; + return 1; + } + + if(!hadOutput) + { + std::cerr << "makepef: no output file specified.\n"; + return 1; + } + std::ifstream in(inputFn.c_str()); + std::ofstream out(outputFn.c_str()); + mkpef(in, out); + return 0; +} + diff --git a/MakePEF/external.h b/MakePEF/external.h new file mode 100755 index 0000000000..19636dab7d --- /dev/null +++ b/MakePEF/external.h @@ -0,0 +1,254 @@ +/* external.h -- External COFF structures + + Copyright 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef COFF_EXTERNAL_H +#define COFF_EXTERNAL_H + +#ifndef DO_NOT_DEFINE_FILHDR +/********************** FILE HEADER **********************/ + +struct external_filehdr + { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ + }; + +#define FILHDR struct external_filehdr +#define FILHSZ 20 +#endif + +#ifndef DO_NOT_DEFINE_AOUTHDR +/********************** AOUT "OPTIONAL HEADER" **********************/ + +typedef struct external_aouthdr + { + char magic[2]; /* type of file */ + char vstamp[2]; /* version stamp */ + char tsize[4]; /* text size in bytes, padded to FW bdry*/ + char dsize[4]; /* initialized data " " */ + char bsize[4]; /* uninitialized data " " */ + char entry[4]; /* entry pt. */ + char text_start[4]; /* base of text used for this file */ + char data_start[4]; /* base of data used for this file */ + } +AOUTHDR; + +#define AOUTHDRSZ 28 +#define AOUTSZ 28 +#endif + +#ifndef DO_NOT_DEFINE_SCNHDR +/********************** SECTION HEADER **********************/ + +struct external_scnhdr + { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries */ + char s_flags[4]; /* flags */ + }; + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* Names of "special" sections. */ + +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _COMMENT ".comment" +#define _LIB ".lib" +#endif /* not DO_NOT_DEFINE_SCNHDR */ + +#ifndef DO_NOT_DEFINE_LINENO + +/********************** LINE NUMBERS **********************/ + +#ifndef L_LNNO_SIZE +#error L_LNNO_SIZE needs to be defined +#endif + +/* 1 line number entry for every "breakpointable" source line in a section. + Line numbers are grouped on a per function basis; first entry in a function + grouping will have l_lnno = 0 and in place of physical address will be the + symbol table index of the function name. */ +struct external_lineno +{ + union + { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + + char l_lnno[L_LNNO_SIZE]; /* line number */ +}; + +#define LINENO struct external_lineno +#define LINESZ (4 + L_LNNO_SIZE) + +#if L_LNNO_SIZE == 4 +#define GET_LINENO_LNNO(abfd, ext) H_GET_32 (abfd, (ext->l_lnno)) +#define PUT_LINENO_LNNO(abfd, val, ext) H_PUT_32 (abfd, val, (ext->l_lnno)) +#endif +#if L_LNNO_SIZE == 2 +#define GET_LINENO_LNNO(abfd, ext) H_GET_16 (abfd, (ext->l_lnno)) +#define PUT_LINENO_LNNO(abfd, val, ext) H_PUT_16 (abfd, val, (ext->l_lnno)) +#endif + +#endif /* not DO_NOT_DEFINE_LINENO */ + +#ifndef DO_NOT_DEFINE_SYMENT +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#ifndef E_FILNMLEN +#define E_FILNMLEN 14 +#endif +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union + { + char e_name[E_SYMNMLEN]; + + struct + { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 + +#ifndef N_BTMASK +#define N_BTMASK 0xf +#endif + +#ifndef N_TMASK +#define N_TMASK 0x30 +#endif + +#ifndef N_BTSHFT +#define N_BTSHFT 4 +#endif + +#ifndef N_TSHIFT +#define N_TSHIFT 2 +#endif + +#endif /* not DO_NOT_DEFINE_SYMENT */ + +#ifndef DO_NOT_DEFINE_AUXENT + +union external_auxent +{ + struct + { + char x_tagndx[4]; /* str, un, or enum tag indx */ + + union + { + struct + { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + + char x_fsize[4]; /* size of function */ + + } x_misc; + + union + { + struct /* if ISFCN, tag, or .bb */ + { + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + + struct /* if ISARY, up to 4 dimen. */ + { + char x_dimen[E_DIMNUM][2]; + } x_ary; + + } x_fcnary; + + char x_tvndx[2]; /* tv index */ + + } x_sym; + + union + { + char x_fname[E_FILNMLEN]; + + struct + { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + + } x_file; + + struct + { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ +#ifdef INCLUDE_COMDAT_FIELDS_IN_AUXENT + char x_checksum[4]; /* section COMDAT checksum */ + char x_associated[2]; /* COMDAT associated section index */ + char x_comdat[1]; /* COMDAT selection number */ +#endif + } x_scn; + + struct + { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ +}; + +#define AUXENT union external_auxent +#define AUXESZ 18 + +#define _ETEXT "etext" + +#endif /* not DO_NOT_DEFINE_AUXENT */ + +#endif /* COFF_EXTERNAL_H */ diff --git a/MakePEF/powerpc.h b/MakePEF/powerpc.h new file mode 100755 index 0000000000..942ba8dcd1 --- /dev/null +++ b/MakePEF/powerpc.h @@ -0,0 +1,58 @@ +/* Basic coff information for the PowerPC + Based on coff/rs6000.h, coff/i386.h and others. + + Copyright 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Initial release: Kim Knuttila (krk@cygnus.com) */ +#define L_LNNO_SIZE 2 +#define INCLUDE_COMDAT_FIELDS_IN_AUXENT +#include "external.h" + +/* Bits for f_flags: + F_RELFLG relocation info stripped from file + F_EXEC file is executable (no unresolved external references) + F_LNNO line numbers stripped from file + F_LSYMS local symbols stripped from file + F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax). */ + +#define F_RELFLG (0x0001) +#define F_EXEC (0x0002) +#define F_LNNO (0x0004) +#define F_LSYMS (0x0008) + +/* extra NT defines */ +#define PPCMAGIC 0760 /* peeked on aa PowerPC Windows NT box */ +#define DOSMAGIC 0x5a4d /* from arm.h, i386.h */ +#define NT_SIGNATURE 0x00004550 /* from arm.h, i386.h */ + +/* from winnt.h */ +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b + +#define PPCBADMAG(x) ((x).f_magic != PPCMAGIC) + +/********************** RELOCATION DIRECTIVES **********************/ + +struct external_reloc +{ + char r_vaddr[4]; + char r_symndx[4]; + char r_type[2]; +}; + +#define RELOC struct external_reloc +#define RELSZ 10 + diff --git a/MakePEF/xcoff.h b/MakePEF/xcoff.h new file mode 100755 index 0000000000..b27cececb0 --- /dev/null +++ b/MakePEF/xcoff.h @@ -0,0 +1,639 @@ +/* Internal format of XCOFF object file data structures for BFD. + + Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. + Written by Ian Lance Taylor , Cygnus Support. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _INTERNAL_XCOFF_H +#define _INTERNAL_XCOFF_H + +/* Linker */ + +/* Names of "special" sections. */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" +#define _EXCEPT ".except" +#define _TYPCHK ".typchk" + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/* Specifies an exception section. A section of this type provides + information to identify the reason that a trap or ececptin occured within + and executable object program */ +#define STYP_EXCEPT 0x0100 + +/* Specifies a type check section. A section of this type contains parameter + argument type check strings used by the AIX binder. */ +#define STYP_TYPCHK 0x4000 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + +/* XCOFF relocation types. + The relocations are described in the function + xcoff[64]_ppc_relocate_section in coff64-rs6000.c and coff-rs6000.c */ + +#define R_POS (0x00) +#define R_NEG (0x01) +#define R_REL (0x02) +#define R_TOC (0x03) +#define R_RTB (0x04) +#define R_GL (0x05) +#define R_TCL (0x06) +#define R_BA (0x08) +#define R_BR (0x0a) +#define R_RL (0x0c) +#define R_RLA (0x0d) +#define R_REF (0x0f) +#define R_TRL (0x12) +#define R_TRLA (0x13) +#define R_RRTBI (0x14) +#define R_RRTBA (0x15) +#define R_CAI (0x16) +#define R_CREL (0x17) +#define R_RBA (0x18) +#define R_RBAC (0x19) +#define R_RBR (0x1a) +#define R_RBRC (0x1b) + +/* Storage class #defines, from /usr/include/storclass.h that are not already + defined in internal.h */ + +/* Comment string in .info section */ +#define C_INFO 110 + +/* Auxillary Symbol Entries */ + +/* x_smtyp values: */ +#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */ +#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ +/* Symbol type values: */ +#define XTY_ER 0 /* External reference */ +#define XTY_SD 1 /* Csect definition */ +#define XTY_LD 2 /* Label definition */ +#define XTY_CM 3 /* .BSS */ +#define XTY_EM 4 /* Error message */ +#define XTY_US 5 /* "Reserved for internal use" */ + +/* x_smclas values: */ +#define XMC_PR 0 /* Read-only program code */ +#define XMC_RO 1 /* Read-only constant */ +#define XMC_DB 2 /* Read-only debug dictionary table */ +#define XMC_TC 3 /* Read-write general TOC entry */ +#define XMC_UA 4 /* Read-write unclassified */ +#define XMC_RW 5 /* Read-write data */ +#define XMC_GL 6 /* Read-only global linkage */ +#define XMC_XO 7 /* Read-only extended operation */ +#define XMC_SV 8 /* Read-only supervisor call */ +#define XMC_BS 9 /* Read-write BSS */ +#define XMC_DS 10 /* Read-write descriptor csect */ +#define XMC_UC 11 /* Read-write unnamed Fortran common */ +#define XMC_TI 12 /* Read-only traceback index csect */ +#define XMC_TB 13 /* Read-only traceback table csect */ +/* 14 ??? */ +#define XMC_TC0 15 /* Read-write TOC anchor */ +#define XMC_TD 16 /* Read-write data in TOC */ +#define XMC_SV64 17 /* Read-only 64 bit supervisor call */ +#define XMC_SV3264 18 /* Read-only 32 or 64 bit supervisor call */ + +/* The ldhdr structure. This appears at the start of the .loader + section. */ + +struct internal_ldhdr +{ + /* The version number: + 1 : 32 bit + 2 : 64 bit */ + unsigned long l_version; + + /* The number of symbol table entries. */ + bfd_size_type l_nsyms; + + /* The number of relocation table entries. */ + bfd_size_type l_nreloc; + + /* The length of the import file string table. */ + bfd_size_type l_istlen; + + /* The number of import files. */ + bfd_size_type l_nimpid; + + /* The offset from the start of the .loader section to the first + entry in the import file table. */ + bfd_size_type l_impoff; + + /* The length of the string table. */ + bfd_size_type l_stlen; + + /* The offset from the start of the .loader section to the first + entry in the string table. */ + bfd_size_type l_stoff; + + /* The offset to start of the symbol table, only in XCOFF64 */ + bfd_vma l_symoff; + + /* The offset to the start of the relocation table, only in XCOFF64 */ + bfd_vma l_rldoff; +}; + +/* The ldsym structure. This is used to represent a symbol in the + .loader section. */ + +struct internal_ldsym +{ + union + { + /* The symbol name if <= SYMNMLEN characters. */ + char _l_name[SYMNMLEN]; + struct + { + /* Zero if the symbol name is more than SYMNMLEN characters. */ + long _l_zeroes; + + /* The offset in the string table if the symbol name is more + than SYMNMLEN characters. */ + long _l_offset; + } + _l_l; + } + _l; + + /* The symbol value. */ + bfd_vma l_value; + + /* The symbol section number. */ + short l_scnum; + + /* The symbol type and flags. */ + char l_smtype; + + /* The symbol storage class. */ + char l_smclas; + + /* The import file ID. */ + bfd_size_type l_ifile; + + /* Offset to the parameter type check string. */ + bfd_size_type l_parm; +}; + +/* These flags are for the l_smtype field (the lower three bits are an + XTY_* value). */ + +/* Imported symbol. */ +#define L_IMPORT (0x40) +/* Entry point. */ +#define L_ENTRY (0x20) +/* Exported symbol. */ +#define L_EXPORT (0x10) + +/* The ldrel structure. This is used to represent a reloc in the + .loader section. */ + +struct internal_ldrel +{ + /* The reloc address. */ + bfd_vma l_vaddr; + + /* The symbol table index in the .loader section symbol table. */ + bfd_size_type l_symndx; + + /* The relocation type and size. */ + short l_rtype; + + /* The section number this relocation applies to. */ + short l_rsecnm; +}; + +/* An entry in the XCOFF linker hash table. */ +struct xcoff_link_hash_entry +{ + struct bfd_link_hash_entry root; + + /* Symbol index in output file. Set to -1 initially. Set to -2 if + there is a reloc against this symbol. */ + long indx; + + /* If we have created a TOC entry for this symbol, this is the .tc + section which holds it. */ + asection *toc_section; + + union + { + /* If we have created a TOC entry (the XCOFF_SET_TOC flag is + set), this is the offset in toc_section. */ + bfd_vma toc_offset; + + /* If the TOC entry comes from an input file, this is set to the + symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */ + long toc_indx; + } + u; + + /* If this symbol is a function entry point which is called, this + field holds a pointer to the function descriptor. If this symbol + is a function descriptor, this field holds a pointer to the + function entry point. */ + struct xcoff_link_hash_entry *descriptor; + + /* The .loader symbol table entry, if there is one. */ + struct internal_ldsym *ldsym; + + /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table + index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set, + this is the l_ifile value. */ + long ldindx; + + /* Some linker flags. */ + unsigned long flags; + + /* The storage mapping class. */ + unsigned char smclas; +}; + +/* Flags for xcoff_link_hash_entry. */ + +/* Symbol is referenced by a regular object. */ +#define XCOFF_REF_REGULAR 0x00000001 +/* Symbol is defined by a regular object. */ +#define XCOFF_DEF_REGULAR 0x00000002 +/* Symbol is defined by a dynamic object. */ +#define XCOFF_DEF_DYNAMIC 0x00000004 +/* Symbol is used in a reloc being copied into the .loader section. */ +#define XCOFF_LDREL 0x00000008 +/* Symbol is the entry point. */ +#define XCOFF_ENTRY 0x00000010 +/* Symbol is called; this is, it appears in a R_BR reloc. */ +#define XCOFF_CALLED 0x00000020 +/* Symbol needs the TOC entry filled in. */ +#define XCOFF_SET_TOC 0x00000040 +/* Symbol is explicitly imported. */ +#define XCOFF_IMPORT 0x00000080 +/* Symbol is explicitly exported. */ +#define XCOFF_EXPORT 0x00000100 +/* Symbol has been processed by xcoff_build_ldsyms. */ +#define XCOFF_BUILT_LDSYM 0x00000200 +/* Symbol is mentioned by a section which was not garbage collected. */ +#define XCOFF_MARK 0x00000400 +/* Symbol size is recorded in size_list list from hash table. */ +#define XCOFF_HAS_SIZE 0x00000800 +/* Symbol is a function descriptor. */ +#define XCOFF_DESCRIPTOR 0x00001000 +/* Multiple definitions have been for the symbol. */ +#define XCOFF_MULTIPLY_DEFINED 0x00002000 +/* Symbol is the __rtinit symbol. */ +#define XCOFF_RTINIT 0x00004000 +/* Symbol is an imported 32 bit syscall. */ +#define XCOFF_SYSCALL32 0x00008000 +/* Symbol is an imported 64 bit syscall. */ +#define XCOFF_SYSCALL64 0x00010000 + +/* The XCOFF linker hash table. */ + +#define XCOFF_NUMBER_OF_SPECIAL_SECTIONS 6 +#define XCOFF_SPECIAL_SECTION_TEXT 0 +#define XCOFF_SPECIAL_SECTION_ETEXT 1 +#define XCOFF_SPECIAL_SECTION_DATA 2 +#define XCOFF_SPECIAL_SECTION_EDATA 3 +#define XCOFF_SPECIAL_SECTION_END 4 +#define XCOFF_SPECIAL_SECTION_END2 5 + +struct xcoff_link_hash_table +{ + struct bfd_link_hash_table root; + + /* The .debug string hash table. We need to compute this while + reading the input files, so that we know how large the .debug + section will be before we assign section positions. */ + struct bfd_strtab_hash *debug_strtab; + + /* The .debug section we will use for the final output. */ + asection *debug_section; + + /* The .loader section we will use for the final output. */ + asection *loader_section; + + /* A count of non TOC relative relocs which will need to be + allocated in the .loader section. */ + size_t ldrel_count; + + /* The .loader section header. */ + struct internal_ldhdr ldhdr; + + /* The .gl section we use to hold global linkage code. */ + asection *linkage_section; + + /* The .tc section we use to hold toc entries we build for global + linkage code. */ + asection *toc_section; + + /* The .ds section we use to hold function descriptors which we + create for exported symbols. */ + asection *descriptor_section; + + /* The list of import files. */ + struct xcoff_import_file *imports; + + /* Required alignment of sections within the output file. */ + unsigned long file_align; + + /* Whether the .text section must be read-only. */ + bfd_boolean textro; + + /* Whether garbage collection was done. */ + bfd_boolean gc; + + /* A linked list of symbols for which we have size information. */ + struct xcoff_link_size_list + { + struct xcoff_link_size_list *next; + struct xcoff_link_hash_entry *h; + bfd_size_type size; + } + *size_list; + + /* Magic sections: _text, _etext, _data, _edata, _end, end. */ + asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS]; +}; + + +/* This structure is used to pass information through + xcoff_link_hash_traverse. */ + +struct xcoff_loader_info +{ + /* Set if a problem occurred. */ + bfd_boolean failed; + + /* Output BFD. */ + bfd *output_bfd; + + /* Link information structure. */ + struct bfd_link_info *info; + + /* Whether all defined symbols should be exported. */ + bfd_boolean export_defineds; + + /* Number of ldsym structures. */ + size_t ldsym_count; + + /* Size of string table. */ + size_t string_size; + + /* String table. */ + bfd_byte *strings; + + /* Allocated size of string table. */ + size_t string_alc; +}; + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value + from smaller values. Start with zero, widen, *then* decrement. */ +#define MINUS_ONE (((bfd_vma) 0) - 1) + +/* __rtinit, from /usr/include/rtinit.h. */ +struct __rtinit +{ + /* Pointer to runtime linker. + XXX: Is the parameter really void? */ + int (*rtl) PARAMS ((void)); + + /* Offset to array of init functions, 0 if none. */ + int init_offset; + + /* Offset to array of fini functions, 0 if none. */ + int fini_offset; + + /* Size of __RTINIT_DESCRIPTOR. This value should be used instead of + sizeof(__RTINIT_DESCRIPTOR). */ + int __rtinit_descriptor_size; +}; + +#define RTINIT_DESCRIPTOR_SIZE (12) + +struct __rtinit_descriptor +{ + /* Init/fini function. */ + int f; + + /* Offset, relative to the start of the __rtinit symbol, to name of the + function. */ + + int name_offset; + + /* Flags */ + unsigned char flags; +}; + +/* Archive */ + +#define XCOFFARMAG "\012" +#define XCOFFARMAGBIG "\012" +#define SXCOFFARMAG 8 + +/* The size of the ascii archive elements */ +#define XCOFFARMAG_ELEMENT_SIZE 12 +#define XCOFFARMAGBIG_ELEMENT_SIZE 20 + +/* This terminates an XCOFF archive member name. */ + +#define XCOFFARFMAG "`\012" +#define SXCOFFARFMAG 2 + +/* XCOFF archives start with this (printable) structure. */ + +struct xcoff_ar_file_hdr +{ + /* Magic string. */ + char magic[SXCOFFARMAG]; + + /* Offset of the member table (decimal ASCII string). */ + char memoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* Offset of the global symbol table (decimal ASCII string). */ + char symoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* Offset of the first member in the archive (decimal ASCII string). */ + char firstmemoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* Offset of the last member in the archive (decimal ASCII string). */ + char lastmemoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* Offset of the first member on the free list (decimal ASCII + string). */ + char freeoff[XCOFFARMAG_ELEMENT_SIZE]; +}; + +#define SIZEOF_AR_FILE_HDR (SXCOFFARMAG + 5 * XCOFFARMAG_ELEMENT_SIZE) + +/* This is the equivalent data structure for the big archive format. */ + +struct xcoff_ar_file_hdr_big +{ + /* Magic string. */ + char magic[SXCOFFARMAG]; + + /* Offset of the member table (decimal ASCII string). */ + char memoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* Offset of the global symbol table for 32-bit objects (decimal ASCII + string). */ + char symoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* Offset of the global symbol table for 64-bit objects (decimal ASCII + string). */ + char symoff64[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* Offset of the first member in the archive (decimal ASCII string). */ + char firstmemoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* Offset of the last member in the archive (decimal ASCII string). */ + char lastmemoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* Offset of the first member on the free list (decimal ASCII + string). */ + char freeoff[XCOFFARMAGBIG_ELEMENT_SIZE]; +}; + +#define SIZEOF_AR_FILE_HDR_BIG (SXCOFFARMAG + 6 * XCOFFARMAGBIG_ELEMENT_SIZE) + +/* Each XCOFF archive member starts with this (printable) structure. */ + +struct xcoff_ar_hdr +{ + /* File size not including the header (decimal ASCII string). */ + char size[XCOFFARMAG_ELEMENT_SIZE]; + + /* File offset of next archive member (decimal ASCII string). */ + char nextoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* File offset of previous archive member (decimal ASCII string). */ + char prevoff[XCOFFARMAG_ELEMENT_SIZE]; + + /* File mtime (decimal ASCII string). */ + char date[12]; + + /* File UID (decimal ASCII string). */ + char uid[12]; + + /* File GID (decimal ASCII string). */ + char gid[12]; + + /* File mode (octal ASCII string). */ + char mode[12]; + + /* Length of file name (decimal ASCII string). */ + char namlen[4]; + + /* This structure is followed by the file name. The length of the + name is given in the namlen field. If the length of the name is + odd, the name is followed by a null byte. The name and optional + null byte are followed by XCOFFARFMAG, which is not included in + namlen. The contents of the archive member follow; the number of + bytes is given in the size field. */ +}; + +#define SIZEOF_AR_HDR (3 * XCOFFARMAG_ELEMENT_SIZE + 4 * 12 + 4) + +/* The equivalent for the big archive format. */ + +struct xcoff_ar_hdr_big +{ + /* File size not including the header (decimal ASCII string). */ + char size[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* File offset of next archive member (decimal ASCII string). */ + char nextoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* File offset of previous archive member (decimal ASCII string). */ + char prevoff[XCOFFARMAGBIG_ELEMENT_SIZE]; + + /* File mtime (decimal ASCII string). */ + char date[12]; + + /* File UID (decimal ASCII string). */ + char uid[12]; + + /* File GID (decimal ASCII string). */ + char gid[12]; + + /* File mode (octal ASCII string). */ + char mode[12]; + + /* Length of file name (decimal ASCII string). */ + char namlen[4]; + + /* This structure is followed by the file name. The length of the + name is given in the namlen field. If the length of the name is + odd, the name is followed by a null byte. The name and optional + null byte are followed by XCOFFARFMAG, which is not included in + namlen. The contents of the archive member follow; the number of + bytes is given in the size field. */ +}; + +#define SIZEOF_AR_HDR_BIG (3 * XCOFFARMAGBIG_ELEMENT_SIZE + 4 * 12 + 4) + +/* We often have to distinguish between the old and big file format. + Make it a bit cleaner. We can use `xcoff_ardata' here because the + `hdr' member has the same size and position in both formats. + is the default format, return TRUE even when xcoff_ardata is + NULL. */ +#ifndef SMALL_ARCHIVE +/* Creates big archives by default */ +#define xcoff_big_format_p(abfd) \ + ((NULL != bfd_ardata (abfd) && NULL == xcoff_ardata (abfd)) || \ + ((NULL != bfd_ardata (abfd)) && \ + (NULL != xcoff_ardata (abfd)) && \ + (xcoff_ardata (abfd)->magic[1] == 'b'))) +#else +/* Creates small archives by default. */ +#define xcoff_big_format_p(abfd) \ + (((NULL != bfd_ardata (abfd)) && \ + (NULL != xcoff_ardata (abfd)) && \ + (xcoff_ardata (abfd)->magic[1] == 'b'))) +#endif + +/* We store a copy of the xcoff_ar_file_hdr in the tdata field of the + artdata structure. Similar for the big archive. */ +#define xcoff_ardata(abfd) \ + ((struct xcoff_ar_file_hdr *) bfd_ardata (abfd)->tdata) +#define xcoff_ardata_big(abfd) \ + ((struct xcoff_ar_file_hdr_big *) bfd_ardata (abfd)->tdata) + +/* We store a copy of the xcoff_ar_hdr in the arelt_data field of an + archive element. Similar for the big archive. */ +#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data)) +#define arch_xhdr(bfd) \ + ((struct xcoff_ar_hdr *) arch_eltdata (bfd)->arch_header) +#define arch_xhdr_big(bfd) \ + ((struct xcoff_ar_hdr_big *) arch_eltdata (bfd)->arch_header) + +#endif /* _INTERNAL_XCOFF_H */