diff options
Diffstat (limited to 'trunk/src/arch-arm.c')
-rw-r--r-- | trunk/src/arch-arm.c | 35 |
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, |