diff options
-rw-r--r-- | trunk/ChangeLog | 20 | ||||
-rw-r--r-- | trunk/src/arch-x86_64.c | 104 |
2 files changed, 58 insertions, 66 deletions
diff --git a/trunk/ChangeLog b/trunk/ChangeLog index 2ab86ce..a4e09da 100644 --- a/trunk/ChangeLog +++ b/trunk/ChangeLog @@ -1,3 +1,23 @@ +2011-12-21 Mark Hatle <mark@hatle.net> + * src/arch-x86_64.c: Add support for x32 ABI + * Following code is based on work originally by + Code Sourcery, LLC. (Now part of Mentor Graphics) + * prelink.h: Change definition of PL_ARCH + * src/arch-alpha.c: Rename PL_ARCH to PL_ARCH(alpha) + * src/arch-arm.c: Likewise + * src/arch-cris.c: Likewise + * src/arch-i386.c: Likewise + * src/arch-ia64.c: Likewise + * src/arch-mips.c: Likewise + * src/arch-ppc.c: Likewise + * src/arch-ppc64.c: Likewise + * src/arch-s390.c: Likewise + * src/arch-s390x.c: Likewise + * src/arch-sh.c: Likewise + * src/arch-sparc.c: Likewise + * src/arch-sparc64.c: Likewise + * src/arch-x86_64.c: Likewise + 2011-10-12 Jakub Jelinek <jakub@redhat.com> * src/main.c (layout_page_size): New variable. diff --git a/trunk/src/arch-x86_64.c b/trunk/src/arch-x86_64.c index 67c9f8c..4fb3efb 100644 --- a/trunk/src/arch-x86_64.c +++ b/trunk/src/arch-x86_64.c @@ -1,5 +1,7 @@ /* Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. + Copyright (C) 2011 Wind River Systems, Inc. + x32 support by Mark Hatle <mark.hatle@windriver.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +30,22 @@ #include "prelink.h" +/* The x32 ABI: https://sites.google.com/site/x32abi/documents/abi.pdf + * documents a "class" value for specific reads and writes. All this + * indicates is that we should be using the ELFCLASS to determine if + * this should be a 32/64 bit read/write. (See table 4.9) + * + * We emulate this behavior below... + */ +#define read_uleclass(DSO, ADDR) \ +( gelf_getclass(DSO->elf) == ELFCLASS32 ? read_ule32(DSO, ADDR) : read_ule64(DSO, ADDR) ) + +#define write_leclass(DSO, ADDR, VAL) \ +( gelf_getclass(DSO->elf) == ELFCLASS32 ? write_le32(DSO, ADDR, VAL) : write_le64(DSO, ADDR, VAL) ) + +#define buf_write_leclass(DSO, BUF, VAL) \ +( gelf_getclass(DSO->elf) == ELFCLASS32 ? buf_write_le32(BUF, VAL) : buf_write_le64(BUF, VAL) ) + static int x86_64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, GElf_Addr adjust) @@ -84,13 +102,8 @@ x86_64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, case R_X86_64_RELATIVE: if (rela->r_addend >= start) { - if (gelf_getclass (dso->elf) == ELFCLASS32) { - if (read_ule32 (dso, rela->r_offset) == rela->r_addend) - write_le32 (dso, rela->r_offset, rela->r_addend + adjust); - } else { - if (read_ule64 (dso, rela->r_offset) == rela->r_addend) - write_le64 (dso, rela->r_offset, rela->r_addend + adjust); - } + if (read_uleclass (dso, rela->r_offset) == rela->r_addend) + write_leclass (dso, rela->r_offset, rela->r_addend + adjust); rela->r_addend += adjust; } break; @@ -99,15 +112,9 @@ x86_64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, rela->r_addend += adjust; /* FALLTHROUGH */ case R_X86_64_JUMP_SLOT: - if (gelf_getclass (dso->elf) == ELFCLASS32) { - addr = read_ule32 (dso, rela->r_offset); - if (addr >= start) - write_le32 (dso, rela->r_offset, addr + adjust); - } else { - addr = read_ule64 (dso, rela->r_offset); - if (addr >= start) - write_le64 (dso, rela->r_offset, addr + adjust); - } + addr = read_uleclass (dso, rela->r_offset); + if (addr >= start) + write_leclass (dso, rela->r_offset, addr + adjust); break; } return 0; @@ -133,10 +140,7 @@ x86_64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, return 0; else if (GELF_R_TYPE (rela->r_info) == R_X86_64_RELATIVE) { - if (gelf_getclass (dso->elf) == ELFCLASS32) - write_le32 (dso, rela->r_offset, rela->r_addend); - else - write_le64 (dso, rela->r_offset, rela->r_addend); + write_leclass (dso, rela->r_offset, rela->r_addend); return 0; } value = info->resolve (info, GELF_R_SYM (rela->r_info), @@ -145,11 +149,8 @@ x86_64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, { case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - if (gelf_getclass (dso->elf) == ELFCLASS32) - { - write_le32 (dso, rela->r_offset, value + rela->r_addend); - break; - } + write_leclass (dso, rela->r_offset, value + rela->r_addend); + break; case R_X86_64_64: write_le64 (dso, rela->r_offset, value + rela->r_addend); break; @@ -196,18 +197,12 @@ x86_64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, char *buf, GElf_Addr dest_addr) { GElf_Rela *ret; - DSO *dso; - - dso = info->dso; - switch (GELF_R_TYPE (rela->r_info)) { case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - if (gelf_getclass (dso->elf) == ELFCLASS32) { - buf_write_le32 (buf, rela->r_addend); - break; - } + buf_write_leclass (info->dso, buf, rela->r_addend); + break; case R_X86_64_64: buf_write_le64 (buf, rela->r_addend); break; @@ -241,9 +236,6 @@ static int x86_64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) { GElf_Addr value; - DSO *dso; - - dso = info->dso; value = info->resolve (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); @@ -253,11 +245,8 @@ x86_64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) break; case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - if (gelf_getclass (dso->elf) == ELFCLASS32) - { - buf_write_le32 (buf, value + rela->r_addend); - break; - } + buf_write_leclass (info->dso, buf, value + rela->r_addend); + break; case R_X86_64_64: buf_write_le64 (buf, value + rela->r_addend); break; @@ -340,10 +329,7 @@ x86_64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, switch (GELF_R_TYPE (rela->r_info)) { case R_X86_64_GLOB_DAT: - if (gelf_getclass (dso->elf) == ELFCLASS32) - ret->r_info = GELF_R_INFO (0, R_X86_64_32); - else - ret->r_info = GELF_R_INFO (0, R_X86_64_64); + ret->r_info = GELF_R_INFO (0, (gelf_getclass (dso->elf) == ELFCLASS32 ? R_X86_64_32 : R_X86_64_64)); /* FALLTHROUGH */ case R_X86_64_JUMP_SLOT: case R_X86_64_IRELATIVE: @@ -501,31 +487,18 @@ x86_64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) } else { - if (gelf_getclass (dso->elf) == ELFCLASS32) { - Elf64_Addr data = read_ule32 (dso, dso->shdr[sec].sh_addr + 8); - - assert (rela->r_offset >= dso->shdr[sec].sh_addr + 24); - assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 7) == 0); - write_le32 (dso, rela->r_offset, - 2 * (rela->r_offset - dso->shdr[sec].sh_addr - 24) - + data); - } else { - Elf64_Addr data = read_ule64 (dso, dso->shdr[sec].sh_addr + 8); + Elf64_Addr data = read_uleclass (dso, dso->shdr[sec].sh_addr + 8); - assert (rela->r_offset >= dso->shdr[sec].sh_addr + 24); - assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 7) == 0); - write_le64 (dso, rela->r_offset, + assert (rela->r_offset >= dso->shdr[sec].sh_addr + 24); + assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 7) == 0); + write_leclass (dso, rela->r_offset, 2 * (rela->r_offset - dso->shdr[sec].sh_addr - 24) + data); - } } break; case R_X86_64_GLOB_DAT: - if (gelf_getclass (dso->elf) == ELFCLASS32) - { - write_le32 (dso, rela->r_offset, 0); - break; - } + write_leclass (dso, rela->r_offset, 0); + break; case R_X86_64_64: case R_X86_64_DTPMOD64: case R_X86_64_DTPOFF64: @@ -557,8 +530,8 @@ x86_64_reloc_size (int reloc_type) { case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - case R_X86_64_IRELATIVE: case R_X86_64_64: + case R_X86_64_IRELATIVE: return 8; default: return 4; @@ -630,7 +603,6 @@ PL_ARCH(x32) = { even dlopened libraries will get the slots they desire. */ .mmap_base = 0x41000000, .mmap_end = 0x50000000, -// .max_page_size = 0x1000, .max_page_size = 0x200000, .page_size = 0x1000 }; |