#define CHECK_RELOC(val, bits) \ if (!RELOC_REACHABLE(val, bits)) { \
printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
me->name, strtab + sym->st_name, (unsignedlong)val, bits); \ return -ENOEXEC; \
}
/* Maximum number of GOT entries. We use a long displacement ldd from *thebottomofthetable,whichhasamaximumsigneddisplacementof *0x3fff;however,sincewe'reonlygoingforward,thisbecomes *0x1fff,andthus,sinceeachGOTentryis8byteslongwecanhave *atmost1023entries. *Toovercomethis14bitdisplacementwithsomekernelmodules,we'll *useinsteadtheunusal16bitdisplacementmethod(seereassemble_16a) *whichgivesusamaximumpositivedisplacementof0x7fff,andassuch
* allows us to allocate up to 4095 GOT entries. */ #define MAX_GOTS 4095
struct stub_entry {
Elf32_Word insns[2]; /* each stub entry has two insns */
}; #else struct got_entry {
Elf64_Addr addr;
};
struct stub_entry {
Elf64_Word insns[4]; /* each stub entry has four insns */
}; #endif
/* Field selection types defined by hppa */ #define rnd(x) (((x)+0x1000)&~0x1fff) /* fsel: full 32 bits */ #define fsel(v,a) ((v)+(a)) /* lsel: select left 21 bits */ #define lsel(v,a) (((v)+(a))>>11) /* rsel: select right 11 bits */ #define rsel(v,a) (((v)+(a))&0x7ff) /* lrsel with rounding of addend to nearest 8k */ #define lrsel(v,a) (((v)+rnd(a))>>11) /* rrsel with rounding of addend to nearest 8k */ #define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
#define mask(x,sz) ((x) & ~((1<<(sz))-1))
/* The reassemble_* functions prepare an immediate value for insertionintoanopcode.pa-riscusesallsortsofweirdbitfields
in the instruction to hold the value. */ staticinlineint sign_unext(int x, int len)
{ int len_ones;
len_ones = (1 << len) - 1; return x & len_ones;
}
staticinlineint low_sign_unext(int x, int len)
{ int sign, temp;
/* Additional bytes needed in front of individual sections */ unsignedint arch_mod_section_prepend(struct module *mod, unsignedint section)
{ /* size needed for all stubs of this section (including
* one additional for correct alignment of the stubs) */ return (mod->arch.section[section].stub_entries + 1)
* sizeof(struct stub_entry);
}
/* some of these are not relevant for 32-bit/64-bit *weleavethemheretomakethecodecommon.the *compilerwilldoitsthingandoptimizeoutthe *stuffwedon'tneed
*/
gots += count_gots(rels, nrels);
fdescs += count_fdescs(rels, nrels);
/* XXX: By sorting the relocs and finding duplicate entries *wecouldreducethenumberofnecessarystubsandsave
* some memory. */
count = count_stubs(rels, nrels); if (!count) continue;
/* so we need relocation stubs. reserve necessary memory. */ /* sh_info gives the section for which we need to add stubs. */
s = sechdrs[i].sh_info;
/* each code section should only have one relocation section */
WARN_ON(me->arch.section[s].stub_entries);
/* store number of stubs we need for this section */
me->arch.section[s].stub_entries += count;
}
mod_mem = &me->mem[MOD_TEXT]; /* align things a bit */
mod_mem->size = ALIGN(mod_mem->size, 16);
me->arch.got_offset = mod_mem->size;
mod_mem->size += gots * sizeof(struct got_entry);
/* initialize stub_offset to point in front of the section */ if (!me->arch.section[targetsec].stub_offset) {
loc0 -= (me->arch.section[targetsec].stub_entries + 1) * sizeof(struct stub_entry); /* get correct alignment for the stubs */
loc0 = ALIGN(loc0, sizeof(struct stub_entry));
me->arch.section[targetsec].stub_offset = loc0;
}
/* get address of stub entry */
stub = (void *) me->arch.section[targetsec].stub_offset;
me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry);
/* do not write outside available stub area */
BUG_ON(0 == me->arch.section[targetsec].stub_entries--);
#ifndef CONFIG_64BIT /* for 32-bit the stub looks like this: *ldilL'XXX,%r1 *be,nR'XXX(%sr4,%r1)
*/ //value = *(unsigned long *)((value + addend) & ~3); /* why? */
pr_debug("Applying relocate section %u to %u\n", relsec,
targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */
loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset; /* This is the start of the target section */
loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info); if (!sym->st_value) {
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name); return -ENOENT;
} //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
dot = (Elf32_Addr)loc & ~0x03;
pr_debug("Applying relocate section %u to %u\n", relsec,
targetsec); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */
loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset; /* This is the start of the target section */
loc0 = sechdrs[targetsec].sh_addr; /* This is the symbol it is referring to */
sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+ ELF64_R_SYM(rel[i].r_info); if (!sym->st_value) {
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name); return -ENOENT;
} //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03;
dot = (Elf64_Addr)loc & ~0x03;
loc64 = (Elf64_Xword *)loc;
switch (ELF64_R_TYPE(rel[i].r_info)) { case R_PARISC_LTOFF21L: /* LT-relative; left 21 bits */
val = get_got(me, val, addend);
pr_debug("LTOFF21L Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
val = lrsel(val, 0);
*loc = mask(*loc, 21) | reassemble_21(val); break; case R_PARISC_LTOFF14R: /* L(ltoff(val+addend)) */ /* LT-relative; right 14 bits */
val = get_got(me, val, addend);
val = rrsel(val, 0);
pr_debug("LTOFF14R Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
*loc = mask(*loc, 14) | reassemble_14(val); break; case R_PARISC_PCREL22F: /* PC-relative; 22 bits */
pr_debug("PCREL22F Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
val += addend; /* can we reach it locally? */ if (within_module(val, me)) { /* this is the case where the symbol is local *tothemodule,butinadifferentsection, *sostubthejumpincaseit'smorethan22
* bits away */
val = (val - dot - 8)/4; if (!RELOC_REACHABLE(val, 22)) { /* direct distance too far, create
* stub entry instead */
val = get_stub(me, sym->st_value,
addend, ELF_STUB_DIRECT,
loc0, targetsec);
} else { /* Ok, we can reach it directly. */
val = sym->st_value;
val += addend;
}
} else {
val = sym->st_value; if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, ELF_STUB_MILLI,
loc0, targetsec); else
val = get_stub(me, val, addend, ELF_STUB_GOT,
loc0, targetsec);
}
pr_debug("STUB FOR %s loc %px, val %llx+%llx at %llx\n",
strtab + sym->st_name, loc, sym->st_value,
addend, val);
val = (val - dot - 8)/4;
CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; case R_PARISC_PCREL32: /* 32-bit PC relative address */
*loc = val - dot - 8 + addend; break; case R_PARISC_PCREL64: /* 64-bit PC relative address */
*loc64 = val - dot - 8 + addend; break; case R_PARISC_DIR64: /* 64-bit effective address */
*loc64 = val + addend; break; case R_PARISC_SEGREL32: /* 32-bit segment relative address */ /* See note about special handling of SEGREL32 at *thebeginningofthisfile.
*/
*loc = fsel(val, addend); break; case R_PARISC_SECREL32: /* 32-bit section relative address. */
*loc = fsel(val, addend); break; case R_PARISC_FPTR64: /* 64-bit function address */ if (within_module(val + addend, me)) {
*loc64 = get_fdesc(me, val+addend);
pr_debug("FDESC for %s at %llx points to %llx\n",
strtab + sym->st_name, *loc64,
((Elf_Fdesc *)*loc64)->addr);
} else { /* if the symbol is not local to this *modulethenval+addendisapointer
* to the function descriptor */
pr_debug("Non local FPTR64 Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
*loc64 = val + addend;
} break;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.27Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.