User/Kernel - ARMv7 fixes (relocation of .text)
authorJohn Hodge (sonata) <[email protected]>
Sun, 4 Nov 2012 02:58:13 +0000 (10:58 +0800)
committerJohn Hodge (sonata) <[email protected]>
Sun, 4 Nov 2012 02:58:13 +0000 (10:58 +0800)
17 files changed:
KernelLand/Kernel/arch/armv7/lib.c
KernelLand/Kernel/arch/armv7/mm_virt.c
KernelLand/Kernel/arch/armv7/start.S
KernelLand/Kernel/bin/elf.c
KernelLand/Kernel/binary.c
KernelLand/Kernel/logging.c
KernelLand/Kernel/syscalls.c
KernelLand/Kernel/vfs/mmap.c
KernelLand/Modules/Filesystems/InitRD/files.lst
Makefile
Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h
Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h
Usermode/Libraries/ld-acess.so_src/common.h
Usermode/Libraries/ld-acess.so_src/elf.c
Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h
Usermode/Libraries/ld-acess.so_src/loadlib.c
Usermode/Libraries/libc.so_src/Makefile

index 65c457c..f33f339 100644 (file)
@@ -103,7 +103,7 @@ void *memset(void *_dest, int _value, size_t _length)
        val32 |= val32 << 16;
        
        // Force alignment
-       while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value;
+       while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value, _length --;
        dst = (void *)dst8;
 
        // DWORD copies
index 00d6c68..146caea 100644 (file)
@@ -10,6 +10,7 @@
 #include <hal_proc.h>
 
 #define TRACE_MAPS     0
+#define TRACE_COW      1
 
 #define AP_KRW_ONLY    1       // Kernel page
 #define AP_KRO_ONLY    5       // Kernel RO page
 #define AP_RO_USER     2       // User RO Page
 #define PADDR_MASK_LVL1        0xFFFFFC00
 
+const char * const caAPValueNames[] = {
+       "AP_NOACCESS", "AP_KRW_ONLY",
+       "AP_RO_USER", "AP_RW_BOTH",
+       "AP_???_4", "AP_KRO_ONLY",
+       "AP_???_6", "AP_RO_BOTH"
+};
+
 // === IMPORTS ===
 extern Uint32  kernel_table0[];
 
@@ -53,7 +61,7 @@ tPAddr        MM_Clone(void);
 tVAddr MM_NewKStack(int bGlobal);
 void   MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info);
 //void MM_DumpTables(tVAddr Start, tVAddr End);
-void   MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch);
+void   MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR);
 
 // === GLOBALS ===
 tPAddr giMM_ZeroPage;
@@ -938,18 +946,20 @@ void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info)
 {
        if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage )
        {
-               Debug("%p => %8s - 0x%7x %i %x %s",
+               Debug("%p => %8s - 0x%7x D%i %x %s %s",
                        Start, "ZERO", Len,
                        Info->Domain, Info->AP,
-                       Info->bGlobal ? "G" : "nG"
+                       Info->bExecutable ? " X" : "nX",
+                       Info->bGlobal ? " G" : "nG"
                        );
        }
        else
        {
-               Debug("%p => %8x - 0x%7x %i %x %s",
+               Debug("%p => %8x - 0x%7x D%i %x %s %s",
                        Start, Info->PhysAddr-Len, Len,
                        Info->Domain, Info->AP,
-                       Info->bGlobal ? "G" : "nG"
+                       Info->bExecutable ? " X" : "nX",
+                       Info->bGlobal ? " G" : "nG"
                        );
        }
 }
@@ -996,7 +1006,7 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
 }
 
 // NOTE: Runs in abort context, not much difference, just a smaller stack
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch)
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR)
 {
         int    rv;
        tMM_PageInfo    pi;
@@ -1070,6 +1080,33 @@ void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch)
        Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR,
                (bPrefetch ? " - Prefetch" : "")
                );
