ReactOS 0.4.15-dev-7924-g5949c20
pseudo-reloc.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
#include <internal.h>
Include dependency graph for pseudo-reloc.c:

Go to the source code of this file.

Classes

struct  runtime_pseudo_reloc_item_v1
 
struct  runtime_pseudo_reloc_item_v2
 
struct  runtime_pseudo_reloc_v2
 

Macros

#define NO_COPY
 
#define ATTRIBUTE_NORETURN
 
#define __MINGW_LSYMBOL(sym)   sym
 
#define RP_VERSION_V1   0
 
#define RP_VERSION_V2   1
 

Functions

char __MINGW_LSYMBOL (_image_base__)
 
void _pei386_runtime_relocator (void)
 
static void ATTRIBUTE_NORETURN __report_error (const char *msg,...)
 
static void __write_memory (void *addr, const void *src, size_t len)
 
static void do_pseudo_reloc (void *start, void *end, void *base)
 

Variables

char __RUNTIME_PSEUDO_RELOC_LIST__
 
char __RUNTIME_PSEUDO_RELOC_LIST_END__
 

Macro Definition Documentation

◆ __MINGW_LSYMBOL

#define __MINGW_LSYMBOL (   sym)    sym

Definition at line 45 of file pseudo-reloc.c.

◆ ATTRIBUTE_NORETURN

#define ATTRIBUTE_NORETURN

Definition at line 41 of file pseudo-reloc.c.

◆ NO_COPY

#define NO_COPY

Definition at line 35 of file pseudo-reloc.c.

◆ RP_VERSION_V1

#define RP_VERSION_V1   0

Definition at line 294 of file pseudo-reloc.c.

◆ RP_VERSION_V2

#define RP_VERSION_V2   1

Definition at line 295 of file pseudo-reloc.c.

Function Documentation

◆ __MINGW_LSYMBOL()

char __MINGW_LSYMBOL ( _image_base__  )

◆ __report_error()

static void ATTRIBUTE_NORETURN __report_error ( const char msg,
  ... 
)
static

Definition at line 83 of file pseudo-reloc.c.

84{
85#ifdef __CYGWIN__
86 /* This function is used to print short error messages
87 * to stderr, which may occur during DLL initialization
88 * while fixing up 'pseudo' relocations. This early, we
89 * may not be able to use cygwin stdio functions, so we
90 * use the win32 WriteFile api. This should work with both
91 * normal win32 console IO handles, redirected ones, and
92 * cygwin ptys.
93 */
94 char buf[SHORT_MSG_BUF_SZ];
95 wchar_t module[MAX_PATH];
96 char * posix_module = NULL;
97 static const char UNKNOWN_MODULE[] = "<unknown module>: ";
98 static const size_t UNKNOWN_MODULE_LEN = sizeof (UNKNOWN_MODULE) - 1;
99 static const char CYGWIN_FAILURE_MSG[] = "Cygwin runtime failure: ";
100 static const size_t CYGWIN_FAILURE_MSG_LEN = sizeof (CYGWIN_FAILURE_MSG) - 1;
101 DWORD len;
102 DWORD done;
105 ssize_t modulelen = GetModuleFileNameW (NULL, module, sizeof (module));
106
107 if (errh == INVALID_HANDLE_VALUE)
108 cygwin_internal (CW_EXIT_PROCESS,
109 STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
110 1);
111
112 if (modulelen > 0)
113 posix_module = cygwin_create_path (CCP_WIN_W_TO_POSIX, module);
114
115 va_start (args, msg);
116 len = (DWORD) vsnprintf (buf, SHORT_MSG_BUF_SZ, msg, args);
117 va_end (args);
118 buf[SHORT_MSG_BUF_SZ-1] = '\0'; /* paranoia */
119
120 if (posix_module)
121 {
122 WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
123 CYGWIN_FAILURE_MSG_LEN, &done, NULL);
124 WriteFile (errh, (PCVOID)posix_module,
125 strlen(posix_module), &done, NULL);
126 WriteFile (errh, (PCVOID)": ", 2, &done, NULL);
127 WriteFile (errh, (PCVOID)buf, len, &done, NULL);
128 free (posix_module);
129 }
130 else
131 {
132 WriteFile (errh, (PCVOID)CYGWIN_FAILURE_MSG,
133 CYGWIN_FAILURE_MSG_LEN, &done, NULL);
134 WriteFile (errh, (PCVOID)UNKNOWN_MODULE,
135 UNKNOWN_MODULE_LEN, &done, NULL);
136 WriteFile (errh, (PCVOID)buf, len, &done, NULL);
137 }
138 WriteFile (errh, (PCVOID)"\n", 1, &done, NULL);
139
140 cygwin_internal (CW_EXIT_PROCESS,
141 STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION,
142 1);
143 /* not reached, but silences noreturn warning */
144 abort ();
145#else
146 va_list argp;
147 va_start (argp, msg);
148# ifdef __MINGW64_VERSION_MAJOR
149 __mingw_fprintf (stderr, "Mingw-w64 runtime failure:\n");
150 __mingw_vfprintf (stderr, msg, argp);
151# else
152 fprintf (stderr, "Mingw runtime failure:\n");
153 vfprintf (stderr, msg, argp);
154#endif
155 va_end (argp);
156 abort ();
157#endif
158}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define msg(x)
Definition: auth_time.c:54
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
CONST VOID * PCVOID
Definition: cfgmgr32.h:44
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
#define abort()
Definition: i386-dis.c:34
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
#define DWORD
Definition: nt_native.h:44
int ssize_t
Definition: rosdhcp.h:48
#define args
Definition: format.c:66
Definition: match.c:390
#define vsnprintf
Definition: tif_win32.c:406
#define STD_ERROR_HANDLE
Definition: winbase.h:269

