summaryrefslogtreecommitdiffstats
path: root/trunk/src/arch-arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/arch-arm.c')
-rw-r--r--trunk/src/arch-arm.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/trunk/src/arch-arm.c b/trunk/src/arch-arm.c
index 0dddaac..ba53929 100644
--- a/trunk/src/arch-arm.c
+++ b/trunk/src/arch-arm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2004, 2009 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
static int
arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
- GElf_Addr adjust)
+ GElf_Addr adjust)
{
if (dyn->d_tag == DT_PLTGOT)
{
@@ -73,7 +73,7 @@ arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
static int
arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
- GElf_Addr adjust)
+ GElf_Addr adjust)
{
Elf32_Addr data;
switch (GELF_R_TYPE (rel->r_info))
@@ -90,7 +90,7 @@ arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
static int
arm_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
- GElf_Addr adjust)
+ GElf_Addr adjust)
{
Elf32_Addr data;
@@ -186,7 +186,7 @@ arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
static int
arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
- GElf_Addr relaaddr)
+ GElf_Addr relaaddr)
{
DSO *dso;
GElf_Addr value;
@@ -254,7 +254,7 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
static int
arm_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
- char *buf)
+ char *buf, GElf_Addr dest_addr)
{
switch (GELF_R_TYPE (rela->r_info))
{
@@ -354,7 +354,7 @@ arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
static int
arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
- GElf_Addr reladdr)
+ GElf_Addr reladdr)
{
GElf_Addr value;
struct prelink_conflict *conflict;
@@ -362,7 +362,8 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
GElf_Rela *ret;
if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE
- || GELF_R_TYPE (rel->r_info) == R_ARM_NONE)
+ || GELF_R_TYPE (rel->r_info) == R_ARM_NONE
+ || info->dso == dso)
/* Fast path: nothing to do. */
return 0;
conflict = prelink_conflict (info, GELF_R_SYM (rel->r_info),
@@ -384,6 +385,12 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
}
value = 0;
}
+ else if (conflict->ifunc)
+ {
+ error (0, 0, "%s: STT_GNU_IFUNC not handled on ARM yet",
+ dso->filename);
+ return 1;
+ }
else
{
/* DTPOFF32 wants to see only real conflicts, not lookups
@@ -452,7 +459,7 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
static int
arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
- GElf_Rela *rela, GElf_Addr relaaddr)
+ GElf_Rela *rela, GElf_Addr relaaddr)
{
GElf_Addr value;
struct prelink_conflict *conflict;
@@ -461,7 +468,8 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
Elf32_Sword val;
if (GELF_R_TYPE (rela->r_info) == R_ARM_RELATIVE
- || GELF_R_TYPE (rela->r_info) == R_ARM_NONE)
+ || GELF_R_TYPE (rela->r_info) == R_ARM_NONE
+ || info->dso == dso)
/* Fast path: nothing to do. */
return 0;
conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
@@ -484,6 +492,12 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
}
value = 0;
}
+ else if (conflict->ifunc)
+ {
+ error (0, 0, "%s: STT_GNU_IFUNC not handled on ARM yet",
+ dso->filename);
+ return 1;
+ }
else
{
/* DTPOFF32 wants to see only real conflicts, not lookups
@@ -823,6 +837,7 @@ PL_ARCH(arm) = {
.R_JMP_SLOT = R_ARM_JUMP_SLOT,
.R_COPY = R_ARM_COPY,
.R_RELATIVE = R_ARM_RELATIVE,
+ .rtype_class_valid = RTYPE_CLASS_VALID,
.dynamic_linker = "/lib/ld-linux.so.2",
.dynamic_linker_alt = "/lib/ld-linux.so.3",
.adjust_dyn = arm_adjust_dyn,