diff options
Diffstat (limited to 'trunk/src/arch-sparc64.c')
-rw-r--r-- | trunk/src/arch-sparc64.c | 725 |
1 files changed, 725 insertions, 0 deletions
diff --git a/trunk/src/arch-sparc64.c b/trunk/src/arch-sparc64.c new file mode 100644 index 0000000..e673e99 --- /dev/null +++ b/trunk/src/arch-sparc64.c @@ -0,0 +1,725 @@ +/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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 + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +#define SPARC64_R_TYPE(info) (GELF_R_TYPE (info) & 0xff) + +static int +sparc64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".got")) + { + Elf64_Addr data; + + data = read_ube64 (dso, dso->shdr[i].sh_addr); + /* .got[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be64 (dso, dso->shdr[i].sh_addr, data + adjust); + break; + } + } + + return 0; +} + +static int +sparc64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + if (rela->r_addend >= start) + rela->r_addend += adjust; + } + else if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_JMP_SLOT + && rela->r_addend) + { + /* .plt[32768+] r_addends are -some_address_in_plt_section. */ + if ((- rela->r_addend) >= start) + rela->r_addend -= adjust; + } + return 0; +} + +static int +sparc64_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static void +sparc64_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr value) +{ + Elf64_Sxword disp = value - rela->r_offset; + + if (rela->r_addend) + { + /* .plt[32768+] */ + write_be64 (dso, rela->r_offset, value); + } + else if (disp >= -0x800000 && disp < 0x800000) + { + /* b,a value + nop + nop */ + write_be32 (dso, rela->r_offset, 0x30800000 | ((disp >> 2) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x01000000); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } + else if (! (value >> 32)) + { + /* sethi %hi(value), %g1 + jmpl %g1 + %lo(value), %g0 + nop */ + write_be32 (dso, rela->r_offset, 0x03000000 | ((value >> 10) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x81c06000 | (value & 0x3ff)); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } + else if ((rela->r_offset + 4 > value + && ((rela->r_offset - value) >> 31) == 0) + || (value > rela->r_offset + 4 + && ((value - rela->r_offset - 4) >> 31) == 0)) + { + /* mov %o7, %g1 + call value + mov %g1, %o7 */ + write_be32 (dso, rela->r_offset, 0x8210000f); + write_be32 (dso, rela->r_offset + 4, 0x40000000 + | (((value - rela->r_offset - 4) >> 2) & 0x3fffffff)); + write_be32 (dso, rela->r_offset + 8, 0x9e100001); + } + else + { + unsigned int csts[4]; + int i = 0; + + /* sethi %hh(value), %g1 + sethi %lm(value), %g5 + or %g1, %hm(value), %g1 + or %g5, %lo(value), %g5 + sllx %g1, 32, %g1 + jmpl %g1 + %g5, %g0 + nop */ + + csts[0] = value >> 42; + csts[1] = (value >> 32) & 0x3ff; + csts[2] = (value >> 10) & 0x3fffff; + csts[3] = value & 0x3ff; + write_be32 (dso, rela->r_offset, 0x03000000 | csts[0]); + write_be32 (dso, rela->r_offset + 4, 0x0b000000 | csts[2]); + /* Sparc64 shared libs are often 0xfffff800XXXXXXXX, so optimize + for this common case. */ + if (csts[1] == 0) + write_be32 (dso, rela->r_offset + 8, 0x83287020); + else + write_be32 (dso, rela->r_offset + 8, 0x82106000 | csts[1]); + write_be32 (dso, rela->r_offset + 12, 0x8a116000 | csts[3]); + if (csts[1] != 0) + write_be32 (dso, rela->r_offset + 16, 0x83287020), i = 4; + write_be32 (dso, rela->r_offset + 16 + i, 0x81c04005); + write_be32 (dso, rela->r_offset + 20 + i, 0x01000000); + } +} + +static int +sparc64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_NONE) + return 0; + else if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + /* 64-bit SPARC handles RELATIVE relocs as + *(long *)rela->r_offset = l_addr + rela->r_addend, + so we must update the memory. */ + write_be64 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + write_be64 (dso, rela->r_offset, value); + break; + case R_SPARC_32: + case R_SPARC_UA32: + write_be32 (dso, rela->r_offset, value); + break; + case R_SPARC_JMP_SLOT: + sparc64_fixup_plt (dso, rela, value); + break; + case R_SPARC_8: + write_8 (dso, rela->r_offset, value); + break; + case R_SPARC_16: + case R_SPARC_UA16: + write_be16 (dso, rela->r_offset, value); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + (value & 0x3ff) | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + write_be32 (dso, rela->r_offset, + ((value >> 10) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP64: + write_be64 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + (((value - rela->r_offset) >> 2) & 0x3fffffff) + | (read_ube32 (dso, rela->r_offset) & 0xc0000000)); + break; + case R_SPARC_H44: + write_be32 (dso, rela->r_offset, + ((value >> 22) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_M44: + write_be32 (dso, rela->r_offset, + ((value >> 12) & 0x3ff) + | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_L44: + write_be32 (dso, rela->r_offset, + (value & 0xfff) | (read_ube32 (dso, rela->r_offset) & ~0xfff)); + break; + case R_SPARC_HH22: + write_be32 (dso, rela->r_offset, + ((value >> 42) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_HM10: + write_be32 (dso, rela->r_offset, + ((value >> 32) & 0x3ff) + | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_OLO10: + write_be32 (dso, rela->r_offset, + (((value & 0x3ff) + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff) + | (read_ube32 (dso, rela->r_offset) & ~0x1fff)); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) SPARC64_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_64: + case R_SPARC_UA64: + buf_write_be64 (buf, rela->r_addend); + break; + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, rela->r_addend); + break; + case R_SPARC_8: + buf_write_8 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +sparc64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +sparc64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + break; + case R_SPARC_DISP64: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + buf_write_be64 (buf, value); + break; + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, value); + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, value); + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + buf_write_8 (buf, value); + break; + case R_SPARC_LO10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) | (value & 0x3ff)); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 10) & 0x3fffff)); + break; + case R_SPARC_WDISP30: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff)); + break; + case R_SPARC_H44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 22) & 0x3fffff)); + break; + case R_SPARC_M44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) + | ((value >> 12) & 0x3ff)); + break; + case R_SPARC_L44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0xfff) | (value & 0xfff)); + break; + case R_SPARC_HH22: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 42) & 0x3fffff)); + break; + case R_SPARC_HM10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) + | ((value >> 32) & 0x3ff)); + break; + case R_SPARC_OLO10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x1fff) + | (((value & 0x3ff) + + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff)); + break; + case R_SPARC_RELATIVE: + error (0, 0, "%s: R_SPARC_RELATIVE in ET_EXEC object?", + info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +sparc64_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *ret; + int r_type; + + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE + || SPARC64_R_TYPE (rela->r_info) == R_SPARC_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + if (conflict == NULL) + return 0; + value = conflict_lookup_value (conflict); + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + value += rela->r_addend; + r_type = SPARC64_R_TYPE (rela->r_info); + switch (r_type) + { + case R_SPARC_DISP64: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + r_type = R_SPARC_64; + break; + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_32: + r_type = R_SPARC_32; + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + r_type = R_SPARC_16; + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + r_type = R_SPARC_8; + break; + /* Attempt to transform all reloc which read-modify-write into + simple writes. */ + case R_SPARC_LO10: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) | (value & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 10) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_WDISP30: + value = (read_ube32 (dso, rela->r_offset) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff); + r_type = R_SPARC_32; + break; + case R_SPARC_H44: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 22) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_M44: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) + | ((value >> 12) & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_L44: + value = (read_ube32 (dso, rela->r_offset) & ~0xfff) | (value & 0xfff); + r_type = R_SPARC_32; + break; + case R_SPARC_HH22: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 42) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_HM10: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) + | ((value >> 32) & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_OLO10: + value = (read_ube32 (dso, rela->r_offset) & ~0x1fff) + | (((value & 0x3ff) + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff); + r_type = R_SPARC_32; + break; + case R_SPARC_JMP_SLOT: + if (rela->r_addend) + r_type = R_SPARC_64; + break; + case R_SPARC_UA16: + case R_SPARC_UA32: + case R_SPARC_UA64: + break; + default: + error (0, 0, "%s: Unknown Sparc relocation type %d", dso->filename, + r_type); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + ret->r_addend = value; + return 0; +} + +static int +sparc64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +sparc64_arch_prelink (struct prelink_info *info) +{ + return 0; +} + +static int +sparc64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + if (sec != -1) + { + if (rela->r_addend == 0) + { + /* sethi .-.plt, %g1 + b,a %xcc, .plt+0x20 */ + write_be32 (dso, rela->r_offset, + 0x03000000 + | ((rela->r_offset - dso->shdr[sec].sh_addr) + & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, + 0x30680000 + | (((dso->shdr[sec].sh_addr + 32 + - rela->r_offset - 4) >> 2) + & 0x7ffff)); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + write_be32 (dso, rela->r_offset + 12, 0x01000000); + write_be32 (dso, rela->r_offset + 16, 0x01000000); + write_be32 (dso, rela->r_offset + 20, 0x01000000); + write_be32 (dso, rela->r_offset + 24, 0x01000000); + write_be32 (dso, rela->r_offset + 28, 0x01000000); + } + else + { + GElf_Addr slot = ((rela->r_offset + 0x400 + - dso->shdr[sec].sh_addr) + / 0x1400) * 0x1400 + + dso->shdr[sec].sh_addr - 0x400; + /* slot+12 contains: ldx [%o7 + X], %g1 */ + GElf_Addr ptr = slot + (read_ube32 (dso, slot + 12) & 0xfff) + 4; + + write_be64 (dso, rela->r_offset, + dso->shdr[sec].sh_addr + - (slot + ((rela->r_offset - ptr) / 8) * 24 + 4)); + } + } + break; + case R_SPARC_RELATIVE: + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + case R_SPARC_DISP64: + write_be64 (dso, rela->r_offset, 0); + break; + case R_SPARC_32: + case R_SPARC_UA32: + case R_SPARC_DISP32: + write_be32 (dso, rela->r_offset, 0); + break; + case R_SPARC_8: + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, 0); + break; + case R_SPARC_16: + case R_SPARC_UA16: + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, 0); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xc0000000); + break; + case R_SPARC_H44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_M44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_L44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0xfff); + break; + case R_SPARC_HH22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_HM10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_OLO10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x1fff); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc64_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_8: + case R_SPARC_DISP8: + return 1; + case R_SPARC_16: + case R_SPARC_DISP16: + case R_SPARC_UA16: + return 2; + case R_SPARC_RELATIVE: + case R_SPARC_64: + case R_SPARC_UA64: + case R_SPARC_GLOB_DAT: + return 8; + default: + break; + } + return 4; +} + +static int +sparc64_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_COPY: return RTYPE_CLASS_COPY; + case R_SPARC_JMP_SLOT: return RTYPE_CLASS_PLT; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "SPARC", + .class = ELFCLASS64, + .machine = EM_SPARCV9, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_SPARC_JMP_SLOT, + .R_COPY = R_SPARC_COPY, + .R_RELATIVE = R_SPARC_RELATIVE, + .dynamic_linker = "/lib64/ld-linux.so.2", + .adjust_dyn = sparc64_adjust_dyn, + .adjust_rel = sparc64_adjust_rel, + .adjust_rela = sparc64_adjust_rela, + .prelink_rel = sparc64_prelink_rel, + .prelink_rela = sparc64_prelink_rela, + .prelink_conflict_rel = sparc64_prelink_conflict_rel, + .prelink_conflict_rela = sparc64_prelink_conflict_rela, + .apply_conflict_rela = sparc64_apply_conflict_rela, + .apply_rel = sparc64_apply_rel, + .apply_rela = sparc64_apply_rela, + .rel_to_rela = sparc64_rel_to_rela, + .need_rel_to_rela = sparc64_need_rel_to_rela, + .reloc_size = sparc64_reloc_size, + .reloc_class = sparc64_reloc_class, + .max_reloc_size = 8, + .arch_prelink = sparc64_arch_prelink, + .undo_prelink_rela = sparc64_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0xfffff80000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0xfffff80001000000LL, + /* If we need yet more space for shared libraries, we can of course + expand, but limiting all DSOs into 4 GB means stack overflows + jumping to shared library functions is much harder (there is + '\0' byte in the address before the bytes that matter). */ + .mmap_end = 0xfffff80100000000LL, + .max_page_size = 0x100000, + .page_size = 0x2000 +}; |