summaryrefslogtreecommitdiff
path: root/rts/linker/PEi386.h
blob: 4c33dfd4d9c41d87f404f577d20c982efeee70d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#pragma once

#include "Rts.h"
#include "LinkerInternals.h"
#include "PathUtils.h"
#include <windows.h>
#include <stdbool.h>

#include "BeginPrivate.h"

#if defined(x86_64_HOST_ARCH)
#define PEi386_IMAGE_OFFSET 4
#else
#define PEi386_IMAGE_OFFSET 0
#endif

#define PEi386_STRTAB_OFFSET 4

/********************************************
 * COFF/PE types
 ********************************************/

typedef enum _COFF_OBJ_TYPE {
    COFF_IMAGE,
    COFF_ANON_OBJ,
    COFF_IMPORT_LIB,
    COFF_ANON_BIG_OBJ,
    COFF_UNKNOWN
} COFF_OBJ_TYPE;

typedef struct _COFF_HEADER_INFO {
   COFF_OBJ_TYPE type;
   uint16_t sizeOfOptionalHeader;
   uint16_t sizeOfHeader;
   uint32_t pointerToSymbolTable;
   uint32_t numberOfSymbols;
   uint32_t numberOfSections;
} COFF_HEADER_INFO;

/********************************************
 * COFF/PE prototypes
 ********************************************/

void initLinker_PEi386( void );
void exitLinker_PEi386( void );
const char * addDLL_PEi386( pathchar *dll_name, HINSTANCE *instance  );
void freePreloadObjectFile_PEi386( ObjectCode *oc );

bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f);

pathchar* findSystemLibrary_PEi386( pathchar* dll_name );
HsPtr addLibrarySearchPath_PEi386( pathchar* dll_path );
bool removeLibrarySearchPath_PEi386( HsPtr dll_path_index );

bool ocResolve_PEi386     ( ObjectCode* oc );
bool ocRunInit_PEi386     ( ObjectCode *oc );
bool ocGetNames_PEi386    ( ObjectCode* oc );
bool ocVerifyImage_PEi386 ( ObjectCode* oc );
SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl);
bool ocAllocateExtras_PEi386 ( ObjectCode* oc );
SymbolAddr *lookupSymbolInDLLs ( const SymbolName* lbl );
/* See Note [mingw-w64 name decoration scheme] */
/* We use myindex to calculate array addresses, rather than
   simply doing the normal subscript thing.  That's because
   some of the above structs have sizes which are not
   a whole number of words.  GCC rounds their sizes up to a
   whole number of words, which means that the address calcs
   arising from using normal C indexing or pointer arithmetic
   are just plain wrong.  Sigh.
*/
INLINE_HEADER unsigned char *
myindex ( int scale, void* base, int index )
{
    return
        ((unsigned char*)base) + scale * index;
}
pathchar* resolveSymbolAddr_PEi386 ( pathchar* buffer, int size,
                                     SymbolAddr* symbol, uintptr_t* top );

char *get_name_string(
    unsigned char* name,
    ObjectCode* oc);

char* get_sym_name(
    uint8_t* name,
    ObjectCode* oc);

/********************************************
 * COFF/PE headers
 ********************************************/
/* Section 7.1 PE Specification */
typedef IMPORT_OBJECT_HEADER COFF_import_header;
#define sizeof_COFF_import_Header sizeof(COFF_import_header)

typedef IMAGE_SECTION_HEADER COFF_section;
#define sizeof_COFF_section sizeof(COFF_section)


typedef IMAGE_SYMBOL COFF_symbol_og;
#define sizeof_COFF_symbol_og sizeof(COFF_symbol_og)

typedef IMAGE_SYMBOL_EX COFF_symbol_ex;
#define sizeof_COFF_symbol_ex sizeof(COFF_symbol_ex)

typedef IMAGE_RELOCATION COFF_reloc;
#define sizeof_COFF_reloc sizeof(COFF_reloc)

// MingW-w64 is missing these from the implementation. So we have to look them up
typedef DLL_DIRECTORY_COOKIE(WINAPI *LPAddDLLDirectory)(PCWSTR NewDirectory);
typedef WINBOOL(WINAPI *LPRemoveDLLDirectory)(DLL_DIRECTORY_COOKIE Cookie);

/* Combine union of possible symbol types.  */
typedef
union _COFF_symbol {
    COFF_symbol_og og;
    COFF_symbol_ex ex;
} COFF_symbol;

/* A record for storing handles into DLLs. */
typedef
struct _OpenedDLL {
    pathchar*          name;
    struct _OpenedDLL* next;
    HINSTANCE instance;
} OpenedDLL;

/* A record for storing indirectly linked functions from DLLs. */
typedef
struct _IndirectAddr {
    SymbolAddr*           addr;
    struct _IndirectAddr* next;
} IndirectAddr;

/* Some alignment information.  */
typedef
struct _Alignments {
    uint32_t mask;
    uint32_t value;
} Alignments;

/* Util symbol handling functions.  */
COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName );
COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc );
size_t getSymbolSize ( COFF_HEADER_INFO *info );
int32_t getSymSectionNumber ( COFF_HEADER_INFO *info, COFF_symbol* sym );
uint32_t getSymValue ( COFF_HEADER_INFO *info, COFF_symbol* sym );
uint8_t getSymStorageClass ( COFF_HEADER_INFO *info, COFF_symbol* sym );
uint8_t getSymNumberOfAuxSymbols ( COFF_HEADER_INFO *info, COFF_symbol* sym );
uint16_t getSymType ( COFF_HEADER_INFO *info, COFF_symbol* sym );
uint8_t* getSymShortName ( COFF_HEADER_INFO *info, COFF_symbol* sym );

/* See Note [mingw-w64 name decoration scheme] */
#if !defined(x86_64_HOST_ARCH)
#define STRIP_LEADING_UNDERSCORE 1
#else
#define STRIP_LEADING_UNDERSCORE 0
#endif

/*
Note [mingw-w64 name decoration scheme]

What's going on with name decoration? Well, original code
have some crufty and ad-hocish paths related mostly to very old
mingw gcc/binutils/runtime combinations. Now mingw-w64 offers pretty
uniform and MS-compatible decoration scheme across its tools and runtime.

The scheme is pretty straightforward: on 32 bit objects symbols are exported
with underscore prepended (and @ + stack size suffix appended for stdcall
functions), on 64 bits no underscore is prepended and no suffix is appended
because we have no stdcall convention on 64 bits.

See #9218
*/

#include "EndPrivate.h"