Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 31153
b: refs/heads/master
c: 6e1b958
h: refs/heads/master
i:
  31151: 4a13c4d
v: v3
  • Loading branch information
James Bottomley authored and Kyle McMartin committed Jun 27, 2006
1 parent be7e95b commit 8a1f43b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1c63b4b8474700f3fb5e3442a78897766f153437
refs/heads/master: 6e1b9585aaae2fa4f9590f363b32c5d3b6339ba6
63 changes: 50 additions & 13 deletions trunk/arch/parisc/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ static inline int is_local(struct module *me, void *loc)
return is_init(me, loc) || is_core(me, loc);
}

static inline int is_local_section(struct module *me, void *loc, void *dot)
{
return (is_init(me, loc) && is_init(me, dot)) ||
(is_core(me, loc) && is_core(me, dot));
}


#ifndef __LP64__
struct got_entry {
Expand Down Expand Up @@ -364,8 +370,14 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
}
#endif /* __LP64__ */

enum elf_stub_type {
ELF_STUB_GOT,
ELF_STUB_MILLI,
ELF_STUB_DIRECT,
};

static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
int millicode, int init_section)
enum elf_stub_type stub_type, int init_section)
{
unsigned long i;
struct stub_entry *stub;
Expand Down Expand Up @@ -396,7 +408,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);

#else
/* for 64-bit we have two kinds of stubs:
/* for 64-bit we have three kinds of stubs:
* for normal function calls:
* ldd 0(%dp),%dp
* ldd 10(%dp), %r1
Expand All @@ -408,26 +420,41 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
* ldo 0(%r1), %r1
* ldd 10(%r1), %r1
* bve,n (%r1)
*
* for direct branches (jumps between different section of the
* same module):
* ldil 0, %r1
* ldo 0(%r1), %r1
* bve,n (%r1)
*/
if (!millicode)
{
switch (stub_type) {
case ELF_STUB_GOT:
stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */
stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */
stub->insns[2] = 0xe820d000; /* bve (%r1) */
stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */

stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
}
else
{
break;
case ELF_STUB_MILLI:
stub->insns[0] = 0x20200000; /* ldil 0,%r1 */
stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */
stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */
stub->insns[3] = 0xe820d002; /* bve,n (%r1) */

stub->insns[0] |= reassemble_21(lrsel(value, addend));
stub->insns[1] |= reassemble_14(rrsel(value, addend));
break;
case ELF_STUB_DIRECT:
stub->insns[0] = 0x20200000; /* ldil 0,%r1 */
stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */
stub->insns[2] = 0xe820d002; /* bve,n (%r1) */

stub->insns[0] |= reassemble_21(lrsel(value, addend));
stub->insns[1] |= reassemble_14(rrsel(value, addend));
break;
}

#endif

return (Elf_Addr)stub;
Expand Down Expand Up @@ -539,14 +566,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_PCREL17F:
/* 17-bit PC relative address */
val = get_stub(me, val, addend, 0, is_init(me, loc));
val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
val = (val - dot - 8)/4;
CHECK_RELOC(val, 17)
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break;
case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */
val = get_stub(me, val, addend, 0, is_init(me, loc));
val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
strtab + sym->st_name, (unsigned long)loc, addend,
val)
Expand Down Expand Up @@ -643,13 +670,23 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
strtab + sym->st_name,
loc, val);
/* can we reach it locally? */
if(!is_local(me, (void *)val)) {
if (strncmp(strtab + sym->st_name, "$$", 2)
if(!is_local_section(me, (void *)val, (void *)dot)) {

if (is_local(me, (void *)val))
/* this is the case where the
* symbol is local to the
* module, but in a different
* section, so stub the jump
* in case it's more than 22
* bits away */
val = get_stub(me, val, addend, ELF_STUB_DIRECT,
is_init(me, loc));
else if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, 1,
val = get_stub(me, val, addend, ELF_STUB_MILLI,
is_init(me, loc));
else
val = get_stub(me, val, addend, 0,
val = get_stub(me, val, addend, ELF_STUB_GOT,
is_init(me, loc));
}
DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
Expand Down

0 comments on commit 8a1f43b

Please sign in to comment.