This is the modified version of alink used to produce pe-coff powerpc

executables.  I received permission from Anthony Williams to distribute
a modified version for use in ReactOS.

Thanks to him, we're able to use better-supported elf tools for most of
the things we do.

svn path=/branches/powerpc/; revision=25300
This commit is contained in:
Art Yerkes
2007-01-05 05:42:00 +00:00
parent 9c3817045b
commit 3bae2c0ecd
20 changed files with 9185 additions and 0 deletions
@@ -0,0 +1,23 @@
ALINK Source Code, V1.6, Copyright 1998-9 Anthony A.J. Williams.
All Rights Reserved.
This source code is free for all to use, compile and distribute for any
purpose, provided it remains unmodified, and I am credited. You may not
charge for this source code, or any executables compiled from it, but you
may charge a small distribution fee to cover costs, and you may charge
for any warranty or support you may wish to give your customers.
As this source is free, it comes with no warranty whatsoever - use it
entirely at your own risk.
makefile contains the makefile for use with GCC (RSXNT)
alink.mak contains the makefile for use with GCC (RSXNT), linking with the
ALINK libaries. Set C_INCLUDE_PATH to point to the ALINK library headers.
alink2.mak contains the makefile for use with MSVC, linking with the ALINK
libraries. Set INCLUDE to point to the ALINK library headers.
Any comments or bug reports, please email me at
[email protected]
+12
View File
@@ -0,0 +1,12 @@
%.o: %.cpp
g++ -g -c -o $@ $<
all: alink.exe
clean:
rm -rf alink.exe *.o
alink.o combine.o util.o output.o objload.o coff.o cofflib.o elf.o: alink.h
alink.exe: alink.o combine.o util.o output.o objload.o coff.o cofflib.o elf.o
g++ -g -o $@ $^
File diff suppressed because it is too large Load Diff
+956
View File
@@ -0,0 +1,956 @@
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
#define typeid x_typeid
#define class x_class
#define stricmp strcasecmp
#define TRUE (1==1)
#define FALSE (1==0)
#define SWITCHCHAR '-'
#define PATH_CHAR '\\'
#define DEFAULT_EXTENSION ".obj"
#define ERR_EXTRA_DATA 1
#define ERR_NO_HEADER 2
#define ERR_NO_RECDATA 3
#define ERR_NO_MEM 4
#define ERR_INV_DATA 5
#define ERR_INV_SEG 6
#define ERR_BAD_FIXUP 7
#define ERR_BAD_SEGDEF 8
#define ERR_ABS_SEG 9
#define ERR_DUP_PUBLIC 10
#define ERR_NO_MODEND 11
#define ERR_EXTRA_HEADER 12
#define ERR_UNKNOWN_RECTYPE 13
#define ERR_SEG_TOO_LARGE 14
#define ERR_MULTIPLE_STARTS 15
#define ERR_BAD_GRPDEF 16
#define ERR_OVERWRITE 17
#define ERR_INVALID_COMENT 18
#define ERR_ILLEGAL_IMPORTS 19
#define PREV_LE 1
#define PREV_LI 2
#define PREV_LI32 3
#define THEADR 0x80
#define LHEADR 0x82
#define COMENT 0x88
#define MODEND 0x8a
#define MODEND32 0x8b
#define EXTDEF 0x8c
#define TYPDEF 0x8e
#define PUBDEF 0x90
#define PUBDEF32 0x91
#define LINNUM 0x94
#define LINNUM32 0x95
#define LNAMES 0x96
#define SEGDEF 0x98
#define SEGDEF32 0x99
#define GRPDEF 0x9a
#define FIXUPP 0x9c
#define FIXUPP32 0x9d
#define LEDATA 0xa0
#define LEDATA32 0xa1
#define LIDATA 0xa2
#define LIDATA32 0xa3
#define COMDEF 0xb0
#define BAKPAT 0xb2
#define BAKPAT32 0xb3
#define LEXTDEF 0xb4
#define LEXTDEF32 0xb5
#define LPUBDEF 0xb6
#define LPUBDEF32 0xb7
#define LCOMDEF 0xb8
#define CEXTDEF 0xbc
#define COMDAT 0xc2
#define COMDAT32 0xc3
#define LINSYM 0xc4
#define LINSYM32 0xc5
#define ALIAS 0xc6
#define NBKPAT 0xc8
#define NBKPAT32 0xc9
#define LLNAMES 0xca
#define LIBHDR 0xf0
#define LIBEND 0xf1
#define COMENT_TRANSLATOR 0x00
#define COMENT_INTEL_COPYRIGHT 0x01
#define COMENT_LIB_SPEC 0x81
#define COMENT_MSDOS_VER 0x9c
#define COMENT_MEMMODEL 0x9d
#define COMENT_DOSSEG 0x9e
#define COMENT_DEFLIB 0x9f
#define COMENT_OMFEXT 0xa0
#define COMENT_NEWOMF 0xa1
#define COMENT_LINKPASS 0xa2
#define COMENT_LIBMOD 0xa3
#define COMENT_EXESTR 0xa4
#define COMENT_INCERR 0xa6
#define COMENT_NOPAD 0xa7
#define COMENT_WKEXT 0xa8
#define COMENT_LZEXT 0xa9
#define COMENT_PHARLAP 0xaa
#define COMENT_IBM386 0xb0
#define COMENT_RECORDER 0xb1
#define COMENT_COMMENT 0xda
#define COMENT_COMPILER 0xdb
#define COMENT_DATE 0xdc
#define COMENT_TIME 0xdd
#define COMENT_USER 0xdf
#define COMENT_DEPFILE 0xe9
#define COMENT_COMMANDLINE 0xff
#define COMENT_PUBTYPE 0xe1
#define COMENT_COMPARAM 0xea
#define COMENT_TYPDEF 0xe3
#define COMENT_STRUCTMEM 0xe2
#define COMENT_OPENSCOPE 0xe5
#define COMENT_LOCAL 0xe6
#define COMENT_ENDSCOPE 0xe7
#define COMENT_SOURCEFILE 0xe8
#define EXT_IMPDEF 0x01
#define EXT_EXPDEF 0x02
#define SEG_ALIGN 0x3e0
#define SEG_COMBINE 0x1c
#define SEG_BIG 0x02
#define SEG_USE32 0x01
#define SEG_ABS 0x00
#define SEG_BYTE 0x20
#define SEG_WORD 0x40
#define SEG_PARA 0x60
#define SEG_PAGE 0x80
#define SEG_DWORD 0xa0
#define SEG_MEMPAGE 0xc0
#define SEG_BADALIGN 0xe0
#define SEG_8BYTE 0x100
#define SEG_32BYTE 0x200
#define SEG_64BYTE 0x300
#define SEG_PRIVATE 0x00
#define SEG_PUBLIC 0x08
#define SEG_PUBLIC2 0x10
#define SEG_STACK 0x14
#define SEG_COMMON 0x18
#define SEG_PUBLIC3 0x1c
typedef enum segdisp_t {
//#define REL_SEGDISP 0x80
REL_SEGDISP = 0x80,
//#define REL_GRPDISP 0x81
REL_GRPDISP = 0x81,
//#define REL_EXTDISP 0x82
REL_EXTDISP = 0x82,
//#define REL_EXPFRAME 0x83
REL_EXPFRAME = 0x83,
//#define REL_SEGONLY 0x84
REL_SEGONLY = 0x84,
//#define REL_GRPONLY 0x85
REL_GRPONLY = 0x85,
//#define REL_EXTONLY 0x86
REL_EXTONLY = 0x86
} segdisp_t;
typedef enum segframe_t {
//#define REL_SEGFRAME 0
REL_SEGFRAME,
//#define REL_GRPFRAME 1
REL_GRPFRAME,
//#define REL_EXTFRAME 2
REL_EXTFRAME,
//#define REL_EXPFFRAME 3
REL_EXPFFRAME,
//#define REL_LILEFRAME 4
REL_LILEFRAME,
//#define REL_TARGETFRAME 5
REL_TARGETFRAME
};
#define FIX_SELFREL 0x10
#define FIX_MASK (0x0f+FIX_SELFREL)
#define FIX_THRED 0x08
#define THRED_MASK 0x07
#define FIX_LBYTE 0
#define FIX_OFS16 1
#define FIX_BASE 2
#define FIX_PTR1616 3
#define FIX_HBYTE 4
#define FIX_OFS16_2 5
#define FIX_OFS32 9
#define FIX_PTR1632 11
#define FIX_OFS32_2 13
#define FIX_PPC_ADDR24 259
#define FIX_PPC_REL24 260
#define FIX_PPC_RVA16LO 261
#define FIX_PPC_RVA16HA 262
#define FIX_PPC_SECTOFF 263
/* RVA32 fixups are not supported by OMF, so has an out-of-range number */
#define FIX_RVA32 256
#define FIX_REL32 264
#define FIX_ADDR32 265
#define FIX_SELF_LBYTE (FIX_LBYTE+FIX_SELFREL)
#define FIX_SELF_OFS16 (FIX_OFS16+FIX_SELFREL)
#define FIX_SELF_OFS16_2 (FIX_OFS16_2+FIX_SELFREL)
#define FIX_SELF_OFS32 (FIX_OFS32+FIX_SELFREL)
#define FIX_SELF_OFS32_2 (FIX_OFS32_2+FIX_SELFREL)
#define LIBF_CASESENSITIVE 1
#define EXT_NOMATCH 0
#define EXT_MATCHEDPUBLIC 1
#define EXT_MATCHEDIMPORT 2
#define PE_SIGNATURE 0x00
#define PE_MACHINEID 0x04
#define PE_NUMOBJECTS 0x06
#define PE_DATESTAMP 0x08
#define PE_SYMBOLPTR 0x0c
#define PE_NUMSYMBOLS 0x10
#define PE_HDRSIZE 0x14
#define PE_FLAGS 0x16
#define PE_MAGIC 0x18
#define PE_LMAJOR 0x1a
#define PE_LMINOR 0x1b
#define PE_CODESIZE 0x1c
#define PE_INITDATASIZE 0x20
#define PE_UNINITDATASIZE 0x24
#define PE_ENTRYPOINT 0x28
#define PE_CODEBASE 0x2c
#define PE_DATABASE 0x30
#define PE_IMAGEBASE 0x34
#define PE_OBJECTALIGN 0x38
#define PE_FILEALIGN 0x3c
#define PE_OSMAJOR 0x40
#define PE_OSMINOR 0x42
#define PE_USERMAJOR 0x44
#define PE_USERMINOR 0x46
#define PE_SUBSYSMAJOR 0x48
#define PE_SUBSYSMINOR 0x4a
#define PE_IMAGESIZE 0x50
#define PE_HEADERSIZE 0x54
#define PE_CHECKSUM 0x58
#define PE_SUBSYSTEM 0x5c
#define PE_DLLFLAGS 0x5e
#define PE_STACKSIZE 0x60
#define PE_STACKCOMMSIZE 0x64
#define PE_HEAPSIZE 0x68
#define PE_HEAPCOMMSIZE 0x6c
#define PE_LOADERFLAGS 0x70
#define PE_NUMRVAS 0x74
#define PE_EXPORTRVA 0x78
#define PE_EXPORTSIZE 0x7c
#define PE_IMPORTRVA 0x80
#define PE_IMPORTSIZE 0x84
#define PE_RESOURCERVA 0x88
#define PE_RESOURCESIZE 0x8c
#define PE_EXCEPTIONRVA 0x90
#define PE_EXCEPTIONSIZE 0x94
#define PE_SECURITYRVA 0x98
#define PE_SECURITYSIZE 0x9c
#define PE_FIXUPRVA 0xa0
#define PE_FIXUPSIZE 0xa4
#define PE_DEBUGRVA 0xa8
#define PE_DEBUGSIZE 0xac
#define PE_DESCRVA 0xb0
#define PE_DESCSIZE 0xb4
#define PE_MSPECRVA 0xb8
#define PE_MSPECSIZE 0xbc
#define PE_TLSRVA 0xc0
#define PE_TLSSIZE 0xc4
#define PE_LOADCONFIGRVA 0xc8
#define PE_LOADCONFIGSIZE 0xcc
#define PE_BOUNDIMPRVA 0xd0
#define PE_BOUNDIMPSIZE 0xd4
#define PE_IATRVA 0xd8
#define PE_IATSIZE 0xdc
#define PE_OBJECT_NAME 0x00
#define PE_OBJECT_VIRTSIZE 0x08
#define PE_OBJECT_VIRTADDR 0x0c
#define PE_OBJECT_RAWSIZE 0x10
#define PE_OBJECT_RAWPTR 0x14
#define PE_OBJECT_RELPTR 0x18
#define PE_OBJECT_LINEPTR 0x1c
#define PE_OBJECT_NUMREL 0x20
#define PE_OBJECT_NUMLINE 0x22
#define PE_OBJECT_FLAGS 0x24
#define PE_BASE_HEADER_SIZE 0x18
#define PE_OPTIONAL_HEADER_SIZE 0xe0
#define PE_OBJECTENTRY_SIZE 0x28
#define PE_HEADBUF_SIZE (PE_BASE_HEADER_SIZE+PE_OPTIONAL_HEADER_SIZE)
#define PE_IMPORTDIRENTRY_SIZE 0x14
#define PE_NUM_VAS 0x10
#define PE_EXPORTHEADER_SIZE 0x28
#define PE_RESENTRY_SIZE 0x08
#define PE_RESDIR_SIZE 0x10
#define PE_RESDATAENTRY_SIZE 0x10
#define PE_SYMBOL_SIZE 0x12
#define PE_RELOC_SIZE 0x0a
#define PE_ORDINAL_FLAG 0x80000000
#define PE_INTEL386 0x014c
#define PE_POWERPC 0x01f0
#define PE_MAGICNUM 0x010b
#define PE_FILE_EXECUTABLE 0x0002
#define PE_FILE_32BIT 0x0100
#define PE_FILE_LIBRARY 0x2000
#define PE_REL_LOW16 0x2000
#define PE_REL_OFS32 0x3000
#define PE_SUBSYS_NATIVE 1
#define PE_SUBSYS_WINDOWS 2
#define PE_SUBSYS_CONSOLE 3
#define PE_SUBSYS_POSIX 7
//seglist[0]->nameindex=0 o=-1 l=38 a=140 f=00100a00
//seglist[1]->nameindex=1 o=-1 l=8 a=178 f=60400020
//seglist[2]->nameindex=2 o=-1 l=20 a=186 f=40300040
#define WINF_UNDEFINED 0x00000000
#define WINF_CODE 0x00000020
#define WINF_INITDATA 0x00000040
#define WINF_UNINITDATA 0x00000080
#define WINF_DISCARDABLE 0x02000000
#define WINF_NOPAGE 0x08000000
#define WINF_SHARED 0x10000000
#define WINF_EXECUTE 0x20000000
#define WINF_READABLE 0x40000000
#define WINF_WRITEABLE 0x80000000
#define WINF_ALIGN_NOPAD 0x00000008
#define WINF_ALIGN_BYTE 0x00100000
#define WINF_ALIGN_WORD 0x00200000
#define WINF_ALIGN_DWORD 0x00300000
#define WINF_ALIGN_8 0x00400000
#define WINF_ALIGN_PARA 0x00500000
#define WINF_ALIGN_32 0x00600000
#define WINF_ALIGN_64 0x00700000
#define WINF_ALIGN (WINF_ALIGN_64)
#define WINF_COMMENT 0x00000200
#define WINF_REMOVE 0x00000800
#define WINF_COMDAT 0x00001000
#define WINF_NEG_FLAGS (WINF_DISCARDABLE | WINF_NOPAGE)
#define WINF_IMAGE_FLAGS 0xfa0008e0
#define COFF_SYM_EXTERNAL 2
#define COFF_SYM_STATIC 3
#define COFF_SYM_LABEL 6
#define COFF_SYM_FUNCTION 101
#define COFF_SYM_FILE 103
#define COFF_SYM_SECTION 104
#define COFF_FIX_DIR32 6
#define COFF_FIX_RVA32 7
#define COFF_FIX_REL32 0x14
#define R_PPC_ADDR32 1
#define R_PPC_ADDR24 2
#define R_PPC_ADDR16 3
#define R_PPC_ADDR16_LO 4
#define R_PPC_ADDR16_HI 5
#define R_PPC_ADDR16_HA 6
#define R_PPC_REL24 10
#define R_PPC_UADDR32 24
#define R_PPC_REL32 26
#define R_PPC_SECTOFF 33
#define IMAGE_REL_PPC_ABSOLUTE 0x00
#define IMAGE_REL_PPC_ADDR64 0x01
#define IMAGE_REL_PPC_ADDR32 0x02
#define IMAGE_REL_PPC_ADDR24 0x03
#define IMAGE_REL_PPC_ADDR16 0x04
#define IMAGE_REL_PPC_ADDR14 0x05
#define IMAGE_REL_PPC_REL24 0x06
#define IMAGE_REL_PPC_REL14 0x07
#define IMAGE_REL_PPC_ADDR32NB 0x0a
#define IMAGE_REL_PPC_SECREL 0x0b
#define IMAGE_REL_PPC_SECTION 0x0c
#define IMAGE_REL_PPC_SECREL16 0x0f
#define IMAGE_REL_PPC_REFHI 0x10
#define IMAGE_REL_PPC_REFLO 0x11
#define IMAGE_REL_PPC_PAIR 0x12
#define IMAGE_REL_PPC_SECRELLO 0x13
#define IMAGE_REL_PPC_SECRELHI 0x14
#define IMAGE_REL_PPC_GPREL 0x15
#define OUTPUT_COM 1
#define OUTPUT_EXE 2
#define OUTPUT_PE 3
#define WIN32_DEFAULT_BASE 0x00400000
#define WIN32_DEFAULT_FILEALIGN 0x00000200
#define WIN32_DEFAULT_OBJECTALIGN 0x00001000
#define WIN32_DEFAULT_STACKSIZE 0x00100000
#define WIN32_DEFAULT_STACKCOMMITSIZE 0x00001000
#define WIN32_DEFAULT_HEAPSIZE 0x00100000
#define WIN32_DEFAULT_HEAPCOMMITSIZE 0x00001000
#define WIN32_DEFAULT_SUBSYS PE_SUBSYS_WINDOWS
#define WIN32_DEFAULT_SUBSYSMAJOR 4
#define WIN32_DEFAULT_SUBSYSMINOR 0
#define WIN32_DEFAULT_OSMAJOR 1
#define WIN32_DEFAULT_OSMINOR 0
#define EXP_ORD 0x80
typedef char *PCHAR,**PPCHAR;
typedef unsigned char *PUCHAR;
typedef unsigned long UINT;
extern UINT imageBase;
extern UINT fileAlign;
extern UINT objectAlign;
extern UINT stackSize;
extern UINT stackCommitSize;
extern UINT heapSize;
extern UINT heapCommitSize;
template <typename T>
int get32(T &vect, int offset)
{
return vect[offset] |
(vect[offset+1] << 8) |
(vect[offset+2] << 16) |
(vect[offset+3] << 24);
}
template <typename T>
void put32(T &vect, int offset, int val)
{
vect[offset] = val;
vect[offset+1] = val >> 8;
vect[offset+2] = val >> 16;
vect[offset+3] = val >> 24;
}
template <typename T>
int get16(T &vect, int offset)
{
return vect[offset] | (vect[offset+1] << 8);
}
template <typename T>
void put16(T &vect, int offset, int val)
{
vect[offset] = val; vect[offset+1] = val >> 8;
}
template <typename T>
void ClearNbit(T &mask,long i)
{
mask[i/8]&=0xff-(1<<(i%8));
}
template <typename T>
void SetNbit(T &mask,long i)
{
mask[i/8]|=(1<<(i%8));
}
template <typename T>
char GetNbit(T &mask,long i)
{
return (mask[i/8]>>(i%8))&1;
}
template <typename T>
long GetIndex(T &buf,long *index)
{
long i;
if(buf[*index]&0x80)
{
i=((buf[*index]&0x7f)*256)+buf[(*index)+1];
(*index)+=2;
return i;
}
else
{
return buf[(*index)++];
}
}
static int roundup(int x, int align)
{
x += align-1;
return x & ~(align-1);
}
typedef struct __int_to_name {
int id;
const char *name;
} INT_TO_NAME, *PINT_TO_NAME;
static const char *findName(const INT_TO_NAME *names, int id)
{
for( int i = 0; names[i].name; i++ ) {
if(names[i].id == id) return names[i].name;
}
return "<unknown>";
}
typedef struct __seg {
private:
UINT base;
public:
std::string name;
long classindex;
long overlayindex;
long orderindex;
UINT length;
UINT virtualSize;
UINT absframe;
UINT absofs;
UINT winFlags;
UINT fileBase;
unsigned short attr;
std::vector<unsigned char> data;
std::vector<unsigned char> datmask;
__seg() {
classindex = overlayindex = orderindex = -1;
length = virtualSize = absframe = absofs = base = 0;
winFlags = WINF_READABLE | WINF_WRITEABLE | WINF_NEG_FLAGS;
attr = SEG_PRIVATE | SEG_PARA;
}
UINT getbase() { return base; }
void setbase(UINT base) {
this->base = base;
}
} SEG, *PSEG, **PPSEG;
typedef struct __datablock {
long count;
long blocks;
long dataofs;
std::vector<UCHAR> data;
__datablock() { count = blocks = dataofs = 0; }
} DATABLOCK, *PDATABLOCK, **PPDATABLOCK;
typedef struct __pubdef {
PSEG seg;
long grpnum;
long typenum;
UINT ofs;
UINT modnum;
std::string name;
std::string aliasName;
__pubdef() {
seg = 0; grpnum = typenum = ofs = modnum = 0;
}
} PUBLIC, *PPUBLIC,**PPPUBLIC;
typedef struct __extdef {
std::string name;
long typenum;
PPUBLIC pubdef;
long impnum;
long flags;
UINT modnum;
__extdef(std::string name = "") : name(name), typenum(-1), pubdef(0), impnum(0), flags(EXT_NOMATCH), modnum(0) { }
} EXTREC, *PEXTREC,**PPEXTREC;
typedef struct __imprec {
std::string int_name, mod_name, imp_name;
unsigned short ordinal;
char flags;
PSEG seg;
UINT abs, ofs;
__imprec() {
abs = ordinal = flags = 0; seg = 0; ofs = 0;
}
} IMPREC, *PIMPREC, **PPIMPREC;
typedef struct __exprec {
std::string int_name, exp_name;
UINT ordinal;
char flags;
PPUBLIC pubdef;
UINT modnum;
__exprec() {
ordinal = flags = modnum = 0;
pubdef = 0;
}
} EXPREC, *PEXPREC, **PPEXPREC;
typedef struct __comdef {
std::string name;
UINT length;
int isFar;
UINT modnum;
__comdef() { length = isFar = modnum; }
} COMREC, *PCOMREC, **PPCOMREC;
typedef struct __elf32sym
{
ULONG st_name;
ULONG st_value;
ULONG st_size;
UCHAR st_info;
UCHAR st_other;
USHORT st_shndx;
} ELF32SYM, *PELF32SYM;
typedef struct __elf32rela
{
ULONG r_offset;
ULONG r_info;
ULONG r_address;
} ELF32RELA, *PELF32RELA;
typedef struct __elf32relx
{
ULONG r_offset;
ULONG r_info;
ULONG r_address;
ULONG r_seg; /* Implied by section order */
} ELF32RELX, *PELF32RELX;
typedef struct __reloc {
UINT ofs;
segframe_t ftype;
segdisp_t ttype;
unsigned short rtype;
long target;
UINT disp;
UINT outputPos;
PSEG seg, targseg;
UINT frame;
ELF32RELX orig;
__reloc() {
frame = 0; seg = 0; targseg = 0;
ftype = REL_SEGFRAME;
ttype = REL_SEGDISP;
rtype = target = disp = outputPos = 0;
}
} RELOC, *PRELOC,**PPRELOC;
typedef struct __grp {
std::string name;
long numsegs;
PSEG segindex[256];
PSEG seg;
__grp() { numsegs = 0; seg = 0; memset(segindex, 0, sizeof(segindex)); }
} GRP, *PGRP, **PPGRP;
typedef std::map<std::string, std::vector<void *> > SORTLIST;
typedef struct __libfile {
std::string filename;
unsigned short blocksize;
unsigned short numdicpages;
UINT dicstart;
char flags;
char libtype;
int modsloaded;
std::vector<UINT> modlist;
std::vector<UCHAR> longnames;
SORTLIST symbols;
} LIBFILE, *PLIBFILE, **PPLIBFILE;
typedef struct __libentry {
UINT libfile;
UINT modpage;
} LIBENTRY, *PLIBENTRY, **PPLIBENTRY;
typedef struct __resource {
std::vector<unsigned char> xtypename;
std::vector<unsigned char> name;
std::vector<unsigned char> data;
UINT length;
unsigned short typeid;
unsigned short id;
unsigned short languageid;
} RESOURCE, *PRESOURCE;
typedef struct __coffsym {
std::string name;
UINT value;
short section;
unsigned short type;
unsigned char coff_class;
long extnum;
UINT numAuxRecs;
std::vector<UCHAR> auxRecs;
int isComDat;
int originalSym;
PSEG segptr;
__coffsym() {
value = numAuxRecs = extnum = isComDat = originalSym = 0;
section = 0; type = 0;
coff_class = 0; segptr = 0;
}
} COFFSYM, *PCOFFSYM;
typedef struct __comdatrec
{
UINT segnum;
UINT combineType;
UINT linkwith;
} COMDATREC, *PCOMDAT;
#define EI_NIDENT 16
typedef struct __elf32hdr
{
UCHAR e_ident[EI_NIDENT];
USHORT e_type, e_machine;
ULONG e_version;
ULONG e_entry;
ULONG e_phoff;
ULONG e_shoff;
ULONG e_flags;
USHORT e_ehsize, e_phentsize;
USHORT e_phnum, e_shentsize;
USHORT e_shnum, e_shtrndx;
} ELF32HDR, *PELF32HDR;
typedef struct __elf32shdr
{
ULONG sh_name;
ULONG sh_type;
ULONG sh_flags;
ULONG sh_addr;
ULONG sh_offset;
ULONG sh_size;
ULONG sh_link;
ULONG sh_info;
ULONG sh_addralign;
ULONG sh_entsize;
} ELF32SHDR, *PELF32SHDR;
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
#define ET_LOOS 0xfe00
#define ET_HIOS 0xfeff
#define ET_LOPROC 0xff00
#define ET_HIPROC 0xffff
#define EM_NONE 0
#define EM_M32 1
#define EM_SPARC 2
#define EM_386 3
#define EM_68K 4
#define EM_88K 5
/* #define EM_RESERVED 6 */
#define EM_860 7
#define EM_MIPS 8
/* #define EM_RESERVED 9 */
#define EM_MIPS_RS3_LE 10
/* #define EM_RESERVED 11-14 */
#define EM_PARISC 15
/* #define EM_RESERVED 16 */
#define EM_VPP500 17
#define EM_SPARC32PLUS 18
#define EM_960 19
#define EM_PPC 20
/* #define EM_RESERVED 21-35 */
#define EM_V800 36
#define EM_FR20 37
#define EM_RH32 38
#define EM_RCE 39
#define EM_ARM 40
#define EM_ALPHA 41
#define EM_SH 42
#define EM_SPARCV9 43
#define EM_TRICORE 44
#define EM_ARC 45
#define EM_H8_300 46
#define EM_H8_300H 47
#define EM_H8S 48
#define EM_H8_500 49
#define EM_IA_64 50
#define EM_MIPPS_X 51
#define EM_COLDFIRE 52
#define EM_68HC12 53
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_UNKNOWN12 12
#define SHT_UNKNOWN13 13
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18
#define SHT_NUM 19
#define SHF_WRITE 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOOS 10
#define STB_HIOS 11
#define STB_LOPROC 13
#define STB_HIPROC 15
#define STT_FILE 4
#define STT_COMMON 5
#define SHN_COMMON 0xfff2
#define ELF32SYMSIZE 16
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
#define ELF32_ST_INFO(bind,type) (((bind)<<4) | ((type)&0xf))
#define ELF32_R_SYM(info) ((info) >> 8)
#define ELF32_R_TYPE(info) ((unsigned char)(info))
#define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type))
#define T_NULL 0
#define T_VOID 1
#define T_CHAR 2
#define T_SHORT 3
#define T_INT 4
#define T_LONG 5
#define T_FLOAT 6
#define T_DOUBLE 7
#define T_STRUCT 8
#define T_UNION 9
#define T_ENUM 10
#define T_MOE 11
#define T_UCHAR 12
#define T_USHORT 13
#define T_UINT 14
#define T_ULONG 15
#define T_LNGDBL 16
#define DT_NON 0
#define DT_PTR 1
#define DT_FCN 2
#define DT_ARY 3
#define COFFTYPE(dt,t) (((dt)<<4)|t)
int sortCompare(const void *x1,const void *x2);
void processArgs(int argc,char *argv[]);
void combine_groups(long i,long j);
void combine_common(long i,long j);
void combine_segments(PSEG i,PSEG j);
void combineBlocks();
void OutputWin32file(const std::string &outname);
void OutputEXEfile(const std::string &outname);
void OutputCOMfile(const std::string &outname);
void GetFixupTarget(PRELOC r,PSEG *tseg,UINT *tofs,int isFlat);
void loadlibmod(UINT libnum,UINT modpage);
void loadlib(FILE *libfile,std::string libname);
void loadelf(FILE *libfile);
void loadCoffLib(FILE *libfile,std::string libname);
void loadcofflibmod(PLIBFILE p,FILE *libfile);
long loadmod(FILE *objfile);
void loadres(FILE *resfile);
void loadcoff(FILE *objfile);
void loadCoffImport(FILE *objfile);
void LoadFIXUP(PRELOC r,PUCHAR buf,long *p);
void RelocLIDATA(PDATABLOCK p,long *ofs,PRELOC r);
void EmitLiData(PDATABLOCK p,long segnum,long *ofs);
PDATABLOCK BuildLiData(long *bufofs);
void DestroyLIDATA(PDATABLOCK p);
void ReportError(long errnum);
int wstricmp(const char *s1,const char*s2);
int wstrlen(const char *s);
unsigned short wtoupper(unsigned short a);
int getBitCount(UINT a);
int _wstricmp(unsigned char *a, unsigned char *b);
int _wstrlen(unsigned char *a);
#define strdup _strdup
extern char case_sensitive;
extern char padsegments;
extern char mapfile;
extern std::string mapname;
extern unsigned short maxalloc;
extern int output_type;
extern std::string outname;
extern FILE *afile;
extern UINT filepos;
extern long reclength;
extern unsigned char rectype;
extern char li_le;
extern UINT prevofs;
extern long prevseg;
extern long gotstart;
extern RELOC startaddr;
extern unsigned char osMajor,osMinor;
extern unsigned char subsysMajor,subsysMinor;
extern unsigned int subSystem;
extern long errcount;
extern std::vector<unsigned char> buf;
extern PDATABLOCK lidata;
//extern std::vector<std::string> namelist;
extern std::vector<PSEG> seglist;
extern std::vector<PSEG> outlist;
extern std::vector<PGRP> grplist;
extern SORTLIST publics;
extern std::vector<EXTREC> externs;
extern std::vector<PCOMREC> comdefs;
extern std::vector<PRELOC> relocs;
extern std::vector<IMPREC> impdefs;
extern std::vector<EXPREC> expdefs;
extern std::vector<LIBFILE> libfiles;
extern std::vector<RESOURCE> resource;
extern std::vector<std::string> modname;
extern std::vector<std::string> filename;
extern SORTLIST comdats;
extern UINT namemin,
pubmin,
segmin,
grpmin,
extmin,
commin,
fixmin,
impmin,impsreq,
expmin;
extern int buildDll;
extern std::string stubName, entryPoint;
extern int cpuIdent;
+11
View File
@@ -0,0 +1,11 @@
CC = gcc -Zomf -c -s -O5
%.obj: %.c
$(CC) -o $@ $<
all: blink.exe
alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj: alink.h
blink.exe: alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj
alink -subsys con @lib/def.rsp -o $@ $^
+11
View File
@@ -0,0 +1,11 @@
CC = cl /Zl /c /Ox
%.obj: %.c
$(CC) /Fo$@ $<
all: blink.exe
alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj: alink.h
blink.exe: alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj
alink -subsys con @lib/def.rsp -o $@ $^
+723
View File
@@ -0,0 +1,723 @@
#include "alink.h"
#define strupr(x)
void loadcoff(FILE *objfile)
{
unsigned char headbuf[20];
unsigned char buf[100];
PUCHAR bigbuf;
std::vector<UCHAR> stringList;
UINT thiscpu;
UINT numSect;
UINT headerSize;
UINT symbolPtr;
UINT numSymbols;
UINT stringPtr;
UINT stringSize;
UINT stringOfs;
UINT i,j,k,l;
UINT fileStart;
UINT minseg;
UINT numrel;
UINT relofs;
UINT relshift;
UINT sectname;
long sectorder;
std::vector<COFFSYM> sym;
UINT combineType;
PPUBLIC pubdef;
PCOMDAT comdat;
PCHAR comdatsym;
std::vector<std::string> nlist;
SORTLIST::iterator listnode;
minseg=seglist.size();
fileStart=ftell(objfile);
if(fread(headbuf,1,20,objfile)!=20)
{
printf("Unable to read from file\n");
exit(1);
}
thiscpu=headbuf[0]+256*headbuf[1];
if(!thiscpu)
{
/* if we've got an import module, start at the beginning */
fseek(objfile,fileStart,SEEK_SET);
/* and load it */
loadCoffImport(objfile);
return;
}
if(thiscpu==0x14c)
cpuIdent = PE_INTEL386;
if(thiscpu==0x1f0)
cpuIdent = PE_POWERPC;
if(!cpuIdent)
{
printf("Unsupported CPU type for module (type %x)\n", thiscpu);
exit(1);
}
numSect=get16(headbuf, PE_NUMOBJECTS-PE_MACHINEID);
symbolPtr=get32(headbuf, PE_SYMBOLPTR-PE_MACHINEID);
numSymbols=get32(headbuf, PE_NUMSYMBOLS-PE_MACHINEID);
if(headbuf[PE_HDRSIZE-PE_MACHINEID]|headbuf[PE_HDRSIZE-PE_MACHINEID+1])
{
printf("warning, optional header discarded\n");
headerSize=headbuf[PE_HDRSIZE-PE_MACHINEID]+256*headbuf[PE_HDRSIZE-PE_MACHINEID+1];
}
else
headerSize=0;
headerSize+=PE_BASE_HEADER_SIZE-PE_MACHINEID;
stringPtr=symbolPtr+numSymbols*PE_SYMBOL_SIZE;
if(stringPtr)
{
fseek(objfile,fileStart+stringPtr,SEEK_SET);
if(fread(buf,1,4,objfile)!=4)
{
printf("Invalid COFF object file, unable to read string table size\n");
exit(1);
}
stringSize=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24);
if(!stringSize) stringSize=4;
if(stringSize<4)
{
printf("Invalid COFF object file, bad string table size %i\n",stringSize);
exit(1);
}
stringPtr+=4;
stringSize-=4;
}
else
{
stringSize=0;
}
if(stringSize)
{
stringList.resize(stringSize);
if(fread(&stringList[0],1,stringSize,objfile)!=stringSize)
{
printf("Invalid COFF object file, unable to read string table\n");
exit(1);
}
if(stringList[stringSize-1])
{
printf("Invalid COFF object file, last string unterminated\n");
exit(1);
}
}
else
{
stringList.resize(0);
}
if(symbolPtr && numSymbols)
{
fseek(objfile,fileStart+symbolPtr,SEEK_SET);
sym.resize(numSymbols);
for(i=0;i<numSymbols;i++)
{
if(fread(buf,1,PE_SYMBOL_SIZE,objfile)!=PE_SYMBOL_SIZE)
{
printf("Invalid COFF object file, unable to read symbols\n");
exit(1);
}
if(get32(buf,0))
{
sym[i].name=std::string((char *)buf,8);
}
else
{
stringOfs=get32(buf,4);
if(stringOfs<4)
{
printf("Invalid COFF object file bad symbol location (StringOfs = %d)\n", stringOfs);
exit(1);
}
stringOfs-=4;
if(stringOfs>=stringSize)
{
printf("Invalid COFF object file bad symbol location\n");
exit(1);
}
sym[i].name=(char *)&stringList[0]+stringOfs;
}
if(!case_sensitive)
{
strupr(sym[i].name);
}
sym[i].value=get32(buf, 8);
sym[i].section=get16(buf, 12);
sym[i].type=get16(buf, 14);
sym[i].coff_class=buf[16];
sym[i].extnum=-1;
sym[i].numAuxRecs=buf[17];
sym[i].isComDat=FALSE;
switch(sym[i].coff_class)
{
case COFF_SYM_SECTION: { /* section symbol */
if(sym[i].section<-1)
{
break;
}
/* section symbols declare an extern always, so can use in relocs */
/* they may also include a PUBDEF */
EXTREC ext;
ext.name=sym[i].name;
ext.pubdef=NULL;
ext.modnum=0;
ext.flags=EXT_NOMATCH;
sym[i].extnum=externs.size();
externs.push_back(ext);
if(sym[i].section!=0) /* if the section is defined here, make public */
{
pubdef=new PUBLIC();
pubdef->grpnum=-1;
pubdef->typenum=0;
pubdef->modnum=0;
pubdef->aliasName="";
pubdef->ofs=sym[i].value;
if(sym[i].section==-1)
{
pubdef->seg=0;
}
else
{
pubdef->seg=seglist[minseg+sym[i].section-1];
}
if((listnode=publics.find(sym[i].name)) != publics.end())
{
for(j=0;j<listnode->second.size();++j)
{
if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum)
{
if(((PPUBLIC)listnode->second[j])->aliasName == "")
{
printf("Duplicate public symbol %s\n",sym[i].name.c_str());
exit(1);
}
(*((PPUBLIC)listnode->second[j]))=(*pubdef);
pubdef=NULL;
break;
}
}
}
if(pubdef)
{
SORTLIST::iterator it = publics.find(sym[i].name);
if(it == publics.end()) {
std::vector<void *> vv;
vv.push_back((void *)pubdef);
publics.insert(std::make_pair(sym[i].name,vv));
} else {
it->second.push_back((void *)pubdef);
}
}
}
}
case COFF_SYM_STATIC: /* allowed, but ignored for now as we only want to process if required */
case COFF_SYM_LABEL:
case COFF_SYM_FILE:
case COFF_SYM_FUNCTION:
case COFF_SYM_EXTERNAL:
break;
default:
printf("unsupported symbol class %02X for symbol %s\n",sym[i].coff_class,sym[i].name.c_str());
exit(1);
}
if(sym[i].numAuxRecs)
{
sym[i].auxRecs.resize(sym[i].numAuxRecs*PE_SYMBOL_SIZE);
}
else
{
sym[i].auxRecs.resize(0);
}
/* read in the auxillary records for this symbol */
for(j=0;j<sym[i].numAuxRecs;j++)
{
if(fread(&sym[i].auxRecs[0]+j*PE_SYMBOL_SIZE,
1,PE_SYMBOL_SIZE,objfile)!=PE_SYMBOL_SIZE)
{
printf("Invalid COFF object file\n");
exit(1);
}
sym[i+j+1].name="";
sym[i+j+1].numAuxRecs=0;
sym[i+j+1].value=0;
sym[i+j+1].section=-1;
sym[i+j+1].type=0;
sym[i+j+1].coff_class=0;
sym[i+j+1].extnum=-1;
}
i+=j;
}
}
for(i=0;i<numSect;i++)
{
fseek(objfile,fileStart+headerSize+i*PE_OBJECTENTRY_SIZE,
SEEK_SET);
if(fread(buf,1,PE_OBJECTENTRY_SIZE,objfile)!=PE_OBJECTENTRY_SIZE)
{
printf("Invalid COFF object file, unable to read section header\n");
exit(1);
}
/* virtual size is also the offset of the data into the segment */
/*
if(buf[PE_OBJECT_VIRTSIZE]|buf[PE_OBJECT_VIRTSIZE+1]|buf[PE_OBJECT_VIRTSIZE+2]
|buf[PE_OBJECT_VIRTSIZE+3])
{
printf("Invalid COFF object file, section has non-zero virtual size\n");
exit(1);
}
*/
buf[8]=0; /* null terminate name */
/* get shift value for relocs */
relshift=get32(buf, PE_OBJECT_VIRTADDR);
if(buf[0]=='/')
{
sectname=strtoul((char *)buf+1,(char**)&bigbuf,10);
if(*bigbuf)
{
printf("Invalid COFF object file, invalid number %s\n",buf+1);
exit(1);
}
if(sectname<4)
{
printf("Invalid COFF object file\n");
exit(1);
}
sectname-=4;
if(sectname>=stringSize)
{
printf("Invalid COFF object file\n");
exit(1);
}
nlist.push_back((char *)&stringList[0]+sectname);
sectname=nlist.size()-1;
}
else
{
nlist.push_back((char *)buf);
sectname=nlist.size()-1;
}
size_t dollar = nlist[sectname].find('$');
if(dollar != std::string::npos)
{
/* if we have a grouped segment, sort by original name */
sectorder=sectname;
/* and get real name, without $ sort section */
sectname=nlist.size();
std::string no_dollar = nlist[sectname].substr(dollar);
nlist.push_back(no_dollar);
}
else
{
sectorder=-1;
}
numrel=get16(buf, PE_OBJECT_NUMREL);
relofs=get32(buf, PE_OBJECT_RELPTR);
PSEG seg = new SEG();
seg->name=nlist[sectname];
seg->orderindex=sectorder;
seg->classindex=-1;
seg->overlayindex=-1;
seg->length=get32(buf, PE_OBJECT_RAWSIZE);
seg->attr=SEG_PUBLIC|SEG_USE32;
seg->winFlags=get32(buf, PE_OBJECT_FLAGS);
seg->setbase(get32(buf, PE_OBJECT_RAWPTR));
if(seg->winFlags & WINF_ALIGN_NOPAD)
{
seg->winFlags &= (0xffffffff-WINF_ALIGN);
seg->winFlags |= WINF_ALIGN_BYTE;
}
switch(seg->winFlags & WINF_ALIGN)
{
case WINF_ALIGN_BYTE:
seg->attr |= SEG_BYTE;
break;
case WINF_ALIGN_WORD:
seg->attr |= SEG_WORD;
break;
case WINF_ALIGN_DWORD:
seg->attr |= SEG_DWORD;
break;
case WINF_ALIGN_8:
seg->attr |= SEG_8BYTE;
break;
case WINF_ALIGN_PARA:
seg->attr |= SEG_PARA;
break;
case WINF_ALIGN_32:
seg->attr |= SEG_32BYTE;
break;
case WINF_ALIGN_64:
seg->attr |= SEG_64BYTE;
break;
case 0:
seg->attr |= SEG_PARA; /* default */
break;
default:
printf("Invalid COFF object file, bad section alignment %08X\n",seg->winFlags);
exit(1);
}
/* invert all negative-logic flags */
seg->winFlags ^= WINF_NEG_FLAGS;
/* remove .debug sections */
if(nlist[sectname] == ".debug")
{
seg->winFlags |= WINF_REMOVE;
seg->length=0;
numrel=0;
}
if(seg->winFlags & WINF_COMDAT)
{
printf("COMDAT section %s\n",nlist[sectname].c_str());
comdat=new COMDATREC();
combineType=0;
comdat->linkwith=0;
for(j=0;j<numSymbols;j++)
{
if(sym[j].name=="") continue;
if(sym[j].section==(i+1))
{
if(sym[j].numAuxRecs!=1)
{
printf("Invalid COMDAT section reference\n");
exit(1);
}
printf("Section %s ",sym[j].name.c_str());
combineType=sym[j].auxRecs[14];
comdat->linkwith=sym[j].auxRecs[12]+(sym[j].auxRecs[13]<<8)+minseg-1;
printf("Combine type %i ",sym[j].auxRecs[14]);
printf("Link alongside section %i",comdat->linkwith);
break;
}
}
if(j==numSymbols)
{
printf("Invalid COMDAT section\n");
exit(1);
}
for(j++;j<numSymbols;j++)
{
if(sym[j].name == "") continue;
if(sym[j].section==(i+1))
{
if(sym[j].numAuxRecs)
{
printf("Invalid COMDAT symbol\n");
exit(1);
}
printf("COMDAT Symbol %s\n",sym[j].name.c_str());
comdatsym=(char *)sym[j].name.c_str();
sym[j].isComDat=TRUE;
break;
}
}
/* associative sections don't have a name */
if(j==numSymbols)
{
if(combineType!=5)
{
printf("\nInvalid COMDAT section\n");
exit(1);
}
else
{
printf("\n");
}
comdatsym=""; /* dummy name */
}
comdat->segnum=seglist.size();
comdat->combineType=combineType;
printf("COMDATs not yet supported\n");
exit(1);
printf("Combine types for duplicate COMDAT symbol %s do not match\n",comdatsym);
exit(1);
}
if(seg->length)
{
seg->data.resize(seg->length);
seg->datmask.resize((seg->length+7)/8);
if(seg->getbase())
{
fseek(objfile,fileStart+seg->getbase(),SEEK_SET);
if(fread(&seg->data[0],1,seg->length,objfile)
!=seg->length)
{
printf("Invalid COFF object file\n");
exit(1);
}
for(j=0;j<(seg->length+7)/8;j++)
seg->datmask[j]=0xff;
}
else
{
for(j=0;j<(seg->length+7)/8;j++)
seg->datmask[j]=0;
}
}
else
{
seg->data.resize(0);
seg->datmask.resize(0);
}
if(numrel) fseek(objfile,fileStart+relofs,SEEK_SET);
for(j=0;j<numrel;j++)
{
if(fread(buf,1,PE_RELOC_SIZE,objfile)!=PE_RELOC_SIZE)
{
printf("Invalid COFF object file, unable to read reloc table\n");
exit(1);
}
PRELOC reloc = new RELOC();
/* get address to relocate */
reloc->ofs=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24);
reloc->ofs-=relshift;
/* get segment */
reloc->seg=seglist[i+minseg];
reloc->disp=0;
/* get relocation target external index */
reloc->target=get32(buf, 4);
if(reloc->target>=numSymbols)
{
printf("Invalid COFF object file, undefined symbol\n");
exit(1);
}
k=reloc->target;
reloc->ttype=REL_EXTONLY; /* assume external reloc */
if(sym[k].extnum<0)
{
switch(sym[k].coff_class)
{
case COFF_SYM_EXTERNAL: {
/* global symbols declare an extern when used in relocs */
EXTREC ext;
ext.name=(char *)sym[k].name.c_str();
ext.pubdef=NULL;
ext.modnum=0;
ext.flags=EXT_NOMATCH;
sym[k].extnum=externs.size();
externs.push_back(ext);
/* they may also include a COMDEF or a PUBDEF */
/* this is dealt with after all sections loaded, to cater for COMDAT symbols */
} break;
case COFF_SYM_STATIC: /* static symbol */
case COFF_SYM_LABEL: /* code label symbol */
if(sym[k].section<-1)
{
printf("cannot relocate against a debug info symbol\n");
exit(1);
break;
}
if(sym[k].section==0)
{
if(sym[k].value)
{
EXTREC ext;
ext.name=(char *)sym[k].name.c_str();
ext.pubdef=NULL;
ext.modnum=modname.size()-1;
ext.flags=EXT_NOMATCH;
sym[k].extnum=externs.size();
externs.push_back(ext);
PCOMREC com = new COMREC();
com->length=sym[k].value;
com->isFar=FALSE;
com->name=(char *)sym[k].name.c_str();
com->modnum=modname.size()-1;
comdefs.push_back(com);
}
else
{
printf("Undefined symbol %s\n",sym[k].name.c_str());
exit(1);
}
}
else
{
/* update relocation information to reflect symbol */
reloc->ttype=REL_SEGDISP;
reloc->disp=sym[k].value;
if(sym[k].section==-1)
{
/* absolute symbols have section=-1 */
reloc->target=-1;
}
else
{
/* else get real number of section */
reloc->target=sym[k].section+minseg-1;
}
}
break;
default:
printf("undefined symbol class 0x%02X for symbol %s\n",sym[k].coff_class,sym[k].name.c_str());
exit(1);
}
}
if(reloc->ttype==REL_EXTONLY)
{
/* set relocation target to external if sym is external */
reloc->target=sym[k].extnum;
}
/* frame is current segment (only relevant for non-FLAT output) */
reloc->ftype=REL_SEGFRAME;
reloc->frame=i+minseg;
/* set relocation type */
switch(get16(buf,8))
{
case COFF_FIX_DIR32:
reloc->rtype=FIX_OFS32;
break;
case COFF_FIX_RVA32:
reloc->rtype=FIX_RVA32;
break;
/*
case 0x0a: -
break;
case 0x0b:
break;
*/
case COFF_FIX_REL32:
reloc->rtype=FIX_SELF_OFS32;
break;
default:
printf("unsupported COFF relocation type %04X\n",buf[8]+(buf[9]<<8));
exit(1);
}
relocs.push_back(reloc);
}
seglist.push_back(seg);
}
/* build PUBDEFs or COMDEFs for external symbols defined here that aren't COMDAT symbols. */
for(i=0;i<numSymbols;i++)
{
printf("sym[%d].section %d (%s)\n", i, sym[i].section, sym[i].name.c_str());
if(sym[i].coff_class!=COFF_SYM_EXTERNAL) continue;
if(sym[i].isComDat) continue;
if(sym[i].section<-1)
{
break;
}
if(sym[i].section==0)
{
if(sym[i].value)
{
PCOMREC com = new COMREC();
com->length=sym[i].value;
com->isFar=FALSE;
com->name=sym[i].name;
com->modnum=0;
comdefs.push_back(com);
}
}
else
{
pubdef=new PUBLIC();
pubdef->grpnum=-1;
pubdef->typenum=0;
pubdef->modnum=0;
pubdef->aliasName="";
pubdef->ofs=sym[i].value;
if(sym[i].section==-1)
{
pubdef->seg=0;
}
else
{
pubdef->seg=seglist[minseg+sym[i].section-1];
}
if((listnode=publics.find(sym[i].name)) != publics.end())
{
for(j=0;j<listnode->second.size();++j)
{
if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum)
{
if(((PPUBLIC)listnode->second[j])->aliasName == "")
{
printf("Duplicate public symbol %s\n",sym[i].name.c_str());
exit(1);
}
(*((PPUBLIC)listnode->second[j]))=(*pubdef);
pubdef=NULL;
break;
}
}
}
if(pubdef)
{
SORTLIST::iterator it = publics.find(sym[i].name);
if( it == publics.end() ) {
std::vector<void *> vv;
vv.push_back((void *)pubdef);
publics.insert(std::make_pair(sym[i].name, vv));
} else {
it->second.push_back((void *)pubdef);
}
}
}
}
}
void loadCoffImport(FILE *objfile)
{
UINT fileStart;
UINT thiscpu;
fileStart=ftell(objfile);
if(fread(&buf[0],1,20,objfile)!=20)
{
printf("Unable to read from file\n");
exit(1);
}
if(get32(buf,0) != 0xffff0000)
{
printf("Invalid Import entry\n");
exit(1);
}
/* get CPU type */
thiscpu=get16(buf,6);
printf("Import CPU=%04X\n",thiscpu);
if(thiscpu!=0x14c && thiscpu!=0x1f0)
{
printf("Unsupported CPU type for module (type %x)\n", thiscpu);
exit(1);
}
}
+310
View File
@@ -0,0 +1,310 @@
#include "alink.h"
#define strupr(x)
void loadCoffLib(FILE *libfile,std::string libname)
{
UINT i,j;
UINT numsyms;
UINT modpage;
UINT memberSize;
UINT startPoint;
PUCHAR endptr;
PLIBFILE p;
std::string name;
std::vector<UCHAR> modbuf;
SORTLIST symlist;
int x;
libfiles.push_back(LIBFILE());
p=&libfiles[libfiles.size()-1];
p->filename=libname;
startPoint=ftell(libfile);
if(fread(&buf[0],1,8,libfile)!=8)
{
printf("Error reading from file\n");
exit(1);
}
buf[8]=0;
/* complain if file header is wrong */
if(strcmp((char *)&buf[0],"!<arch>\n"))
{
printf("Invalid library file format - bad file header\n");
printf("\"%s\"\n",&buf[0]);
exit(1);
}
/* read archive member header */
if(fread(&buf[0],1,60,libfile)!=60)
{
printf("Error reading from file\n");
exit(1);
}
if((buf[58]!=0x60) || (buf[59]!='\n'))
{
printf("Invalid library file format - bad member signature\n");
exit(1);
}
buf[16]=0;
/* check name of first linker member */
if(strcmp((char *)&buf[0],"/ ")) /* 15 spaces */
{
printf("Invalid library file format - bad member name\n");
exit(1);
}
buf[58]=0;
/* strip trailing spaces from size */
endptr=&buf[57];
while((endptr>(&buf[48])) && isspace(*endptr))
{
*endptr=0;
endptr--;
}
/* get size */
errno=0;
memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10);
if(errno || (*endptr))
{
printf("Invalid library file format - bad member size\n");
exit(1);
}
if((memberSize<4) && memberSize)
{
printf("Invalid library file format - bad member size\n");
exit(1);
}
if(!memberSize)
{
numsyms=0;
}
else
{
if(fread(&buf[0],1,4,libfile)!=4)
{
printf("Error reading from file\n");
exit(1);
}
numsyms=buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24);
}
printf("%u symbols\n",numsyms);
if(numsyms)
{
if(fread(&modbuf[0],1,4*numsyms,libfile)!=4*numsyms)
{
printf("Error reading from file\n");
exit(1);
}
}
for(i=0;i<numsyms;i++)
{
modpage=modbuf[3+i*4]+(modbuf[2+i*4]<<8)+(modbuf[1+i*4]<<16)+(modbuf[i*4]<<24);
for(j=0;TRUE;j++)
{
if((x=getc(libfile))==EOF)
{
printf("Error reading from file\n");
exit(1);
}
if(!x) break;
name+=(char)x;
}
if(!name.size())
{
printf("NULL name for symbol %i\n",i);
exit(1);
}
if(!case_sensitive)
{
strupr(name);
}
std::vector<void *> vv;
vv.resize(modpage);
symlist.insert(std::make_pair(name, vv));
}
if(numsyms)
{
p->symbols=symlist;
}
/* move to an even byte boundary in the file */
if(ftell(libfile)&1)
{
fseek(libfile,1,SEEK_CUR);
}
if(ftell(libfile)!=(startPoint+68+memberSize))
{
printf("Invalid first linker member\n");
printf("Pos=%08X, should be %08X\n",ftell(libfile),startPoint+68+memberSize);
exit(1);
}
printf("Loaded first linker member\n");
startPoint=ftell(libfile);
/* read archive member header */
if(fread(&buf[0],1,60,libfile)!=60)
{
printf("Error reading from file\n");
exit(1);
}
if((buf[58]!=0x60) || (buf[59]!='\n'))
{
printf("Invalid library file format - bad member signature\n");
exit(1);
}
buf[16]=0;
/* check name of second linker member */
if(!strcmp((char *)&buf[0],"/ ")) /* 15 spaces */
{
/* OK, so we've found it, now skip over */
buf[58]=0;
/* strip trailing spaces from size */
endptr=&buf[57];
while((endptr>(&buf[48])) && isspace(*endptr))
{
*endptr=0;
endptr--;
}
/* get size */
errno=0;
memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10);
if(errno || (*endptr))
{
printf("Invalid library file format - bad member size\n");
exit(1);
}
if((memberSize<8) && memberSize)
{
printf("Invalid library file format - bad member size\n");
exit(1);
}
/* move over second linker member */
fseek(libfile,startPoint+60+memberSize,SEEK_SET);
/* move to an even byte boundary in the file */
if(ftell(libfile)&1)
{
fseek(libfile,1,SEEK_CUR);
}
}
else
{
fseek(libfile,startPoint,SEEK_SET);
}
startPoint=ftell(libfile);
p->longnames.resize(0);
/* read archive member header */
if(fread(&buf[0],1,60,libfile)!=60)
{
printf("Error reading from file\n");
exit(1);
}
if((buf[58]!=0x60) || (buf[59]!='\n'))
{
printf("Invalid library file format - bad 3rd member signature\n");
exit(1);
}
buf[16]=0;
/* check name of long names linker member */
if(!strcmp((char *)&buf[0],"// ")) /* 14 spaces */
{
buf[58]=0;
/* strip trailing spaces from size */
endptr=&buf[57];
while((endptr>(&buf[48])) && isspace(*endptr))
{
*endptr=0;
endptr--;
}
/* get size */
errno=0;
memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10);
if(errno || (*endptr))
{
printf("Invalid library file format - bad member size\n");
exit(1);
}
if(memberSize)
{
p->longnames.resize(memberSize);
if(fread(&p->longnames[0],1,memberSize,libfile)!=memberSize)
{
printf("Error reading from file\n");
exit(1);
}
}
}
else
{
/* if no long names member, move back to member header */
fseek(libfile,startPoint,SEEK_SET);
}
p->modsloaded=0;
p->modlist.resize(numsyms);
p->libtype='C';
p->blocksize=1;
p->flags=LIBF_CASESENSITIVE;
}
void loadcofflibmod(PLIBFILE p,FILE *libfile)
{
char *name;
UINT ofs;
if(fread(&buf[0],1,60,libfile)!=60)
{
printf("Error reading from file\n");
exit(1);
}
if((buf[58]!=0x60) || (buf[59]!='\n'))
{
printf("Invalid library member header\n");
exit(1);
}
buf[16]=0;
if(buf[0]=='/')
{
ofs=15;
while(isspace(buf[ofs]))
{
buf[ofs]=0;
ofs--;
}
ofs=strtoul((char *)&buf[1],&name,10);
if(!buf[1] || *name)
{
printf("Invalid string number \n");
exit(1);
}
name=(char *)&p->longnames[0]+ofs;
}
else
{
name=(char *)&buf[0];
}
printf("Loading module %s\n",name);
loadcoff(libfile);
}
+519
View File
@@ -0,0 +1,519 @@
#include "alink.h"
void fixpubsegs(PSEG src,PSEG dest,UINT shift)
{
UINT i,j;
PPUBLIC q;
SORTLIST::iterator it;
for(it=publics.begin();it!=publics.end();++it)
{
for(j=0;j<it->second.size();++it)
{
q=(PPUBLIC)it->second[j];
if(q->seg==src)
{
q->seg=dest;
q->ofs+=shift;
}
}
}
}
void fixpubgrps(int src,int dest)
{
UINT i,j;
PPUBLIC q;
SORTLIST::iterator it;
for(it=publics.begin();it!=publics.end();++it)
{
for(j=0;j<it->second.size();++j)
{
q=(PPUBLIC)it->second[j];
if(q->grpnum==src)
{
q->grpnum=dest;
}
}
}
}
void combine_segments(PSEG destseg,PSEG srcseg)
{
UINT k,n;
std::vector<unsigned char> p,q;
long a1,a2;
assert(destseg != srcseg);
k=destseg->length;
switch(srcseg->attr&SEG_ALIGN)
{
case SEG_WORD:
a2=2;
k=(k+1)&0xfffffffe;
break;
case SEG_PARA:
a2=16;
k=(k+0xf)&0xfffffff0;
break;
case SEG_PAGE:
a2=0x100;
k=(k+0xff)&0xffffff00;
break;
case SEG_DWORD:
a2=4;
k=(k+3)&0xfffffffc;
break;
case SEG_MEMPAGE:
a2=0x1000;
k=(k+0xfff)&0xfffff000;
break;
case SEG_8BYTE:
a2=8;
k=(k+7)&0xfffffff8;
break;
case SEG_32BYTE:
a2=32;
k=(k+31)&0xffffffe0;
break;
case SEG_64BYTE:
a2=64;
k=(k+63)&0xffffffc0;
break;
default:
a2=1;
break;
}
switch(destseg->attr&SEG_ALIGN)
{
case SEG_WORD:
a1=2;
break;
case SEG_DWORD:
a1=4;
break;
case SEG_8BYTE:
a1=8;
break;
case SEG_PARA:
a1=16;
break;
case SEG_32BYTE:
a1=32;
break;
case SEG_64BYTE:
a1=64;
break;
case SEG_PAGE:
a1=0x100;
break;
case SEG_MEMPAGE:
a1=0x1000;
break;
default:
a1=1;
break;
}
srcseg->setbase(k);
p.resize(k+srcseg->length);
q.resize((k+srcseg->length+7)/8);
for(k=0;k<destseg->length;k++)
{
if(GetNbit(destseg->datmask,k))
{
SetNbit(q,k);
p[k]=destseg->data[k];
}
else
{
ClearNbit(q,k);
}
}
for(;k<srcseg->getbase();k++)
{
ClearNbit(q,k);
}
for(;k<(srcseg->getbase()+srcseg->length);k++)
{
if(GetNbit(srcseg->datmask,k-srcseg->getbase()))
{
p[k]=srcseg->data[k-srcseg->getbase()];
SetNbit(q,k);
}
else
{
ClearNbit(q,k);
}
}
destseg->length=k;
if(a2>a1) destseg->attr=srcseg->attr;
destseg->winFlags |= srcseg->winFlags;
destseg->data=p;
destseg->datmask=q;
fixpubsegs(srcseg,destseg,srcseg->getbase());
for(k=0;k<relocs.size();k++)
{
if(relocs[k]->seg==srcseg)
{
relocs[k]->seg=destseg;
relocs[k]->ofs+=srcseg->getbase();
}
if(relocs[k]->ttype==REL_SEGDISP)
{
if(relocs[k]->targseg==srcseg)
{
relocs[k]->targseg=destseg;
relocs[k]->disp=srcseg->getbase();
}
}
else if(relocs[k]->ttype==REL_SEGONLY)
{
if(relocs[k]->targseg==srcseg)
{
relocs[k]->targseg=destseg;
relocs[k]->ttype=REL_SEGDISP;
relocs[k]->disp=srcseg->getbase();
}
}
if((relocs[k]->ftype==REL_SEGFRAME) ||
(relocs[k]->ftype==REL_LILEFRAME))
{
if(relocs[k]->seg==srcseg)
{
relocs[k]->seg=destseg;
}
}
}
if(gotstart)
{
if(startaddr.ttype==REL_SEGDISP)
{
if(startaddr.targseg==srcseg)
{
startaddr.targseg=destseg;
startaddr.disp+=srcseg->getbase();
}
}
else if(startaddr.ttype==REL_SEGONLY)
{
if(startaddr.targseg==srcseg)
{
startaddr.targseg=destseg;
startaddr.disp=srcseg->getbase();
startaddr.ttype=REL_SEGDISP;
}
}
if((startaddr.ftype==REL_SEGFRAME) ||
(startaddr.ftype==REL_LILEFRAME))
{
if(startaddr.seg==srcseg)
{
startaddr.seg=destseg;
}
}
}
for(k=0;k<grplist.size();k++)
{
if(grplist[k])
{
for(n=0;n<grplist[k]->numsegs;n++)
{
if(grplist[k]->segindex[n]==srcseg)
{
grplist[k]->segindex[n]=destseg;
}
}
}
}
srcseg=0;
}
void combine_common(long i,long j)
{
UINT k,n;
std::vector<unsigned char> p,q;
if(seglist[j]->length>seglist[i]->length)
{
k=seglist[i]->length;
seglist[i]->length=seglist[j]->length;
seglist[j]->length=k;
p=seglist[i]->data;
q=seglist[i]->datmask;
seglist[i]->data=seglist[j]->data;
seglist[i]->datmask=seglist[j]->datmask;
}
else
{
p=seglist[j]->data;
q=seglist[j]->datmask;
}
for(k=0;k<seglist[j]->length;k++)
{
if(GetNbit(q,k))
{
if(GetNbit(seglist[i]->datmask,k))
{
if(seglist[i]->data[k]!=p[k])
{
ReportError(ERR_OVERWRITE);
}
}
else
{
SetNbit(seglist[i]->datmask,k);
seglist[i]->data[k]=p[k];
}
}
}
fixpubsegs(seglist[j],seglist[i],0);
for(k=0;k<relocs.size();k++)
{
if(relocs[k]->seg==seglist[j])
{
relocs[k]->seg=seglist[i];
}
if(relocs[k]->ttype==REL_SEGDISP)
{
if(relocs[k]->target==j)
{
relocs[k]->target=i;
}
}
else if(relocs[k]->ttype==REL_SEGONLY)
{
if(relocs[k]->target==j)
{
relocs[k]->target=i;
}
}
if((relocs[k]->ftype==REL_SEGFRAME) ||
(relocs[k]->ftype==REL_LILEFRAME))
{
if(relocs[k]->frame==j)
{
relocs[k]->frame=i;
}
}
}
if(gotstart)
{
if(startaddr.ttype==REL_SEGDISP)
{
if(startaddr.target==j)
{
startaddr.target=i;
}
}
else if(startaddr.ttype==REL_SEGONLY)
{
if(startaddr.target==j)
{
startaddr.target=i;
}
}
if((startaddr.ftype==REL_SEGFRAME) ||
(startaddr.ftype==REL_LILEFRAME))
{
if(startaddr.frame==j)
{
startaddr.frame=i;
}
}
}
for(k=0;k<grplist.size();k++)
{
if(grplist[k])
{
for(n=0;n<grplist[k]->numsegs;n++)
{
if(grplist[k]->segindex[n]==seglist[j])
{
grplist[k]->segindex[n]=seglist[i];
}
}
}
}
free(seglist[j]);
seglist[j]=0;
}
void combine_groups(long i,long j)
{
long n,m;
char match;
for(n=0;n<grplist[j]->numsegs;n++)
{
match=0;
for(m=0;m<grplist[i]->numsegs;m++)
{
if(grplist[j]->segindex[n]==grplist[i]->segindex[m])
{
match=1;
}
}
if(!match)
{
grplist[i]->numsegs++;
grplist[i]->segindex[grplist[i]->numsegs]=grplist[j]->segindex[n];
}
}
free(grplist[j]);
grplist[j]=0;
fixpubgrps(j,i);
for(n=0;n<relocs.size();n++)
{
if(relocs[n]->ftype==REL_GRPFRAME)
{
if(relocs[n]->frame==j)
{
relocs[n]->frame=i;
}
}
if((relocs[n]->ttype==REL_GRPONLY) || (relocs[n]->ttype==REL_GRPDISP))
{
if(relocs[n]->target==j)
{
relocs[n]->target=i;
}
}
}
if(gotstart)
{
if((startaddr.ttype==REL_GRPDISP) || (startaddr.ttype==REL_GRPONLY))
{
if(startaddr.target==j)
{
startaddr.target=i;
}
}
if(startaddr.ftype==REL_GRPFRAME)
{
if(startaddr.frame==j)
{
startaddr.frame=i;
}
}
}
}
void combineBlocks()
{
long i,j,k;
std::string name;
long attr;
UINT count;
std::vector<UINT> slist;
UINT curseg;
for(i=0;i<seglist.size();i++)
{
if(seglist[i]&&((seglist[i]->attr&SEG_ALIGN)!=SEG_ABS))
{
if(seglist[i]->winFlags & WINF_COMDAT) continue; /* don't combine COMDAT segments */
name=seglist[i]->name;
attr=seglist[i]->attr&(SEG_COMBINE|SEG_USE32);
switch(attr&SEG_COMBINE)
{
case SEG_STACK:
for(j=i+1;j<seglist.size();j++)
{
if(!seglist[j]) continue;
if(seglist[j]->winFlags & WINF_COMDAT) continue;
if((seglist[j]->attr&SEG_ALIGN)==SEG_ABS) continue;
if((seglist[j]->attr&SEG_COMBINE)!=SEG_STACK) continue;
combine_segments(seglist[i],seglist[j]);
}
break;
case SEG_PUBLIC:
case SEG_PUBLIC2:
case SEG_PUBLIC3:
slist.resize(1);
slist[0] = i;
/* get list of segments to combine */
for(j=i+1,count=1;j<seglist.size();j++)
{
if(!seglist[j]) continue;
if(seglist[j]->winFlags & WINF_COMDAT) continue;
if((seglist[j]->attr&SEG_ALIGN)==SEG_ABS) continue;
if(attr!=(seglist[j]->attr&(SEG_COMBINE|SEG_USE32))) continue;
if(name != seglist[j]->name) continue;
slist.push_back(j);
}
/* sort them by sortorder */
for(j=0;j<count;j++)
{
for(k=j+1;k<count;k++)
{
if(seglist[slist[k]]->orderindex<0 ||
seglist[slist[j]]->orderindex<0) continue;
if(seglist[slist[j]]->name >
seglist[slist[k]]->name) {
int x = slist[k];
slist[k] = slist[j];
slist[j] = x;
}
}
}
/* then combine in that order */
for(j=1;j<count;j++)
{
combine_segments(seglist[slist[0]],seglist[slist[j]]);
}
break;
case SEG_COMMON:
for(j=i+1;j<seglist.size();j++)
{
if((seglist[j]&&((seglist[j]->attr&SEG_ALIGN)!=SEG_ABS)) &&
((seglist[i]->attr&(SEG_ALIGN|SEG_COMBINE|SEG_USE32))==(seglist[j]->attr&(SEG_ALIGN|SEG_COMBINE|SEG_USE32)))
&&
(name == seglist[j]->name)
&& !(seglist[j]->winFlags & WINF_COMDAT)
)
{
combine_common(i,j);
}
}
break;
default:
break;
}
}
}
for(i=0;i<grplist.size();i++)
{
if(grplist[i])
{
for(j=i+1;j<grplist.size();j++)
{
if(!grplist[j]) continue;
if(grplist[i]->name == grplist[j]->name)
{
combine_groups(i,j);
}
}
}
}
}
+693
View File
@@ -0,0 +1,693 @@
#include "alink.h"
#include <assert.h>
#define strupr(x)
unsigned short get16(unsigned char **src)
{
unsigned short out = ((*src)[0] & 0xff) | (((*src)[1] & 0xff) << 8);
*src += 2;
return out;
}
unsigned long get32(unsigned char **src)
{
unsigned long out =
((*src)[0] & 0xff) |
(((*src)[1] & 0xff) << 8) |
(((*src)[2] & 0xff) << 16) |
(((*src)[3] & 0xff) << 24);
*src += 4;
return out;
}
int wantSeg(PSEG seg)
{
return
!((seg->name.find(".debug") != std::string::npos) ||
(seg->name.find(".rela") != std::string::npos) ||
(seg->name.find("symtab") != std::string::npos) ||
(seg->name.find("strtab") != std::string::npos));
}
int readElf32Hdr(FILE *objfile, PELF32HDR elf32hdr)
{
unsigned char headbuf[52];
PUCHAR hptr = headbuf;
if(fread(headbuf,1,52,objfile)!=52)
{
return 0;
}
memcpy(elf32hdr->e_ident, headbuf, EI_NIDENT);
hptr += EI_NIDENT;
elf32hdr->e_type = get16(&hptr);
elf32hdr->e_machine = get16(&hptr);
elf32hdr->e_version = get32(&hptr);
elf32hdr->e_entry = get32(&hptr);
elf32hdr->e_phoff = get32(&hptr);
elf32hdr->e_shoff = get32(&hptr);
elf32hdr->e_flags = get32(&hptr);
elf32hdr->e_ehsize = get16(&hptr);
elf32hdr->e_phentsize=get16(&hptr);
elf32hdr->e_phnum = get16(&hptr);
elf32hdr->e_shentsize=get16(&hptr);
elf32hdr->e_shnum = get16(&hptr);
elf32hdr->e_shtrndx = get16(&hptr);
return 1;
}
int readElf32SHdr(FILE *objfile, PELF32SHDR elf32shdr)
{
unsigned char buf[40];
PUCHAR bptr = buf;
if(fread(buf,1,40,objfile)!=40)
{
return 0;
}
elf32shdr->sh_name = get32(&bptr);
elf32shdr->sh_type = get32(&bptr);
elf32shdr->sh_flags = get32(&bptr);
elf32shdr->sh_addr = get32(&bptr);
elf32shdr->sh_offset = get32(&bptr);
elf32shdr->sh_size = get32(&bptr);
elf32shdr->sh_link = get32(&bptr);
elf32shdr->sh_info = get32(&bptr);
elf32shdr->sh_addralign =get32(&bptr);
elf32shdr->sh_entsize = get32(&bptr);
return 1;
}
int readElf32Sym(FILE *objfile, PELF32SYM elf32sym)
{
unsigned char buf[16];
unsigned char *bptr = buf;
if(fread(buf,1,16,objfile)!=16)
{
return 0;
}
elf32sym->st_name = get32(&bptr);
elf32sym->st_value = get32(&bptr);
elf32sym->st_size = get32(&bptr);
elf32sym->st_info = *bptr; bptr++;
elf32sym->st_other = *bptr; bptr++;
elf32sym->st_shndx = get16(&bptr);
return 1;
}
int readElf32Rel(FILE *objfile, PELF32RELX elf32rel)
{
unsigned char buf[8];
unsigned char *bptr = buf;
if(fread(buf,1,8,objfile)!=8)
{
return 0;
}
elf32rel->r_offset = get32(&bptr);
elf32rel->r_info = get32(&bptr);
elf32rel->r_address= 0;
return 1;
}
int readElf32Rela(FILE *objfile, PELF32RELX elf32rel)
{
unsigned char buf[12];
unsigned char *bptr = buf;
if(fread(buf,1,12,objfile)!=12)
{
return 0;
}
elf32rel->r_offset = get32(&bptr);
elf32rel->r_info = get32(&bptr);
elf32rel->r_address= get32(&bptr);
return 1;
}
void swapscn( PELF32SHDR seca, PELF32SHDR secb ) {
ELF32SHDR scn;
memcpy(&scn, seca, sizeof(scn));
memcpy(seca, secb, sizeof(scn));
memcpy(secb, &scn, sizeof(scn));
}
void loadelf(FILE *objfile)
{
unsigned char buf[100];
PUCHAR bigbuf;
std::vector<UCHAR> stringList;
UINT thiscpu;
UINT symbolPtr = 0;
UINT numSymbols;
UINT stringPtr = 0;
UINT stringSize;
UINT stringOfs;
UINT curBase = 0;
UINT i,j,k,l;
UINT fileStart;
UINT relcount = 0;
UINT bss, bsscur = 0;
std::vector<COFFSYM> sym;
PPUBLIC pubdef;
PCOMDAT comdat;
PCHAR comdatsym;
SORTLIST::iterator listnode;
ELF32HDR elf32hdr;
std::vector<ELF32SHDR> elf32shdr;
int elf32sn = 0;
ELF32SYM elf32sym;
std::vector<int> stringListOffsets;
int stringOffset = 0, secNum;
std::vector<ELF32RELX> rel;
fileStart=ftell(objfile);
if(!readElf32Hdr(objfile, &elf32hdr))
{
printf("Unable to read from file\n");
exit(1);
}
if( elf32hdr.e_machine == EM_386 )
cpuIdent = PE_INTEL386;
else if( elf32hdr.e_machine == EM_PPC )
cpuIdent = PE_POWERPC;
if( !cpuIdent ) {
printf("Unsupported CPU type for module (type %x)\n", elf32hdr.e_machine);
exit(1);
}
elf32shdr.resize((elf32hdr.e_shnum * 2) + 1);
memset(&elf32shdr[0], 0, (sizeof(elf32shdr[0]) * elf32hdr.e_shnum * 2) + 1);
stringListOffsets.resize(elf32hdr.e_shnum);
/* Find a symbol section */
for( i = 0; i < elf32hdr.e_shnum; i++ )
{
int seekto = fileStart + elf32hdr.e_shoff + elf32hdr.e_shentsize * i;
if(fseek(objfile, seekto, 0)==-1)
{
printf("Short elf file (wanted to seek to %d)\n", seekto);
exit(1);
}
if(!readElf32SHdr(objfile, &(elf32shdr[i])))
{
printf("Could not read elf section header %d\n", i);
exit(1);
}
}
/* Find string tables */
for( i = 0; i < elf32hdr.e_shnum; i++ )
{
if( elf32shdr[i].sh_type != SHT_STRTAB ) continue;
stringPtr = elf32shdr[i].sh_offset;
stringSize = elf32shdr[i].sh_size + 1;
if(fseek(objfile,fileStart+stringPtr,SEEK_SET)==-1)
{
printf("Short elf file, unable to seek to (%d)\n", stringPtr);
exit(1);
}
if(stringSize)
{
stringList.resize(stringSize + stringOffset);
if(fread(&stringList[0]+stringOffset,1,stringSize - 1,objfile)!=stringSize - 1)
{
printf("Invalid elf object file, unable to read string table\n");
exit(1);
}
stringList[stringSize-1] = 0;
stringListOffsets[i] = stringOffset;
stringOffset += stringSize;
}
}
/* Find segment order */
for( i = 0; i < elf32hdr.e_shnum; i++ )
{
const char *segname = (char *)
&stringList[0] + stringListOffsets[elf32hdr.e_shtrndx] +
elf32shdr[i].sh_name;
if(elf32shdr[i].sh_type == SHT_REL ||
elf32shdr[i].sh_type == SHT_RELA ||
elf32shdr[i].sh_type == SHT_SYMTAB ||
elf32shdr[i].sh_type == SHT_STRTAB)
continue;
if(!strcmp(segname,".bss"))
{
bss = i;
bsscur = elf32shdr[i].sh_size;
}
}
for( i = 0; i < elf32hdr.e_shnum; i++ )
{
if(elf32shdr[i].sh_type == SHT_REL ||
elf32shdr[i].sh_type == SHT_RELA ||
elf32shdr[i].sh_type == SHT_SYMTAB ||
elf32shdr[i].sh_type == SHT_STRTAB)
continue;
}
memcpy(&elf32shdr[elf32hdr.e_shnum], &elf32shdr[0], sizeof(elf32shdr[0]));
memcpy(&elf32shdr[0], &elf32shdr[elf32sn], sizeof(elf32shdr[0]) * elf32sn);
elf32sn = elf32hdr.e_shnum;
for( i = 0; i < elf32sn; i++ )
{
if(stringPtr && !symbolPtr && elf32shdr[i].sh_type == SHT_SYMTAB)
{
int actualNum = 0;
symbolPtr = elf32shdr[i].sh_offset;
numSymbols = elf32shdr[i].sh_size / ELF32SYMSIZE;
if(fseek(objfile,fileStart+symbolPtr,SEEK_SET)==-1)
{
printf("Short elf file, unable to seek to (%d)\n", symbolPtr);
exit(1);
}
sym.resize(numSymbols);
for( j = 0; j < numSymbols; j++ )
{
if(!readElf32Sym(objfile, &elf32sym))
{
printf("Could not read elf symbol %d\n", i);
exit(1);
}
sym[j].name = (char *)
(&stringList[stringListOffsets[elf32shdr[i].sh_link]] +
elf32sym.st_name);
#if 0
fprintf(stderr,
"S[%05x] value %08x size %08x info %08x "
"other %08x shndx %08x %s\n",
j,
elf32sym.st_value, elf32sym.st_size, elf32sym.st_info,
elf32sym.st_other, elf32sym.st_shndx, sym[j].name.c_str());
#endif
if(!case_sensitive)
{
strupr(sym[j].name);
}
if(elf32sym.st_shndx == SHN_COMMON)
{
UINT thisbss = roundup(bsscur, elf32sym.st_value);
/* Round up bss objects */
bsscur = thisbss + elf32sym.st_size;
sym[j].section = bss;
sym[j].value = thisbss;
sym[j].coff_class = COFF_SYM_EXTERNAL;
//fprintf( stderr, "BSS: @%08x(%04x) %s\n", sym[j].value, elf32sym.st_size, sym[j].name.c_str() );
}
else
{
if(sym[j].name == entryPoint)
sym[j].coff_class = COFF_SYM_EXTERNAL;
else
sym[j].coff_class = COFF_SYM_STATIC;
sym[j].section = elf32sym.st_shndx;
sym[j].value = elf32sym.st_value;
}
sym[j].extnum = -1;
sym[j].type = COFFTYPE(DT_FCN,T_NULL);
}
}
else if(elf32shdr[i].sh_type == SHT_REL ||
elf32shdr[i].sh_type == SHT_RELA)
{
int rela = elf32shdr[i].sh_type == SHT_RELA;
int size = rela ? sizeof(ELF32RELA) : 8;
int oldrel = relcount;
relcount+=elf32shdr[i].sh_size/size;
rel.resize(relcount);
fseek(objfile,fileStart+elf32shdr[i].sh_offset,SEEK_SET);
for( j = oldrel; j < relcount; j++ )
{
if( rela )
readElf32Rela(objfile, &rel[j]);
else
readElf32Rel(objfile, &rel[j]);
rel[j].r_seg = elf32shdr[i].sh_info;
}
}
}
for(i=0;i<elf32sn;i++)
{
PSEG seg = new SEG();
seg->name=
(char *)&stringList[0] + stringListOffsets[elf32hdr.e_shtrndx] +
elf32shdr[i].sh_name;
seg->orderindex=0;
seg->classindex=-1;
seg->overlayindex=-1;
if(seg->name == ".bss")
{
seg->length = bsscur;
}
else
{
seg->length=elf32shdr[i].sh_size;
}
seg->attr=SEG_PUBLIC|SEG_USE32|SEG_DWORD;
seg->winFlags=WINF_ALIGN_DWORD | WINF_READABLE;
seg->fileBase = elf32shdr[i].sh_offset;
seg->setbase(curBase);
if( wantSeg(seg) ) {
curBase += roundup(curBase + seg->length, objectAlign);
} else {
seg->winFlags |= WINF_REMOVE;
}
if( elf32shdr[i].sh_flags & SHF_WRITE )
seg->winFlags |= WINF_WRITEABLE;
if( elf32shdr[i].sh_flags == 0 )
seg->winFlags |= WINF_COMMENT;
switch( elf32shdr[i].sh_type )
{
case SHT_PROGBITS:
if( elf32shdr[i].sh_flags & SHF_EXECINSTR )
seg->winFlags |= WINF_CODE | WINF_EXECUTE;
else
seg->winFlags |= WINF_INITDATA;
break;
case SHT_NOBITS:
if( elf32shdr[i].sh_flags & SHF_WRITE )
seg->winFlags |= WINF_UNINITDATA;
break;
default:
break;
}
if(seg->winFlags & WINF_ALIGN_NOPAD)
{
seg->winFlags &= ~WINF_ALIGN;
seg->winFlags |= WINF_ALIGN_BYTE;
}
/* invert all negative-logic flags */
seg->winFlags ^= WINF_NEG_FLAGS;
seg->datmask.resize(roundup(seg->length,8)/8);
seg->data.resize(roundup(seg->length,8));
if(seg->name == ".bss")
{
memset(&seg->datmask[0], 0, seg->datmask.size());
memset(&seg->data[0], 0, seg->data.size());
}
else
{
memset(&seg->datmask[0], 0xff, seg->datmask.size());
fseek(objfile, seg->fileBase, 0);
fread(&seg->data[0], 1, seg->length, objfile);
}
seglist.push_back(seg);
}
for( i = 0; i < numSymbols; i++ ) {
sym[i].segptr = seglist[sym[i].section];
switch(sym[i].coff_class)
{
case COFF_SYM_SECTION: { /* section symbol */
/* section symbols declare an extern always, so can use in relocs */
/* they may also include a PUBDEF */
EXTREC ext;
ext.name=(char *)sym[i].name.c_str();
ext.pubdef=NULL;
ext.modnum=0;
ext.flags=EXT_NOMATCH;
sym[i].extnum=externs.size();
externs.push_back(ext);
if(sym[i].section) /* if the section is defined here, make public */
{
pubdef=new PUBLIC();
pubdef->grpnum=-1;
pubdef->typenum=0;
pubdef->modnum=0;
pubdef->aliasName="";
pubdef->name = sym[i].name;
pubdef->ofs=sym[i].value;
//fprintf(stderr, "sym[%05d] public %s\n", i, sym[i].name.c_str());
if(sym[i].section==-1)
{
pubdef->seg=NULL;
}
else
{
pubdef->seg=seglist[sym[i].section];
}
if((listnode=publics.find(sym[i].name)) != publics.end())
{
for(j=0;j<listnode->second.size();++j)
{
if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum)
{
if(((PPUBLIC)listnode->second[j])->aliasName=="")
{
printf("Duplicate public symbol %s\n",sym[i].name.c_str());
exit(1);
}
(*((PPUBLIC)listnode->second[j]))=(*pubdef);
pubdef=NULL;
break;
}
}
}
if(pubdef)
{
SORTLIST::iterator it = publics.find(sym[i].name);
if( it == publics.end() ) {
std::vector<void *> vv;
vv.push_back((void *)pubdef);
publics.insert(std::make_pair(sym[i].name, vv));
} else {
it->second.push_back((void *)pubdef);
}
}
}
} break;
case COFF_SYM_EXTERNAL:
case COFF_SYM_STATIC: /* allowed, but ignored for now as we only want to process if required */
case COFF_SYM_LABEL:
case COFF_SYM_FILE:
case COFF_SYM_FUNCTION:
break;
default:
printf("unsupported symbol class %02X for symbol %s\n",sym[i].coff_class,sym[i].name.c_str());
exit(1);
}
}
for(i=0;i<elf32sn;i++)
{
for(j=0;j<relcount;j++)
{
if( (rel[j].r_seg != i) ||
(seglist[rel[j].r_seg]->winFlags & WINF_REMOVE) ) continue;
PRELOC reloc = new RELOC();
/* get address to relocate */
reloc->ofs=rel[j].r_offset;
reloc->orig = rel[j];
reloc->ftype = REL_SEGFRAME;
/* get segment */
reloc->seg = seglist[rel[j].r_seg];
if( cpuIdent == PE_INTEL386 )
reloc->disp=4;
else
reloc->disp=rel[j].r_address;
/* get relocation target external index */
reloc->target=rel[j].r_info >> 8;
if(reloc->target>=numSymbols)
{
printf("Invalid ELF object file, undefined symbol\n");
exit(1);
}
k=reloc->target;
reloc->ttype=REL_EXTDISP; /* assume external reloc */
if(sym[k].extnum<0)
{
switch(sym[k].coff_class)
{
case COFF_SYM_EXTERNAL: {
/* global symbols declare an extern when used in relocs */
EXTREC ext;
ext.name=sym[k].name;
ext.pubdef=NULL;
ext.modnum=0;
ext.flags=EXT_NOMATCH;
sym[k].extnum=externs.size();
externs.push_back(ext);
/* they may also include a COMDEF or a PUBDEF */
/* this is dealt with after all sections loaded, to cater
for COMDAT symbols */
} break;
case COFF_SYM_STATIC: /* static symbol */
case COFF_SYM_LABEL: /* code label symbol */
/* update relocation information to reflect symbol */
reloc->ttype=REL_SEGDISP;
reloc->disp=rel[j].r_address + sym[k].value;
reloc->targseg = seglist[sym[k].section];
break;
default:
printf("undefined symbol class 0x%02X for symbol %s\n",sym[k].coff_class,sym[k].name.c_str());
exit(1);
}
}
if(reloc->ttype==REL_EXTONLY ||
reloc->ttype==REL_EXTDISP)
{
/* set relocation target to external if sym is external */
reloc->target=sym[k].extnum;
}
/* set relocation type */
switch (rel[j].r_info & 0xff)
{
case R_PPC_ADDR32:
reloc->rtype = FIX_ADDR32;
break;
case R_PPC_UADDR32:
reloc->rtype = FIX_RVA32;
break;
case R_PPC_REL32:
reloc->rtype = FIX_REL32;
break;
case R_PPC_ADDR24:
reloc->rtype = FIX_PPC_ADDR24;
break;
case R_PPC_REL24:
reloc->rtype = FIX_PPC_REL24;
break;
case R_PPC_ADDR16_LO:
reloc->rtype = FIX_PPC_RVA16LO;
break;
case R_PPC_ADDR16_HA:
reloc->rtype = FIX_PPC_RVA16HA;
break;
default:
printf("unsupported ELF relocation type %04X\n",rel[j].r_info & 0xff);
exit(1);
}
relocs.push_back(reloc);
}
}
/* build PUBDEFs or COMDEFs for external symbols defined here that aren't COMDAT symbols. */
for(i=0;i<numSymbols;i++)
{
if(sym[i].coff_class!=COFF_SYM_EXTERNAL) continue;
if(sym[i].isComDat) continue;
if(sym[i].section<-1)
{
break;
}
pubdef=new PUBLIC();
pubdef->grpnum=-1;
pubdef->typenum=0;
pubdef->modnum=0;
pubdef->name = sym[i].name;
pubdef->aliasName="";
pubdef->ofs=sym[i].value;
if(sym[i].section==-1)
{
pubdef->seg=0;
}
else
{
pubdef->seg=seglist[sym[i].section];
}
if((listnode=publics.find(sym[i].name)) != publics.end())
{
for(j=0;j<listnode->second.size();++j)
{
if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum)
{
if(((PPUBLIC)listnode->second[j])->aliasName=="")
{
printf("Duplicate public symbol %s\n",sym[i].name.c_str());
exit(1);
}
(*((PPUBLIC)listnode->second[j]))=(*pubdef);
pubdef=NULL;
break;
}
}
}
if(pubdef)
{
SORTLIST::iterator it = publics.find(sym[i].name);
if( it == publics.end() ) {
std::vector<void *> vv;
vv.push_back((void *)pubdef);
publics.insert(std::make_pair(sym[i].name,vv));
} else {
it->second.push_back((void *)pubdef);
}
}
}
for(i = 0; i < seglist.size(); i++) {
if(seglist[i]->winFlags & WINF_REMOVE) {
seglist.erase(seglist.begin()+i);
i--;
}
}
}
@@ -0,0 +1,8 @@
I received permission from Anthony Williams to use alink as the basis for
the elf to coff conversion stage in reactos-powerpc. Thanks to Anthony
for writing alink in a way that made it possible to produce binaries for
reactos-powerpc, and for giving me permission to modify it despite the
license.
This version of alink has been modified heavily, mostly for the benefit
of producing pe-coff powerpc executables.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
What's here as been modified for use with a PowerPC elf toolchain, but retains
every original feature for x86 as well.
General modifications:
- Addition of elf32 input support
- PowerPC and x86 relocation types for elf
- Small bugfixes
elf.c is based on coff.c, modified to deal with elf sections, symbols etc.
@@ -0,0 +1 @@
int main() { return 0; }
Binary file not shown.
@@ -0,0 +1,2 @@
extern int f( int x );
int main() { return f(3); }
@@ -0,0 +1 @@
int f(int x) {return x-3;}
Binary file not shown.
+186
View File
@@ -0,0 +1,186 @@
#include "alink.h"
#define _strdup strdup
int getBitCount(UINT a)
{
int count=0;
while(a)
{
if(a&1) count++;
a>>=1;
}
return count;
}
void ReportError(long errnum)
{
UINT tot,i;
printf("\nError in file at %08lX",filepos);
switch(errnum)
{
case ERR_EXTRA_DATA:
printf(" - extra data in record\n");
break;
case ERR_NO_HEADER:
printf(" - no header record\n");
break;
case ERR_NO_RECDATA:
printf(" - record data not present\n");
break;
case ERR_NO_MEM:
printf(" - insufficient memory\n");
break;
case ERR_INV_DATA:
printf(" - invalid data address\n");
break;
case ERR_INV_SEG:
printf(" - invalid segment number\n");
break;
case ERR_BAD_FIXUP:
printf(" - invalid fixup record\n");
break;
case ERR_BAD_SEGDEF:
printf(" - invalid segment definition record\n");
break;
case ERR_ABS_SEG:
printf(" - data emitted to absolute segment\n");
break;
case ERR_DUP_PUBLIC:
printf(" - duplicate public definition\n");
break;
case ERR_NO_MODEND:
printf(" - unexpected end of file (no MODEND record)\n");
break;
case ERR_EXTRA_HEADER:
printf(" - duplicate module header\n");
break;
case ERR_UNKNOWN_RECTYPE:
printf(" - unknown object module record type %02X\n",rectype);
break;
case ERR_SEG_TOO_LARGE:
printf(" - 4Gb Non-Absolute segments not supported.\n");
break;
case ERR_MULTIPLE_STARTS:
printf(" - start address defined in more than one module.\n");
break;
case ERR_BAD_GRPDEF:
printf(" - illegal group definition\n");
break;
case ERR_OVERWRITE:
printf(" - overlapping data regions\n");
break;
case ERR_INVALID_COMENT:
printf(" - COMENT record format invalid\n");
break;
case ERR_ILLEGAL_IMPORTS:
printf(" - Imports required to link, and not supported by output file type\n");
break;
default:
printf("\n");
}
printf("seg count = %i\n",seglist.size());
printf("extcount=%i\n",externs.size());
printf("grpcount=%i\n",grplist.size());
printf("comcount=%i\n",comdefs.size());
printf("fixcount=%i\n",relocs.size());
printf("impcount=%i\n",impdefs.size());
printf("expcount=%i\n",expdefs.size());
printf("modcount=%i\n",modname.size());
for(i=0,tot=0;i<seglist.size();i++)
{
if(seglist[i] && seglist[i]->data.size())
tot+=seglist[i]->length;
}
printf("total segment size=%08X\n",tot);
exit(1);
}
unsigned short wtoupper(unsigned short a)
{
if(a>=256) return a;
return toupper(a);
}
int wstricmp(const char *s1,const char *s2)
{
int i=0;
unsigned short a,b;
while(TRUE)
{
a=s1[i]+(s1[i+1]<<8);
b=s2[i]+(s2[i+1]<<8);
if(wtoupper(a)<wtoupper(b)) return -1;
if(wtoupper(a)>wtoupper(b)) return +1;
if(!a) return 0;
i+=2;
}
}
int wstrlen(const char *s)
{
int i;
for(i=0;s[i]||s[i+1];i+=2);
return i/2;
}
void *checkMalloc(size_t x)
{
void *p;
p=malloc(x);
if(!p)
{
fprintf(stderr,"Error, Insufficient memory in call to malloc\n");
exit(1);
}
return p;
}
void *checkRealloc(void *p,size_t x)
{
p=realloc(p,x);
if(!p)
{
fprintf(stderr,"Error, Insufficient memory in call to realloc\n");
exit(1);
}
return p;
}
char *checkStrdup(const char *s)
{
char *p;
if(!s)
{
fprintf(stderr,"Error, Taking duplicate of NULL pointer in call to strdup\n");
exit(1);
}
p=strdup(s);
if(!p)
{
fprintf(stderr,"Error, Insufficient memory in call to strdup\n");
exit(1);
}
return p;
}
int _wstricmp(unsigned char *a, unsigned char *b)
{
uint16_t *a16 = (uint16_t*)a, *b16 = (uint16_t*)b;
while(*a16 && (*a16 == *b16)) { a16++; b16++; }
return (*a16 < *b16) ? ((*a16 > *b16) ? 1 : 0) : -1;
}
int _wstrlen(unsigned char *a)
{
uint16_t *a16 = (uint16_t*)a;
while(*a16++);
return a16 - ((uint16_t *)a);
}