aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2006-08-18 19:00:35 -0500
committerMark Hatle <mark.hatle@windriver.com>2010-07-22 16:16:35 -0500
commitcabd0d8040fa221214257a0a181ea0d1b5490fbb (patch)
treef137d6cc34016d1a08587343a5fae3b1f71c8941
parentef17341a76ec060226cbaed75d154143592a46cf (diff)
downloadprelink-cross-cabd0d8040fa221214257a0a181ea0d1b5490fbb.tar.gz
prelink-cross-cabd0d8040fa221214257a0a181ea0d1b5490fbb.tar.bz2
prelink-cross-cabd0d8040fa221214257a0a181ea0d1b5490fbb.zip
Import from: prelink-arch-arm-be.patchcross_prelink_20060712
Source: Wind River Systems Support big endian ARM prelinking. The previous code only supported little endian. We use the arch-sh code as an example of how to support an architecture that supports both big and little endian.
-rw-r--r--ChangeLog.cross3
-rw-r--r--src/arch-arm.c120
2 files changed, 81 insertions, 42 deletions
diff --git a/ChangeLog.cross b/ChangeLog.cross
index d2354ce..61b4d24 100644
--- a/ChangeLog.cross
+++ b/ChangeLog.cross
@@ -1,11 +1,14 @@
2006-08-18 Mark Hatle <mark.hatle@windriver.com>
* arch-arm.c: remove prelink_conflict_rela
+ * arch-arm.c: Add big-endian arm support, based on arch-sh.c
2006-08-17 Mark Hatle <mark.hatle@windriver.com>
* data.c, dso.c, prelink.h: when using elfutils/libelf, we need
to byte swap only if the type is ELF_T_BYTE.
+ * dso-readonly.c: add get_data prototype change for byteswapping
+ * ld-libs.c: add get_data prototype change for byteswapping
2006-08-10 Mark Hatle <mark.hatle@windriver.com>
diff --git a/src/arch-arm.c b/src/arch-arm.c
index dabea03..607d428 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -34,6 +34,42 @@
#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
#endif
+static inline uint32_t
+read_une32 (DSO *dso, GElf_Addr addr)
+{
+ if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ return read_ule32 (dso, addr);
+ else
+ return read_ube32 (dso, addr);
+}
+
+static inline void
+write_ne32 (DSO *dso, GElf_Addr addr, uint32_t value)
+{
+ if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ write_le32 (dso, addr, value);
+ else
+ write_be32 (dso, addr, value);
+}
+
+static inline void
+buf_write_ne32 (DSO *dso, unsigned char *buf, uint32_t value)
+{
+ if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ buf_write_le32 (buf, value);
+ else
+ buf_write_be32 (buf, value);
+}
+
+static inline uint32_t
+buf_read_une32 (DSO *dso, unsigned char *data)
+{
+ if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ return buf_read_ule32 (data);
+ else
+ return buf_read_ube32 (data);
+}
+
static int
arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
GElf_Addr adjust)
@@ -46,12 +82,12 @@ arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
if (sec == -1)
return 0;
- data = read_ule32 (dso, dyn->d_un.d_ptr);
+ data = read_une32 (dso, dyn->d_un.d_ptr);
/* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */
if (data == dso->shdr[n].sh_addr && data >= start)
- write_le32 (dso, dyn->d_un.d_ptr, data + adjust);
+ write_ne32 (dso, dyn->d_un.d_ptr, data + adjust);
- data = read_ule32 (dso, dyn->d_un.d_ptr + 4);
+ data = read_une32 (dso, dyn->d_un.d_ptr + 4);
/* If .got.plt[1] points to .plt, it needs to be adjusted. */
if (data && data >= start)
{
@@ -63,7 +99,7 @@ arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
&& strcmp (strptr (dso, dso->ehdr.e_shstrndx,
dso->shdr[i].sh_name), ".plt") == 0)
{
- write_le32 (dso, dyn->d_un.d_ptr + 4, data + adjust);
+ write_ne32 (dso, dyn->d_un.d_ptr + 4, data + adjust);
break;
}
}
@@ -80,9 +116,9 @@ arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
{
case R_ARM_RELATIVE:
case R_ARM_JUMP_SLOT:
- data = read_ule32 (dso, rel->r_offset);
+ data = read_une32 (dso, rel->r_offset);
if (data >= start)
- write_le32 (dso, rel->r_offset, data + adjust);
+ write_ne32 (dso, rel->r_offset, data + adjust);
break;
}
return 0;
@@ -102,13 +138,13 @@ arm_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
rela->r_addend += (Elf32_Sword) adjust;
/* Write it to the memory location as well.
Not necessary, but we can do it. */
- write_le32 (dso, rela->r_offset, rela->r_addend);
+ write_ne32 (dso, rela->r_offset, rela->r_addend);
}
break;
case R_ARM_JUMP_SLOT:
- data = read_ule32 (dso, rela->r_offset);
+ data = read_une32 (dso, rela->r_offset);
if (data >= start)
- write_le32 (dso, rela->r_offset, data + adjust);
+ write_ne32 (dso, rela->r_offset, data + adjust);
break;
break;
}
@@ -132,18 +168,18 @@ arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
{
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
- write_le32 (dso, rel->r_offset, value);
+ write_ne32 (dso, rel->r_offset, value);
break;
case R_ARM_ABS32:
{
- if (read_ule32 (dso, rel->r_offset))
+ if (read_une32 (dso, rel->r_offset))
{
error (0, 0, "%s: R_ARM_ABS32 relocs with non-zero addend should not be present in prelinked REL sections",
dso->filename);
return 1;
}
rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_GLOB_DAT);
- write_le32 (dso, rel->r_offset, value);
+ write_ne32 (dso, rel->r_offset, value);
/* Tell prelink_rel routine *rel has changed. */
return 2;
}
@@ -158,7 +194,7 @@ arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename);
return 1;
case R_ARM_TLS_DTPOFF32:
- write_le32 (dso, rel->r_offset, value);
+ write_ne32 (dso, rel->r_offset, value);
break;
/* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries
unless prelink sets the rules. */
@@ -203,10 +239,10 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
{
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
- write_le32 (dso, rela->r_offset, value + rela->r_addend);
+ write_ne32 (dso, rela->r_offset, value + rela->r_addend);
break;
case R_ARM_ABS32:
- write_le32 (dso, rela->r_offset, value + rela->r_addend);
+ write_ne32 (dso, rela->r_offset, value + rela->r_addend);
break;
case R_ARM_PC24:
val = value + rela->r_addend - rela->r_offset;
@@ -217,8 +253,8 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
return 1;
}
val &= 0xffffff;
- write_le32 (dso, rela->r_offset,
- (read_ule32 (dso, rela->r_offset) & 0xff000000) | val);
+ write_ne32 (dso, rela->r_offset,
+ (read_une32 (dso, rela->r_offset) & 0xff000000) | val);
break;
case R_ARM_COPY:
if (dso->ehdr.e_type == ET_EXEC)
@@ -227,7 +263,7 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename);
return 1;
case R_ARM_TLS_DTPOFF32:
- write_le32 (dso, rela->r_offset, value + rela->r_addend);
+ write_ne32 (dso, rela->r_offset, value + rela->r_addend);
break;
/* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries
unless prelink sets the rules. */
@@ -241,7 +277,7 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
break;
case R_ARM_TLS_TPOFF32:
if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
- write_le32 (dso, rela->r_offset,
+ write_ne32 (dso, rela->r_offset,
value + rela->r_addend + info->resolvetls->offset);
break;
default:
@@ -261,7 +297,7 @@ arm_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
case R_ARM_ABS32:
- buf_write_le32 (buf, rela->r_addend);
+ buf_write_ne32 (info->dso, buf, rela->r_addend);
break;
default:
abort ();
@@ -283,14 +319,14 @@ arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
break;
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
- buf_write_le32 (buf, value);
+ buf_write_ne32 (info->dso, buf, value);
break;
case R_ARM_ABS32:
- buf_write_le32 (buf, value + read_ule32 (info->dso, rel->r_offset));
+ buf_write_ne32 (info->dso, buf, value + read_une32 (info->dso, rel->r_offset));
break;
case R_ARM_PC24:
val = value + rel->r_offset;
- value = read_ule32 (info->dso, rel->r_offset) << 8;
+ value = read_une32 (info->dso, rel->r_offset) << 8;
value = ((Elf32_Sword) value) >> 6;
val += value;
val >>= 2;
@@ -300,7 +336,7 @@ arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
return 1;
}
val &= 0xffffff;
- buf_write_le32 (buf, (buf_read_ule32 (buf) & 0xff000000) | val);
+ buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val);
break;
case R_ARM_COPY:
abort ();
@@ -328,7 +364,7 @@ arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
case R_ARM_GLOB_DAT:
case R_ARM_JUMP_SLOT:
case R_ARM_ABS32:
- buf_write_le32 (buf, value + rela->r_addend);
+ buf_write_ne32 (info->dso, buf, value + rela->r_addend);
break;
case R_ARM_PC24:
val = value + rela->r_addend - rela->r_offset;
@@ -339,7 +375,7 @@ arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
return 1;
}
val &= 0xffffff;
- buf_write_le32 (buf, (buf_read_ule32 (buf) & 0xff000000) | val);
+ buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val);
break;
case R_ARM_COPY:
abort ();
@@ -437,7 +473,7 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
ret->r_addend = value;
break;
case R_ARM_TLS_TPOFF32:
- ret->r_addend = (value + read_ule32 (dso, rel->r_offset)
+ ret->r_addend = (value + read_une32 (dso, rel->r_offset)
+ tls->offset);
break;
}
@@ -516,7 +552,7 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename);
return 1;
}
- value = read_ule32 (dso, rela->r_offset) & 0xff000000;
+ value = read_une32 (dso, rela->r_offset) & 0xff000000;
ret->r_addend = (Elf32_Sword) (value | (val & 0xffffff));
ret->r_info = GELF_R_INFO (0, R_ARM_ABS32);
break;
@@ -570,10 +606,10 @@ arm_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
case R_ARM_RELATIVE:
case R_ARM_ABS32:
case R_ARM_TLS_TPOFF32:
- rela->r_addend = (Elf32_Sword) read_ule32 (dso, rel->r_offset);
+ rela->r_addend = (Elf32_Sword) read_une32 (dso, rel->r_offset);
break;
case R_ARM_PC24:
- rela->r_addend = read_ule32 (dso, rel->r_offset) << 8;
+ rela->r_addend = read_une32 (dso, rel->r_offset) << 8;
rela->r_addend = ((Elf32_Sword) rela->r_addend) >> 6;
break;
case R_ARM_COPY:
@@ -600,17 +636,17 @@ arm_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel)
case R_ARM_RELATIVE:
case R_ARM_ABS32:
case R_ARM_TLS_TPOFF32:
- write_le32 (dso, rela->r_offset, rela->r_addend);
+ write_ne32 (dso, rela->r_offset, rela->r_addend);
break;
case R_ARM_PC24:
- write_le32 (dso, rela->r_offset,
- (read_ule32 (dso, rela->r_offset) & 0xff000000)
+ write_ne32 (dso, rela->r_offset,
+ (read_une32 (dso, rela->r_offset) & 0xff000000)
| ((rela->r_addend >> 2) & 0xffffff));
break;
case R_ARM_GLOB_DAT:
case R_ARM_TLS_DTPMOD32:
case R_ARM_TLS_DTPOFF32:
- write_le32 (dso, rela->r_offset, 0);
+ write_ne32 (dso, rela->r_offset, 0);
break;
}
return 0;
@@ -636,7 +672,7 @@ arm_need_rel_to_rela (DSO *dso, int first, int last)
switch (ELF32_R_TYPE (rel->r_info))
{
case R_ARM_ABS32:
- val = read_ule32 (dso, rel->r_offset);
+ val = read_une32 (dso, rel->r_offset);
/* R_ARM_ABS32 with addend 0 can be converted
to R_ARM_GLOB_DAT and we don't have to convert
to RELA because of that. */
@@ -684,7 +720,7 @@ arm_arch_prelink (DSO *dso)
if (i == dso->ehdr.e_shnum)
return 0;
data = dso->shdr[i].sh_addr;
- write_le32 (dso, dso->info[DT_PLTGOT] + 4, data);
+ write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data);
}
return 0;
@@ -713,9 +749,9 @@ arm_arch_undo_prelink (DSO *dso)
if (i == dso->ehdr.e_shnum)
return 0;
- data = read_ule32 (dso, dso->info[DT_PLTGOT] + 4);
+ data = read_une32 (dso, dso->info[DT_PLTGOT] + 4);
if (data == dso->shdr[i].sh_addr)
- write_le32 (dso, dso->info[DT_PLTGOT] + 4, 0);
+ write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0);
}
return 0;
@@ -743,17 +779,17 @@ arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr)
}
else
{
- Elf32_Addr data = read_ule32 (dso, dso->shdr[sec].sh_addr + 4);
+ Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4);
assert (rel->r_offset >= dso->shdr[sec].sh_addr + 12);
assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0);
- write_le32 (dso, rel->r_offset, data);
+ write_ne32 (dso, rel->r_offset, data);
}
break;
case R_ARM_GLOB_DAT:
sec = addr_to_sec (dso, rel->r_offset);
- write_le32 (dso, rel->r_offset, 0);
+ write_ne32 (dso, rel->r_offset, 0);
if (sec != -1)
{
if (strcmp (strptr (dso, dso->ehdr.e_shstrndx,
@@ -779,7 +815,7 @@ arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr)
return 1;
case R_ARM_TLS_DTPMOD32:
case R_ARM_TLS_DTPOFF32:
- write_le32 (dso, rel->r_offset, 0);
+ write_ne32 (dso, rel->r_offset, 0);
break;
case R_ARM_TLS_TPOFF32:
break;