forked from KolibriOS/kolibrios
newlib: fix pseudo relocations
git-svn-id: svn://kolibrios.org@1908 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
f987f52aaa
commit
b98d495334
@ -17,7 +17,7 @@ AMZ_SRCS:= \
|
|||||||
crt/crt_amz.S \
|
crt/crt_amz.S \
|
||||||
crt/chkstk.S \
|
crt/chkstk.S \
|
||||||
crt/exit.S \
|
crt/exit.S \
|
||||||
crt/pseudo-reloc.S \
|
crt/pseudo-reloc.c \
|
||||||
crt/setjmp.S
|
crt/setjmp.S
|
||||||
|
|
||||||
STATIC_SRCS:= \
|
STATIC_SRCS:= \
|
||||||
@ -267,7 +267,7 @@ MATH_SRCS = acosf.c acosh.c acoshf.c acoshl.c acosl.c asinf.c asinh.c asinhf.c
|
|||||||
sinf.S sinl.S tan.S tanf.S tanl.S s_expm1.S
|
sinf.S sinl.S tan.S tanf.S tanl.S s_expm1.S
|
||||||
|
|
||||||
|
|
||||||
AMZ_OBJS = $(patsubst %.S, %.o, $(AMZ_SRCS))
|
AMZ_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(AMZ_SRCS)))
|
||||||
|
|
||||||
STATIC_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(STATIC_SRCS)))
|
STATIC_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(STATIC_SRCS)))
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
|
.def ___chkstk; .scl 2; .type 32; .endef
|
||||||
|
.def __alloca; .scl 2; .type 32; .endef
|
||||||
___chkstk:
|
___chkstk:
|
||||||
__alloca:
|
__alloca:
|
||||||
pushl %ecx /* save temp */
|
pushl %ecx /* save temp */
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
__start:
|
__start:
|
||||||
|
call __pei386_runtime_relocator
|
||||||
jmp _main
|
jmp _main
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
|
|
||||||
.global __pei386_runtime_relocator
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
__pei386_runtime_relocator:
|
|
||||||
|
|
||||||
# movl $___RUNTIME_PSEUDO_RELOC_LIST__, %ecx
|
|
||||||
|
|
||||||
# pushl %ebp
|
|
||||||
# cmpl $___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx
|
|
||||||
# movl %esp, %ebp
|
|
||||||
# jnb .L2
|
|
||||||
|
|
||||||
#.L1:
|
|
||||||
# movl (%ecx), %eax
|
|
||||||
# movl 4(%ecx), %edx
|
|
||||||
# addl $8, %ecx
|
|
||||||
# addl %eax, __image_base__(%edx)
|
|
||||||
# cmpl $___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx
|
|
||||||
# jb .L1
|
|
||||||
|
|
||||||
#.L2:
|
|
||||||
# popl %ebp
|
|
||||||
ret
|
|
||||||
|
|
214
programs/develop/libraries/newlib/crt/pseudo-reloc.c
Normal file
214
programs/develop/libraries/newlib/crt/pseudo-reloc.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* pseudo-reloc.c
|
||||||
|
|
||||||
|
Contributed by Egor Duda <deo@logos-m.ru>
|
||||||
|
Modified by addition of runtime_pseudo_reloc version 2
|
||||||
|
by Kai Tietz <kai.tietz@onevision.com>
|
||||||
|
|
||||||
|
THIS SOFTWARE IS NOT COPYRIGHTED
|
||||||
|
|
||||||
|
This source code is offered for use in the public domain. You may
|
||||||
|
use, modify or distribute it freely.
|
||||||
|
|
||||||
|
This code is distributed in the hope that it will be useful but
|
||||||
|
WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||||
|
DISCLAMED. This includes but is not limited to warrenties of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
extern char __RUNTIME_PSEUDO_RELOC_LIST__;
|
||||||
|
extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
|
||||||
|
extern char _image_base__;
|
||||||
|
|
||||||
|
void _pei386_runtime_relocator (void);
|
||||||
|
|
||||||
|
/* v1 relocation is basically:
|
||||||
|
* *(base + .target) += .addend
|
||||||
|
* where (base + .target) is always assumed to point
|
||||||
|
* to a DWORD (4 bytes).
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t addend;
|
||||||
|
uint32_t target;
|
||||||
|
} runtime_pseudo_reloc_item_v1;
|
||||||
|
|
||||||
|
/* v2 relocation is more complex. In effect, it is
|
||||||
|
* *(base + .target) += *(base + .sym) - (base + .sym)
|
||||||
|
* with care taken in both reading, sign extension, and writing
|
||||||
|
* because .flags may indicate that (base + .target) may point
|
||||||
|
* to a BYTE, WORD, DWORD, or QWORD (w64).
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sym;
|
||||||
|
uint32_t target;
|
||||||
|
uint32_t flags;
|
||||||
|
} runtime_pseudo_reloc_item_v2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t magic1;
|
||||||
|
uint32_t magic2;
|
||||||
|
uint32_t version;
|
||||||
|
} runtime_pseudo_reloc_v2;
|
||||||
|
|
||||||
|
#define RP_VERSION_V1 0
|
||||||
|
#define RP_VERSION_V2 1
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_pseudo_reloc (void * start, void * end, void * base)
|
||||||
|
{
|
||||||
|
ptrdiff_t addr_imp, reldata;
|
||||||
|
ptrdiff_t reloc_target = (ptrdiff_t) ((char *)end - (char*)start);
|
||||||
|
runtime_pseudo_reloc_v2 *v2_hdr = (runtime_pseudo_reloc_v2 *) start;
|
||||||
|
runtime_pseudo_reloc_item_v2 *r;
|
||||||
|
|
||||||
|
/* A valid relocation list will contain at least one entry, and
|
||||||
|
* one v1 data structure (the smallest one) requires two DWORDs.
|
||||||
|
* So, if the relocation list is smaller than 8 bytes, bail.
|
||||||
|
*/
|
||||||
|
if (reloc_target < 8)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Check if this is the old pseudo relocation version. */
|
||||||
|
/* There are two kinds of v1 relocation lists:
|
||||||
|
* 1) With a (v2-style) version header. In this case, the
|
||||||
|
* first entry in the list is a 3-DWORD structure, with
|
||||||
|
* value:
|
||||||
|
* { 0, 0, RP_VERSION_V1 }
|
||||||
|
* In this case, we skip to the next entry in the list,
|
||||||
|
* knowing that all elements after the head item can
|
||||||
|
* be cast to runtime_pseudo_reloc_item_v1.
|
||||||
|
* 2) Without a (v2-style) version header. In this case, the
|
||||||
|
* first element in the list IS an actual v1 relocation
|
||||||
|
* record, which is two DWORDs. Because there will never
|
||||||
|
* be a case where a v1 relocation record has both
|
||||||
|
* addend == 0 and target == 0, this case will not be
|
||||||
|
* confused with the prior one.
|
||||||
|
* All current binutils, when generating a v1 relocation list,
|
||||||
|
* use the second (e.g. original) form -- that is, without the
|
||||||
|
* v2-style version header.
|
||||||
|
*/
|
||||||
|
if (reloc_target >= 12
|
||||||
|
&& v2_hdr->magic1 == 0 && v2_hdr->magic2 == 0
|
||||||
|
&& v2_hdr->version == RP_VERSION_V1)
|
||||||
|
{
|
||||||
|
/* We have a list header item indicating that the rest
|
||||||
|
* of the list contains v1 entries. Move the pointer to
|
||||||
|
* the first true v1 relocation record. By definition,
|
||||||
|
* that v1 element will not have both addend == 0 and
|
||||||
|
* target == 0 (and thus, when interpreted as a
|
||||||
|
* runtime_pseudo_reloc_v2, it will not have both
|
||||||
|
* magic1 == 0 and magic2 == 0).
|
||||||
|
*/
|
||||||
|
v2_hdr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v2_hdr->magic1 != 0 || v2_hdr->magic2 != 0)
|
||||||
|
{
|
||||||
|
/*************************
|
||||||
|
* Handle v1 relocations *
|
||||||
|
*************************/
|
||||||
|
runtime_pseudo_reloc_item_v1 * o;
|
||||||
|
for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr;
|
||||||
|
o < (runtime_pseudo_reloc_item_v1 *)end;
|
||||||
|
o++)
|
||||||
|
{
|
||||||
|
uint32_t newval;
|
||||||
|
reloc_target = (ptrdiff_t) base + o->target;
|
||||||
|
newval = (*((uint32_t*) reloc_target)) + o->addend;
|
||||||
|
*(uint32_t*)reloc_target = newval;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we got this far, then we have relocations of version 2 or newer */
|
||||||
|
|
||||||
|
/* Check if this is a known version. */
|
||||||
|
if (v2_hdr->version != RP_VERSION_V2)
|
||||||
|
{
|
||||||
|
printf(" Unknown pseudo relocation protocol version %d.\n",
|
||||||
|
(int) v2_hdr->version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
* Handle v2 relocations *
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
/* Walk over header. */
|
||||||
|
r = (runtime_pseudo_reloc_item_v2 *) &v2_hdr[1];
|
||||||
|
|
||||||
|
for (; r < (runtime_pseudo_reloc_item_v2 *) end; r++)
|
||||||
|
{
|
||||||
|
/* location where new address will be written */
|
||||||
|
reloc_target = (ptrdiff_t) base + r->target;
|
||||||
|
|
||||||
|
/* get sym pointer. It points either to the iat entry
|
||||||
|
* of the referenced element, or to the stub function.
|
||||||
|
*/
|
||||||
|
addr_imp = (ptrdiff_t) base + r->sym;
|
||||||
|
addr_imp = *((ptrdiff_t *) addr_imp);
|
||||||
|
|
||||||
|
/* read existing relocation value from image, casting to the
|
||||||
|
* bitsize indicated by the 8 LSBs of flags. If the value is
|
||||||
|
* negative, manually sign-extend to ptrdiff_t width. Raise an
|
||||||
|
* error if the bitsize indicated by the 8 LSBs of flags is not
|
||||||
|
* supported.
|
||||||
|
*/
|
||||||
|
switch ((r->flags & 0xff))
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
reldata = (ptrdiff_t) (*((unsigned char *)reloc_target));
|
||||||
|
if ((reldata & 0x80) != 0)
|
||||||
|
reldata |= ~((ptrdiff_t) 0xff);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
reldata = (ptrdiff_t) (*((unsigned short *)reloc_target));
|
||||||
|
if ((reldata & 0x8000) != 0)
|
||||||
|
reldata |= ~((ptrdiff_t) 0xffff);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
reldata = (ptrdiff_t) (*((unsigned int *)reloc_target));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reldata=0;
|
||||||
|
printf(" Unknown pseudo relocation bit size %d.\n",
|
||||||
|
(int) (r->flags & 0xff));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the relocation value */
|
||||||
|
reldata -= ((ptrdiff_t) base + r->sym);
|
||||||
|
reldata += addr_imp;
|
||||||
|
|
||||||
|
/* Write the new relocation value back to *reloc_target */
|
||||||
|
switch ((r->flags & 0xff))
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
*(uint8_t*)reloc_target = (uint8_t)reldata;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
*(uint16_t*)reloc_target = (uint16_t)reldata;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
*(uint32_t*)reloc_target = (uint32_t)reldata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_pei386_runtime_relocator (void)
|
||||||
|
{
|
||||||
|
static int was_init = 0;
|
||||||
|
if (was_init)
|
||||||
|
return;
|
||||||
|
++was_init;
|
||||||
|
do_pseudo_reloc (&__RUNTIME_PSEUDO_RELOC_LIST__,
|
||||||
|
&__RUNTIME_PSEUDO_RELOC_LIST_END__,
|
||||||
|
&_image_base__);
|
||||||
|
}
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
|
.def _create_thread; .scl 2; .type 32; .endef
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
_create_thread:
|
_create_thread:
|
||||||
#.thr_proc equ esp+8
|
#.thr_proc equ esp+8
|
||||||
|
@ -10,7 +10,6 @@ SECTIONS
|
|||||||
|
|
||||||
.text __image_base__ + . :
|
.text __image_base__ + . :
|
||||||
{
|
{
|
||||||
|
|
||||||
*(.init)
|
*(.init)
|
||||||
*(.text)
|
*(.text)
|
||||||
*(SORT(.text$*))
|
*(SORT(.text$*))
|
||||||
@ -26,10 +25,7 @@ SECTIONS
|
|||||||
*(.gcc_exc)
|
*(.gcc_exc)
|
||||||
PROVIDE (etext = .);
|
PROVIDE (etext = .);
|
||||||
*(.gcc_except_table)
|
*(.gcc_except_table)
|
||||||
}
|
|
||||||
|
|
||||||
.rdata ALIGN(__section_alignment__):
|
|
||||||
{
|
|
||||||
*(.rdata)
|
*(.rdata)
|
||||||
*(SORT(.rdata$*))
|
*(SORT(.rdata$*))
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
||||||
@ -37,7 +33,26 @@ SECTIONS
|
|||||||
*(.rdata_runtime_pseudo_reloc)
|
*(.rdata_runtime_pseudo_reloc)
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||||
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||||
}
|
}
|
||||||
|
.data ALIGN(__section_alignment__):
|
||||||
|
{
|
||||||
|
PROVIDE ( __data_start__ = .) ;
|
||||||
|
*(.data)
|
||||||
|
*(.data2)
|
||||||
|
*(SORT(.data$*))
|
||||||
|
*(.jcr)
|
||||||
|
__CRT_MT = .;
|
||||||
|
LONG(0);
|
||||||
|
PROVIDE ( __data_end__ = .) ;
|
||||||
|
*(.data_cygwin_nocopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
.eh_frame ALIGN(__section_alignment__):
|
||||||
|
{
|
||||||
|
*(.eh_frame)
|
||||||
|
___iend = . ;
|
||||||
|
}
|
||||||
|
|
||||||
.CRT ALIGN(__section_alignment__):
|
.CRT ALIGN(__section_alignment__):
|
||||||
{
|
{
|
||||||
___crt_xc_start__ = . ;
|
___crt_xc_start__ = . ;
|
||||||
@ -57,24 +72,6 @@ SECTIONS
|
|||||||
___crt_xt_end__ = . ;
|
___crt_xt_end__ = . ;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data ALIGN(__section_alignment__):
|
|
||||||
{
|
|
||||||
PROVIDE ( __data_start__ = .) ;
|
|
||||||
*(.data)
|
|
||||||
*(.data2)
|
|
||||||
*(SORT(.data$*))
|
|
||||||
*(.jcr)
|
|
||||||
__CRT_MT = .;
|
|
||||||
LONG(0);
|
|
||||||
PROVIDE ( __data_end__ = .) ;
|
|
||||||
*(.data_cygwin_nocopy)
|
|
||||||
}
|
|
||||||
|
|
||||||
.eh_frame ALIGN(__section_alignment__):
|
|
||||||
{
|
|
||||||
*(.eh_frame)
|
|
||||||
___iend = . ;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bss ALIGN(__section_alignment__):
|
.bss ALIGN(__section_alignment__):
|
||||||
{
|
{
|
||||||
|
@ -51,3 +51,11 @@ _DEFUN (time, (t),
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_DEFUN (gettimeofday, (ptimeval, ptimezone),
|
||||||
|
struct timeval *ptimeval _AND
|
||||||
|
void *ptimezone)
|
||||||
|
{
|
||||||
|
return _gettimeofday_r (_REENT, ptimeval, ptimezone);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user