+       Log_Error("MMVirt", "- User LR = 0x%x", UserLR);
+       const char * const dfsr_errors[] = {
+               /* 00000 */ "-", "Alignment Fault",
+               /* 00010 */ "Debug event", "Access Flag (Section)",
+               /* 00100 */ "Instr Cache Maint", "Translation (Section)",
+               /* 00110 */ "Access Flag (Page)", "Translation (Page)",
+               /* 01000 */ "Sync. External abort", "Domain (Section)",
+               /* 01010 */ "-", "Domain (Page)",
+               /* 01100 */ "Table Walk sync ext (lvl 1)", "Permission (Section)",
+               /* 01110 */ "Table Walk sync ext (lvl 2)", "Permission (Page)",
+               // 0b10000
+               /* 10000 */ "-", "-",
+               /* 10010 */ "-", "-",
+               /* 10100 */ "IMPL (Lockdown)", "-",
+               /* 10110 */ "Async. Extern. Abort", "-",
+               /* 11000 */ "Mem. access async pairity error", "Mem. access async pairity error",
+               /* 11010 */ "IMPL (Coprocessor abort)", "-",
+               /* 11100 */ "Table Walk Sync parity (lvl 1)", "-",
+               /* 11110 */ "Table Walk Sync parity (lvl 2)", "-"
+               };
+        int    errcode = (DFSR & 0xF) | (((DFSR >> 10) & 1) << 4);
+       Log_Error("MMVirt", "- Errcode 0b%05b", errcode);
+       Log_Error("MMVirt", "- Dom %i %s %s",
+               (DFSR >> 4) & 0xF, (DFSR & 0x800 ? "Write": "Read"),
+               dfsr_errors[errcode]
+               );
+       Log_Error("MMVirt", "- AP=%i(%s) %s", pi.AP, caAPValueNames[pi.AP], pi.bExecutable ? " Executable":"");
        if( Addr < 0x80000000 )
                MM_DumpTables(0, 0x80000000);
        else
index 113c8a4..71534f5 100644 (file)
@@ -194,12 +194,21 @@ DataAbort:
 @      cpsid ifa, #19
        PUSH_GPRS
 
+       @ Get the user's LR value (and push to stack)
+       cps #31 @ Go to system mode
+       mov r1, lr
+       cps #19 @ Go to supervisor
+       mov r0, lr
+       cps #23 @ back to exception
+       push {r0,r1}
+       
        mov r3, #0      @ not a prefetch abort
        mrc p15, 0, r2, c5, c0, 0       @ Read DFSR (Data Fault Status Register) to R2
        mrc p15, 0, r1, c6, c0, 0       @ Read DFAR (Data Fault Address Register) into R1
        mov r0, lr      @ PC
        ldr r4, =MM_PageFault
        blx r4
+       add sp, #8      @ Undo push of the user/system LR
 
        POP_GPRS
        rfeia sp!       @ Pop state (actually RFEFD)
@@ -211,17 +220,24 @@ PrefetchAbort:
 @      cpsid ifa, #19
        PUSH_GPRS
 
-       ldr r0, =csAbort_Tag
-       ldr r1, =csPrefetchAbort_Fmt
-#      mov r2, lr
-       mrc p15, 0, r2, c6, c0, 2       @ Read IFAR (Instruction Fault Address Register) into R3
-       mrc p15, 0, r3, c5, c0, 1       @ Read IFSR (Instruction Fault Status Register) into R3
-       ldr r5, =Log_Error
-       blx r5
 
-.loop:
-       wfi
-       b .loop
+       @ Get the user's LR value (and push to stack)
+       cps #31 @ Go to system mode
+       mov r0, lr
+       cps #23 @ back to supervisor
+       push {r0}
+       
+       mrc p15, 0, r2, c5, c0, 1       @ Read IFSR (Instruction Fault Status Register) into R3
+       mrc p15, 0, r1, c6, c0, 2       @ Read IFAR (Instruction Fault Address Register) into R3
+       mov r0, r1
+       mov r3, #1      @ IS a prefetch abort
+       ldr r4, =MM_PageFault
+       blx r4
+       add sp, #4      @ Undo push of the user LR
+
+       POP_GPRS
+       rfeia sp!       @ Pop state (actually RFEFD)
+
 .globl Undef_Handler
 Undef_Handler:
        wfi