Referenced by __write_memory(), and do_pseudo_reloc().

◆ __write_memory()

static void __write_memory ( void addr,
const void src,
size_t  len 
)
static

Definition at line 260 of file pseudo-reloc.c.

261{
263 DWORD oldprot;
264 int call_unprotect = 0;
265
266 if (!len)
267 return;
268
269#ifdef __MINGW64_VERSION_MAJOR
270 mark_section_writable ((LPVOID) addr);
271#endif
272
273 if (!VirtualQuery (addr, &b, sizeof(b)))
274 {
275 __report_error (" VirtualQuery failed for %d bytes at address %p",
276 (int) sizeof(b), addr);
277 }
278
279 /* Temporarily allow write access to read-only protected memory. */
280 if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
281 {
282 call_unprotect = 1;
283 VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
284 &oldprot);
285 }
286
287 /* write the data. */
288 memcpy (addr, src, len);
289 /* Restore original protection. */
290 if (call_unprotect && b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
291 VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
292}
GLenum src
Definition: glext.h:6340
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLvoid * addr
Definition: glext.h:9621
#define b
Definition: ke_i.h:79
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
static void ATTRIBUTE_NORETURN __report_error(const char *msg,...)
Definition: pseudo-reloc.c:83
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:135
SIZE_T NTAPI VirtualQuery(IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:211

Referenced by do_pseudo_reloc().

◆ _pei386_runtime_relocator()

void _pei386_runtime_relocator ( void  )

Definition at line 455 of file pseudo-reloc.c.

456{
457 static NO_COPY int was_init = 0;
458#ifdef __MINGW64_VERSION_MAJOR
459 int mSecs;
460#endif /* __MINGW64_VERSION_MAJOR */
461
462 if (was_init)
463 return;
464 ++was_init;
465#ifdef __MINGW64_VERSION_MAJOR
466 mSecs = __mingw_GetSectionCount ();
467 the_secs = (sSecInfo *) alloca (sizeof (sSecInfo) * (size_t) mSecs);
468 maxSections = 0;
469#endif /* __MINGW64_VERSION_MAJOR */
470
473#ifdef __GNUC__
474 &__MINGW_LSYMBOL(_image_base__)
475#else
477#endif
478 );
479#ifdef __MINGW64_VERSION_MAJOR
480 restore_modified_sections ();
481#endif /* __MINGW64_VERSION_MAJOR */
482}
#define __GNUC__
Definition: _icc.h:38
#define __ImageBase
Definition: crt_handler.c:22
__kernel_size_t size_t
Definition: linux.h:237
#define alloca
Definition: malloc.h:357
int __mingw_GetSectionCount(void)
Definition: pesect.c:115
#define NO_COPY
Definition: pseudo-reloc.c:35
char __RUNTIME_PSEUDO_RELOC_LIST_END__
#define __MINGW_LSYMBOL(sym)
Definition: pseudo-reloc.c:45
char __RUNTIME_PSEUDO_RELOC_LIST__
static void do_pseudo_reloc(void *start, void *end, void *base)
Definition: pseudo-reloc.c:298

◆ do_pseudo_reloc()

static void do_pseudo_reloc ( void start,
void end,
void base 
)
static

Definition at line 298 of file pseudo-reloc.c.

