Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ARM kernel module supported reloc types



On Sat, Dec 27, 2008 at 04:22:26PM +1300, Lloyd Parkes wrote:
> Rafal,
> Are you sure the relocs for PC24 are out of range? I've been looking  
> at this over the past few days before I saw your message in the archive.
> 
> As far as I can tell, the actual offset is a word offset, not a byte  
> offset, so the address range is effectively +/- 32MB. That's a whole  
> lot of address space for kernel code. Of course, it might be that  
> modules are loaded into far flung parts of the address space.

Right, the offset is the low 24-bits right-shifted by 2, so you're right
about the offset.  

In my case, I think the offset for at least 'printf' in the example module
was indeed > 32MB.  Note that I was running an monolithic INSTALL kernel
and to get at the modules and stuff I wanted to play with had to re-mount
the real root FS over NFS, so there's quite a bit of stuff going on before
I could get to the module.

Since that point, I haven't had much NetBSD hacking time, so I haven't had
a chance to play with any of the suggestions Andrew offered later in the
thread (create new module_map, submap module_map from kernel_map)... I'll
attach my PC24 reloc patch below in case it's helpful (or in case you find
it's indeed buggy ;)).

--rafal

PS: I'm mostly AFK for the next week or so, but let me know if you do make
any progress.

-- 
  Time is an illusion; lunchtime, doubly so.     |/\/\|           Rafal Boni
                   -- Ford Prefect               |\/\/|      
rafal%pobox.com@localhost
:100644 100644 901d01f... 6ff9326... M  sys/arch/arm/arm32/kobj_machdep.c

diff --git a/sys/arch/arm/arm32/kobj_machdep.c 
b/sys/arch/arm/arm32/kobj_machdep.c
index 901d01f..6ff9326 100644
--- a/sys/arch/arm/arm32/kobj_machdep.c
+++ b/sys/arch/arm/arm32/kobj_machdep.c
@@ -93,6 +93,31 @@ kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data,
        case R_ARM_NONE:        /* none */
                break;
 
+       case R_ARM_PC24: {      /* S - PC + (SignExt(A & 0xffffff)) << 2  */
+               Elf_Addr tmp;
+
+               /* Truncate (and sign-extend if needed) 24-bit addend */
+               addend &= 0x00ffffff;
+               if (addend & 0x00800000)
+                       addend |= 0xff000000;
+
+               addr = kobj_sym_lookup(ko, symidx);
+               if (addr == 0)
+                       return -1;
+               tmp = addr - (Elf_Addr)where + (addend << 2);
+               printf("kobj_reloc: R_PC24 relocation @ %p -- base = %#lx, addr 
= %#lx, addend = %#lx, out = %#lx\n", where, (long)relocbase, (long)addr, 
(long)addend, (long)tmp);
+               if ((tmp & 0xfe000000) != 0xfe000000 &&
+                   (tmp & 0xfe000000) != 0) {
+                       printf("kobj_reloc: failed R_PC24 relocation @ %p (disp 
%ld (%#lx) out of range)\n", where, (long)tmp, (long)tmp);
+                       return -1;
+               }
+
+               tmp >>= 2;
+               if ((*where & 0x00ffffff) != (tmp & 0x00ffffff))
+                       *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
+               break;
+       }
+
        case R_ARM_ABS32:
                addr = kobj_sym_lookup(ko, symidx);
                if (addr == 0)
@@ -125,7 +150,7 @@ kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data,
                break;
 
        default:
-               printf("kobj_reloc: unexpected relocation type %d\n", rtype);
+               printf("kobj_reloc: unexpected relocation type %d @ %p\n", 
rtype, where);
                return -1;
        }
        return 0;


Home | Main Index | Thread Index | Old Index