@@ -238,7 +254,7 @@ csIRQ_Fmt:
 csDataAbort_Fmt:
        .asciz "Data Abort - %p accessed %p, DFSR=%x Unk:%x Unk:%x"
 csPrefetchAbort_Fmt:
-       .asciz "Prefetch Abort at %p, IFSR=%x"
+       .asciz "Prefetch Abort at %p, IFSR=%x, UserLR:0x%x"
 csSyscallPrintRetAddr:
        .asciz "Syscall ret to %p"
 
index 76724bc..7e1ef5e 100644 (file)
 #if BITS <= 32\r
 # define DISABLE_ELF64\r
 #endif\r
-void   *GetSymbol(const char *Name, size_t *Size);\r
-void   *GetSymbol(const char *Name, size_t *Size) { Uint val; Binary_GetSymbol(Name, &val); if(Size)*Size=0; return (void*)val; };\r
+static int     GetSymbol(const char *Name, void **Value, size_t *Size);\r
+static int     GetSymbol(const char *Name, void **Value, size_t *Size) {\r
+       Uint val;\r
+       if(Binary_GetSymbol(Name, &val))\r
+               return 0;\r
+       if(Size)\r
+               *Size=0;\r
+       *Value = (void*)val;\r
+       return 1;\r
+}\r
 #define AddLoaded(a,b) do{}while(0)\r
 #define LoadLibrary(a,b,c)     (Log_Debug("ELF", "Module requested lib '%s'",a),0)\r
+#define SysSetMemFlags(ad,f,m) do{}while(0)\r
 #include "../../../Usermode/Libraries/ld-acess.so_src/elf.c"\r
 \r
 #define DEBUG_WARN     1\r
index 92baa73..ec5db13 100644 (file)
@@ -2,7 +2,7 @@
  * Acess2
  * Common Binary Loader
  */
-#define DEBUG  0
+#define DEBUG  1
 #include <acess.h>
 #include <binary.h>
 #include <mm_virt.h>
index 9617b83..323e84b 100644 (file)
@@ -161,9 +161,11 @@ void Log_Int_PrintMessage(tLogEntry *Entry)
        if( CPU_HAS_LOCK(&glLogOutput) )
                return ;        // TODO: Error?
        SHORTLOCK( &glLogOutput );
-       LogF("%s%014lli%s [%-8s] %i - %s",
+       LogF("%s%014lli",
                csaLevelColours[Entry->Level],
-               Entry->Time,
+               Entry->Time
+               );
+       LogF("%s [%-8s] %i - %s",
                csaLevelCodes[Entry->Level],
                Entry->Ident,
                Threads_GetTID(),
index bfd68bf..3dc1955 100644 (file)
@@ -38,6 +38,7 @@ extern Uint   Binary_Load(const char *file, Uint *entryPoint);
 void   SyscallHandler(tSyscallRegs *Regs);
  int   Syscall_ValidString(const char *Addr);
  int   Syscall_Valid(int Size, const void *Addr);
+ int   Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask);
 
 // === CODE ===
 // TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel
@@ -114,6 +115,11 @@ void SyscallHandler(tSyscallRegs *Regs)
        // -- Unmap an address
        case SYS_UNMAP:         MM_Deallocate(Regs->Arg1);      break;
        
+       // -- Change the protection on an address
+       case SYS_SETFLAGS:
+               ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3);
+               break;
+
        // -- Get Thread/Process IDs
        case SYS_GETTID:        ret = Threads_GetTID(); break;
        case SYS_GETPID:        ret = Threads_GetPID(); break;