299{
300 ptrdiff_t addr_imp, reldata;
301 ptrdiff_t reloc_target = (ptrdiff_t) ((char *)end - (char*)start);
304
305 /* A valid relocation list will contain at least one entry, and
306 * one v1 data structure (the smallest one) requires two DWORDs.
307 * So, if the relocation list is smaller than 8 bytes, bail.
308 */
309 if (reloc_target < 8)
310 return;
311
312 /* Check if this is the old pseudo relocation version. */
313 /* There are two kinds of v1 relocation lists:
314 * 1) With a (v2-style) version header. In this case, the
315 * first entry in the list is a 3-DWORD structure, with
316 * value:
317 * { 0, 0, RP_VERSION_V1 }
318 * In this case, we skip to the next entry in the list,
319 * knowing that all elements after the head item can
320 * be cast to runtime_pseudo_reloc_item_v1.
321 * 2) Without a (v2-style) version header. In this case, the
322 * first element in the list IS an actual v1 relocation
323 * record, which is two DWORDs. Because there will never
324 * be a case where a v1 relocation record has both
325 * addend == 0 and target == 0, this case will not be
326 * confused with the prior one.
327 * All current binutils, when generating a v1 relocation list,
328 * use the second (e.g. original) form -- that is, without the
329 * v2-style version header.
330 */
331 if (reloc_target >= 12
332 && v2_hdr->magic1 == 0 && v2_hdr->magic2 == 0
333 && v2_hdr->version == RP_VERSION_V1)
334 {
335 /* We have a list header item indicating that the rest
336 * of the list contains v1 entries. Move the pointer to
337 * the first true v1 relocation record. By definition,
338 * that v1 element will not have both addend == 0 and
339 * target == 0 (and thus, when interpreted as a
340 * runtime_pseudo_reloc_v2, it will not have both
341 * magic1 == 0 and magic2 == 0).
342 */
343 v2_hdr++;
344 }
345
346 if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
347 {
348 /*************************
349 * Handle v1 relocations *
350 *************************/
352 for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr;
354 o++)
355 {
356 DWORD newval;
357 reloc_target = (ptrdiff_t) base + o->target;
358 newval = (*((DWORD*) reloc_target)) + o->addend;
359 __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
360 }
361 return;
362 }
363
364 /* If we got this far, then we have relocations of version 2 or newer */
365
366 /* Check if this is a known version. */
367 if (v2_hdr->version != RP_VERSION_V2)
368 {
369 __report_error (" Unknown pseudo relocation protocol version %d.\n",
370 (int) v2_hdr->version);
371 return;
372 }
373
374 /*************************
375 * Handle v2 relocations *
376 *************************/
377
378 /* Walk over header. */
379 r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
380
381 for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
382 {
383 /* location where new address will be written */
384 reloc_target = (ptrdiff_t) base + r->target;
385
386 /* get sym pointer. It points either to the iat entry
387 * of the referenced element, or to the stub function.
388 */
389 addr_imp = (ptrdiff_t) base + r->sym;
390 addr_imp = *((ptrdiff_t *) addr_imp);
391
392 /* read existing relocation value from image, casting to the
393 * bitsize indicated by the 8 LSBs of flags. If the value is
394 * negative, manually sign-extend to ptrdiff_t width. Raise an
395 * error if the bitsize indicated by the 8 LSBs of flags is not
396 * supported.
397 */
398 switch ((r->flags & 0xff))
399 {
400 case 8:
401 reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
402 if ((reldata & 0x80) != 0)
403 reldata |= ~((ptrdiff_t) 0xff);
404 break;
405 case 16:
406 reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
407 if ((reldata & 0x8000) != 0)
408 reldata |= ~((ptrdiff_t) 0xffff);
409 break;
410 case 32:
411 reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
412#ifdef _WIN64
413 if ((reldata & 0x80000000) != 0)
414 reldata |= ~((ptrdiff_t) 0xffffffff);
415#endif
416 break;
417#ifdef _WIN64
418 case 64:
419 reldata = (ptrdiff_t) (*((unsigned long long *)reloc_target));
420 break;
421#endif
422 default:
423 reldata=0;
424 __report_error (" Unknown pseudo relocation bit size %d.\n",
425 (int) (r->flags & 0xff));
426 break;
427 }
428
429 /* Adjust the relocation value */
430 reldata -= ((ptrdiff_t) base + r->sym);
431 reldata += addr_imp;
432
433 /* Write the new relocation value back to *reloc_target */
434 switch ((r->flags & 0xff))
435 {
436 case 8:
437 __write_memory ((void *) reloc_target, &reldata, 1);
438 break;
439 case 16:
440 __write_memory ((void *) reloc_target, &reldata, 2);
441 break;
442 case 32:
443 __write_memory ((void *) reloc_target, &reldata, 4);
444 break;
445#ifdef _WIN64
446 case 64:
447 __write_memory ((void *) reloc_target, &reldata, 8);
448 break;
449#endif
450 }
451 }
452}
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
GLuint start
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static void __write_memory(void *addr, const void *src, size_t len)
Definition: pseudo-reloc.c:260
#define RP_VERSION_V1
Definition: pseudo-reloc.c:294
#define RP_VERSION_V2
Definition: pseudo-reloc.c:295

Referenced by _pei386_runtime_relocator().

Variable Documentation

◆ __RUNTIME_PSEUDO_RELOC_LIST__

char __RUNTIME_PSEUDO_RELOC_LIST__
extern

Definition at line 8 of file pseudo-reloc-list.c.

Referenced by _pei386_runtime_relocator().

◆ __RUNTIME_PSEUDO_RELOC_LIST_END__

char __RUNTIME_PSEUDO_RELOC_LIST_END__
extern

This file has no copyright assigned and is placed in the Public Domain. This file is part of the w64 mingw-runtime package. No warranty is given; refer to the file DISCLAIMER.PD within this package.

Definition at line 7 of file pseudo-reloc-list.c.

Referenced by _pei386_runtime_relocator().