diff options
-rw-r--r-- | ChangeLog.cross | 3 | ||||
-rw-r--r-- | src/arch-arm.c | 120 |
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; |