@@ -398,3 +404,21 @@ int Syscall_Valid(int Size, const void *Addr)
        
        return CheckMem( Addr, Size );
 }
+
+int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask)
+{
+       tPAddr  paddr = MM_GetPhysAddr(Addr);
+       Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+       Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+       // Enable write?
+       if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) {
+               void    *node;
+               // HACK - Assume that RO mmap'd files are immutable
+               if( MM_GetPageNode(paddr, &node) == 0 && node ) {
+                       Flags |= MM_PFLAG_COW;
+                       Mask |= MM_PFLAG_COW;
+               }
+       }
+       MM_SetFlags((tVAddr)Addr, Flags, Mask);
+       return 0;
+}
index c5015e6..15dacf2 100644 (file)
@@ -5,7 +5,7 @@
  * mmap.c
  * - VFS_MMap support
  */
-#define DEBUG  0
+#define DEBUG  1
 #include <acess.h>
 #include <vfs.h>
 #include <vfs_ext.h>
@@ -57,6 +57,7 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                                        PAGE_SIZE - (mapping_base & (PAGE_SIZE-1))
                                        );
                                memset( (void*)(mapping_base + ofs), 0, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1)));
+                               LOG("dune");
                        }
                        else {
                                LOG("New empty page");
index fe2fc4d..77426da 100644 (file)
@@ -19,7 +19,6 @@ Dir "Libs" {
        File "ld-acess.so" "__BIN__/Libs/ld-acess.so"
        File "libld-acess.so" "__BIN__/Libs/libld-acess.so"
        File "libc.so" "__BIN__/Libs/libc.so"
-       File "libgcc.so" "__BIN__/Libs/libgcc.so"
        File "libreadline.so" "__BIN__/Libs/libreadline.so"
        File "libnet.so" "__BIN__/Libs/libnet.so"
        File "liburi.so" "__BIN__/Libs/liburi.so"
index 1d05b1a..abf19e5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
 
 SUBMAKE = $(MAKE) --no-print-directory
 
-USRLIBS := crt0.o acess.ld ld-acess.so libgcc.so libc.so
+USRLIBS := crt0.o acess.ld ld-acess.so libc.so
 USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
 USRLIBS += libimage_sif.so
 
index 9132c02..46128b2 100644 (file)
@@ -39,29 +39,19 @@ __clear_cache:
        svc #0x1001
        mov pc, lr
 
-@ DEST
-@ SRC
-@_memcpy:
-@      push rbp
-@      mov rbp, rsp
-@      
-@      ; RDI - First Param
-@      ; RSI - Second Param
-@      mov rcx, rdx    ; RDX - Third
-@      rep movsb
-@      
-@      pop rbp
-@      ret
-@
+.section .data
 .globl _errno
 _errno:        .long   0       @ Placed in .text, to allow use of relative addressing
+.section .text
 
 .macro syscall0 _name, _num    
 .globl \_name
 \_name:
        push {lr}
        svc #\_num
-       str r2, _errno
+       @mrc p15, 0, r3, c13, c0, 2
+       ldr r3, =_errno
+       str r2, [r3]
        pop {pc}
 .endm
 
@@ -71,7 +61,8 @@ _errno:       .long   0       @ Placed in .text, to allow use of relative addressing
        push {r4, lr}
        ldr r4, [sp,#8]
        svc #\_num
-       str r2, _errno
+       ldr r3, =_errno
+       str r2, [r3]
        pop {r4, pc}
 .endm
 
@@ -82,7 +73,8 @@ _errno:       .long   0       @ Placed in .text, to allow use of relative addressing
        ldr r4, [sp,#12]
        ldr r5, [sp,#16]
        svc #\_num
-       str r2, _errno
+       ldr r3, =_errno
+       str r2, [r3]
        pop {r4,r5,pc}
 .endm
 
@@ -107,7 +99,8 @@ _clone:
        push {r4}
        mov r4, r1
        svc #SYS_CLONE
-       str r2, _errno
+       ldr r3, =_errno
+       str r2, [r3]
        tst r4, r4
        beq _clone_ret
        @ If in child, set SP
index a978a35..a59e857 100644 (file)
@@ -37,6 +37,7 @@ SYSCALL1(_SysSetFaultHandler, SYS_SETFAULTHANDLER)
 SYSCALL6(_SysDebug, 0x100)
 SYSCALL1(_SysGetPhys, SYS_GETPHYS)     // uint64_t _SysGetPhys(uint addr)
 SYSCALL1(_SysAllocate, SYS_ALLOCATE)   // uint64_t _SysAllocate(uint addr)
+SYSCALL3(SysSetMemFlags, SYS_SETFLAGS) // uint32_t SysSetMemFlags(uint addr, uint flags, uint mask)
 // VFS System calls
 SYSCALL2(open, SYS_OPEN)       // char*, int
 SYSCALL3(reopen, SYS_REOPEN)   // int, char*, int
index 6f67811..eb9b83b 100644 (file)
@@ -39,7 +39,7 @@ extern void   *DoRelocate(void *Base, char **envp, const char *Filename);
 // === Library/Symbol Manipulation ==
 extern void    *LoadLibrary(const char *Filename, const char *SearchDir, char **envp);
 extern void    AddLoaded(const char *File, void *base);
-extern void    *GetSymbol(const char *name, size_t *size);
+extern int     GetSymbol(const char *Name, void **Value, size_t *size);
 extern int     GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
 
 // === Library Functions ===
index dc9dca3..9a2668a 100644 (file)
@@ -9,6 +9,10 @@
 # define DEBUG 0
 #endif
 
+#ifndef PAGE_SIZE
+# define PAGE_SIZE     4096
+#endif
+
 #include "common.h"
 #include <stdint.h>
 #include "elf32.h"
@@ -35,8 +39,8 @@ void  *ElfRelocate(void *Base, char **envp, const char *Filename);
  int   ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
 void   *Elf32Relocate(void *Base, char **envp, const char *Filename);
  int   Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
-void   elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
-void   elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int   elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int   elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
 #ifdef SUPPORT_ELF64
 void   *Elf64Relocate(void *Base, char **envp, const char *Filename);
  int   Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
@@ -87,26 +91,28 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size)
        }
 }
 
-void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type,
+               int bRela, const char *Sym, intptr_t iBaseDiff)
 {
-       intptr_t        val;
+       void    *symval;
        switch( type )
        {
        // Standard 32 Bit Relocation (S+A)
        case R_386_32:
-               val = (intptr_t) GetSymbol(Sym, NULL);
-               DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')",
-                               ptr, val, Sym);
-               *ptr = val + addend;
+               if( !GetSymbol(Sym, &symval, NULL) )
+                       return 1;
+               DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')",
+                               ptr, symval, Sym);
+               *ptr = (intptr_t)symval + addend;
                break;
                
        // 32 Bit Relocation wrt. Offset (S+A-P)
        case R_386_PC32:
                DEBUGS(" elf_doRelocate: '%s'", Sym);
-               val = (intptr_t) GetSymbol(Sym, NULL);
-               DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x",
-                       ptr, *ptr, val, (intptr_t)ptr );
-               *ptr = val + addend - (intptr_t)ptr;
+               if( !GetSymbol(Sym, &symval, NULL) )    return 1;
+               DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x",
+                       ptr, *ptr, symval, (intptr_t)ptr );
+               *ptr = (intptr_t)symval + addend - (intptr_t)ptr;
                //*ptr = val + addend - ((Uint)ptr - iBaseDiff);
                break;
 
