ReactOS  0.4.13-dev-551-gf37fb1f
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;
103  va_list args;
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 }
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
#define vsnprintf
Definition: tif_win32.c:406
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define free
Definition: debug_ros.c:5
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
Definition: match.c:390
#define DWORD
Definition: nt_native.h:44
#define va_end(ap)
Definition: acmsvcex.h:90
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
smooth NULL
Definition: ftsmooth.c:416
char * va_list
Definition: acmsvcex.h:78
#define STD_ERROR_HANDLE
Definition: winbase.h:266
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
int ssize_t
Definition: rosdhcp.h:48
CONST VOID * PCVOID
Definition: cfgmgr32.h:44
#define abort()
Definition: i386-dis.c:35
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define msg(x)
Definition: auth_time.c:54
FILE * stderr
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
#define args
Definition: format.c:66

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 }
#define b
Definition: ke_i.h:79
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
unsigned long DWORD
Definition: ntddk_ex.h:95
SIZE_T NTAPI VirtualQuery(IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:220
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:144
GLenum const GLvoid * addr
Definition: glext.h:9621
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLenum src
Definition: glext.h:6340
static void ATTRIBUTE_NORETURN __report_error(const char *msg,...)
Definition: pseudo-reloc.c:83
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define PAGE_READWRITE
Definition: nt_native.h:1304

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
476  &__ImageBase
477 #endif
478  );
479 #ifdef __MINGW64_VERSION_MAJOR
480  restore_modified_sections ();
481 #endif /* __MINGW64_VERSION_MAJOR */
482 }
int __mingw_GetSectionCount(void)
Definition: pesect.c:115
#define __GNUC__
Definition: _icc.h:38
static void do_pseudo_reloc(void *start, void *end, void *base)
Definition: pseudo-reloc.c:298
#define alloca
Definition: malloc.h:361
__kernel_size_t size_t
Definition: linux.h:237
#define NO_COPY
Definition: pseudo-reloc.c:35
char __RUNTIME_PSEUDO_RELOC_LIST__
#define __MINGW_LSYMBOL(sym)
Definition: pseudo-reloc.c:45
#define __ImageBase
Definition: crt_handler.c:22
char __RUNTIME_PSEUDO_RELOC_LIST_END__

◆ 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 }
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint GLuint end
Definition: gl.h:1545
#define RP_VERSION_V2
Definition: pseudo-reloc.c:295
#define RP_VERSION_V1
Definition: pseudo-reloc.c:294
unsigned long DWORD
Definition: ntddk_ex.h:95
static void __write_memory(void *addr, const void *src, size_t len)
Definition: pseudo-reloc.c:260
GLuint start
Definition: gl.h:1545
static void ATTRIBUTE_NORETURN __report_error(const char *msg,...)
Definition: pseudo-reloc.c:83
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247

Referenced by _pei386_runtime_relocator().

Variable Documentation

◆ __RUNTIME_PSEUDO_RELOC_LIST__

char __RUNTIME_PSEUDO_RELOC_LIST__

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__

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().