mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
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:
@@ -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]
|
||||
@@ -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
@@ -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;
|
||||
@@ -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 $@ $^
|
||||
@@ -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 $@ $^
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Executable
+519
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Executable
+693
@@ -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
@@ -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;}
|
||||
BIN
Binary file not shown.
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user