@@ -114,9 +120,9 @@ void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t
        case R_386_GLOB_DAT:
        case R_386_JMP_SLOT:
                DEBUGS(" elf_doRelocate: '%s'", Sym);
-               val = (intptr_t) GetSymbol( Sym, NULL );
-               DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val);
-               *ptr = val;
+               if( !GetSymbol(Sym, &symval, NULL) )    return 1;
+               DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval);
+               *ptr = (intptr_t)symval;
                break;
 
        // Base Address (B+A)
@@ -127,18 +133,19 @@ void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t
 
        case R_386_COPY: {
                size_t  size;
-               void    *src = GetSymbol(Sym, &size);
-               DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, src, size);
-               memcpy(ptr, src, size);
+               if( !GetSymbol(Sym, &symval, &size) )   return 1;
+               DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size);
+               memcpy(ptr, symval, size);
                break; }
 
        default:
                SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
-               break;
+               return 2;
        }
+       return 0;
 }
 
-void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
 {
        uint32_t        val;
        switch(type)
@@ -146,32 +153,35 @@ void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t
        // (S + A) | T
        case R_ARM_ABS32:
                DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend);
-               val = (intptr_t)GetSymbol(Sym, NULL);
+               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
                *ptr = val + addend;
                break;
        case R_ARM_GLOB_DAT:
                DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend);
-               val = (intptr_t)GetSymbol(Sym, NULL);
+               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
                *ptr = val + addend;
                break;
        case R_ARM_JUMP_SLOT:
                if(!bRela)      addend = 0;
                DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend);
-               val = (intptr_t)GetSymbol(Sym, NULL);
+               if( !GetSymbol(Sym, (void**)&val, NULL) )       return 1;
                *ptr = val + addend;
                break;
        // Copy
        case R_ARM_COPY: {
                size_t  size;
-               void    *src = GetSymbol(Sym, &size);
+               void    *src;
+               if( !GetSymbol(Sym, &src, &size) )      return 1;
                DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size);
                memcpy(ptr, src, size);
                break; }
        // Delta between link and runtime locations + A
        case R_ARM_RELATIVE:
+               DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend);
                if(Sym[0] != '\0') {
                        // TODO: Get delta for a symbol
                        SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols");
+                       return 2;
                }
                else {
                        *ptr = iBaseDiff + addend;
@@ -179,8 +189,9 @@ void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t
                break;
        default:
                SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type);
-               break;
+               return 2;
        }
+       return 0;
 }
 
 void *Elf32Relocate(void *Base, char **envp, const char *Filename)
@@ -202,8 +213,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
        Elf32_Dyn       *dynamicTab = NULL;     // Dynamic Table Pointer
        char    *dynstrtab = NULL;      // .dynamic String Table
        Elf32_Sym       *dynsymtab;
-       void    (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
-       auto void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend);
+       int     (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
+       auto int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend);
        
        DEBUGS("ElfRelocate: (Base=0x%x)", Base);
        
@@ -236,7 +247,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
        
        // Adjust "Real" Base
        iBaseDiff = (intptr_t)Base - iRealBase;
-       
+
 //     hdr->entrypoint += iBaseDiff;   // Adjust Entrypoint
        
        // Check if a PT_DYNAMIC segement was found
@@ -244,7 +255,19 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
                return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
        }
-       
+
+       // Allow writing to read-only segments, just in case they need to be relocated
+       // - Will be reversed at the end of the function
+       for( i = 0; i < iSegmentCount; i ++ )
+       {
+               if(phtab[i].Type == PT_LOAD && phtab[i].Flags & PF_R ) {
+                       uintptr_t       addr = phtab[i].VAddr + iBaseDiff;
+                       uintptr_t       end = addr + phtab[i].MemSize;
+                       for( ; addr < end; addr += PAGE_SIZE )
+                               SysSetMemFlags(addr, 0, 1);     // Unset RO
+               }
+       }
+
        // Adjust Dynamic Table
        dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff );
        
@@ -340,12 +363,12 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
        
        DEBUGS(" elf_relocate: Beginning Relocation");
 
-       void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend)
+       int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend)
        {
                 int    type = ELF32_R_TYPE(r_info);
                 int    sym = ELF32_R_SYM(r_info);
                const char      *symname = dynstrtab + dynsymtab[sym].nameOfs;
-               do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff);
+               return do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff);
        }
 
        switch(hdr->machine)
@@ -358,11 +381,14 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                break;
        default:
                SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine);
+               // TODO: Chuck sad
                break;
        }
        
        DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm);
 
+        int    fail = 0;
+
        // Parse Relocation Entries
        if(rel && relSz)
        {
@@ -373,7 +399,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                {
                        //DEBUGS("  Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset);
                        ptr = (void*)(iBaseDiff + rel[i].r_offset);
-                       _doRelocate(rel[i].r_info, ptr, 0, *ptr);
+                       fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr);
                }
        }
        // Parse Relocation Entries
@@ -385,7 +411,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                for( i = 0; i < j; i++ )
                {
                        ptr = (void*)(iBaseDiff + rela[i].r_offset);
-                       _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
+                       fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
                }
        }
        
@@ -402,7 +428,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                        for(i=0;i<j;i++)
                        {
                                ptr = (void*)(iBaseDiff + pltRel[i].r_offset);
-                               _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
+                               fail |= _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
                        }
                }
                else
@@ -413,11 +439,27 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
                        for(i=0;i<j;i++)
                        {
                                ptr = (void*)(iRealBase + pltRela[i].r_offset);
-                               _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
+                               fail |= _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
                        }
                }
        }
-       
+
+       // Re-set readonly
+       for( i = 0; i < iSegmentCount; i ++ )
+       {
+               if(phtab[i].Type == PT_LOAD && phtab[i].Flags & PF_R ) {
+                       uintptr_t       addr = phtab[i].VAddr + iBaseDiff;
+                       uintptr_t       end = addr + phtab[i].MemSize;
+                       for( ; addr < end; addr += PAGE_SIZE )
+                               SysSetMemFlags(addr, 1, 1);     // Unset RO
+               }
+       }
+
+       if( fail ) {
+               DEBUGS("ElfRelocate: Failure");
+               return NULL;
+       }       
+
        DEBUGS("ElfRelocate: RETURN 0x%x to %p", hdr->entrypoint + iBaseDiff, __builtin_return_address(0));
        return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff );
 }
@@ -663,45 +705,51 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
        }
 
        // Relocation function
-       void _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
+       int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
        {
                 int    sym = ELF64_R_SYM(r_info);
                 int    type = ELF64_R_TYPE(r_info);
                const char      *symname = strtab + symtab[sym].st_name;
+               void    *symval;
                switch( type )
                {
                case R_X86_64_NONE:
                        break;
                case R_X86_64_64:
-                       *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL) + addend;
+                       if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+                       *(uint64_t*)ptr = (uintptr_t)symval + addend;
                        break;
                case R_X86_64_COPY: {
                        size_t  size;
-                       void    *symptr = GetSymbol(symname, &size);
-                       memcpy(ptr, symptr, size);
+                       if( !GetSymbol(symname, &symval, &size)  )      return 1;
+                       memcpy(ptr, symval, size);
                        } break;
                case R_X86_64_GLOB_DAT:
-                       *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+                       if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+                       *(uint64_t*)ptr = (uintptr_t)symval;
                        break;
                case R_X86_64_JUMP_SLOT:
-                       *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+                       if( !GetSymbol(symname, &symval, NULL)  )       return 1;
+                       *(uint64_t*)ptr = (uintptr_t)symval;
                        break;
                case R_X86_64_RELATIVE:
                        *(uint64_t*)ptr = (uintptr_t)Base + addend;
                        break;
                default:
                        SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type);
-                       break;
+                       return 2;
                }
+               return 0;
        }
 
+       int fail = 0;
        if( rel )
        {
                DEBUGS("rel_count = %i", rel_count);
                for( i = 0; i < rel_count; i ++ )
                {
                        uint64_t *ptr = (void *)(uintptr_t)( rel[i].r_offset + baseDiff );
-                       _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
+                       fail |= _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
                }
        }
 
@@ -711,7 +759,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                for( i = 0; i < rela_count; i ++ )
                {
                        uint64_t *ptr = (void *)(uintptr_t)( rela[i].r_offset + baseDiff );
-                       _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
+                       fail |= _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
                }
        }
 
@@ -724,7 +772,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                        for( i = 0; i < count; i ++ )
                        {
                                uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
-                               _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
+                               fail |= _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
                        }
                }
                else {
@@ -734,11 +782,16 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
                        for( i = 0; i < count; i ++ )
                        {
                                uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
-                               _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
+                               fail |= _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
                        }
                }
        }
 
+       if( fail ) {
+               DEBUGS("Elf64Relocate: Failure");
+               return NULL;
+       }
+
        {
        void *ret = (void *)(uintptr_t)(hdr->e_entry + baseDiff);
        DEBUGS("Elf64Relocate: Relocations done, return %p", ret);
index 5505479..88502b0 100644 (file)
@@ -90,5 +90,6 @@ extern int    SysGetMessage(pid_t *src, uint buflen, void *Data);
 // --- MEMORY ---
 uint64_t       _SysGetPhys(uint vaddr);
 uint64_t       _SysAllocate(uint vaddr);
+uint32_t       SysSetMemFlags(uint vaddr, uint32_t flags, uint32_t mask);
 
 #endif
index 3f8e674..f59caf2 100644 (file)
@@ -15,7 +15,6 @@
 
 // === PROTOTYPES ===
 void   *IsFileLoaded(const char *file);
- int   GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
 
 // === IMPORTS ===
 extern const struct {
@@ -88,6 +87,9 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
        
        // Load Symbols
        fEntry = DoRelocate( base, envp, filename );
+       if( !fEntry ) {
+               return 0;
+       }
        
        // Call Entrypoint
        DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
@@ -198,26 +200,31 @@ void Unload(void *Base)
  \fn Uint GetSymbol(const char *name)
  \brief Gets a symbol value from a loaded library
 */
-void *GetSymbol(const char *name, size_t *Size)
+int GetSymbol(const char *name, void **Value, size_t *Size)
 {
         int    i;
-       void    *ret;
        
        //SysDebug("ciNumLocalExports = %i", ciNumLocalExports);
        for(i=0;i<ciNumLocalExports;i++)
        {
-               if( strcmp(caLocalExports[i].Name, name) == 0 )
-                       return caLocalExports[i].Value;
+               if( strcmp(caLocalExports[i].Name, name) == 0 ) {
+                       *Value = caLocalExports[i].Value;
+                       if(Size)
+                               *Size = 0;
+                       return 1;
+               }
        }
        
        // Entry 0 is ld-acess, ignore it
        for(i = 1; i < MAX_LOADED_LIBRARIES; i ++)
        {
-               if(gLoadedLibraries[i].Base == 0)       break;
+               if(gLoadedLibraries[i].Base == 0)
+                       break;
                
                //SysDebug(" GetSymbol: Trying 0x%x, '%s'",
                //      gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
-               if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret, Size))       return ret;
+               if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, Value, Size))
+                       return 1;
        }
        SysDebug("GetSymbol: === Symbol '%s' not found ===", name);
        return 0;
index 3dfe1fb..fb3225b 100644 (file)
@@ -6,7 +6,7 @@
 CPPFLAGS += \r
 CFLAGS   += -Werror -Wextra\r
 ASFLAGS  +=\r
-LDFLAGS  += -soname libc.so -Map map.txt -lgcc\r
+LDFLAGS  += -soname libc.so -Map map.txt\r
 \r
 INCFILES := stdio.h stdlib.h\r
 \r

UCC git Repository :: git.ucc.asn.au