Author: kib
Date: Thu Oct  8 16:58:01 2015
New Revision: 289035
URL: https://svnweb.freebsd.org/changeset/base/289035

Log:
  Implement in-kernel relocator for the arm64 module linker.
  
  It is decided to go with the shared object file format for modules on
  arm64, due to the Aarch64 instruction set details.  Combination of the
  signed 28-bit offset in the branch instructions encoding together with
  the supported memory model of compilers makes the relocatable object
  support impossible or at least too hard.
  
  Reviewed by:  andrew, emaste
  Tested by:    andrew (on real hardware)
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D3796

Modified:
  head/sys/arm64/arm64/elf_machdep.c

Modified: head/sys/arm64/arm64/elf_machdep.c
==============================================================================
--- head/sys/arm64/arm64/elf_machdep.c  Thu Oct  8 16:46:11 2015        
(r289034)
+++ head/sys/arm64/arm64/elf_machdep.c  Thu Oct  8 16:58:01 2015        
(r289035)
@@ -1,11 +1,14 @@
 /*-
- * Copyright (c) 2014 The FreeBSD Foundation.
+ * Copyright (c) 2014, 2015 The FreeBSD Foundation.
  * Copyright (c) 2014 Andrew Turner.
  * All rights reserved.
  *
  * This software was developed by Andrew Turner under
  * sponsorship from the FreeBSD Foundation.
  *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -124,12 +127,66 @@ elf64_dump_thread(struct thread *td __un
 
 }
 
+static int
+elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
+    int type, int local, elf_lookup_fn lookup)
+{
+       Elf_Addr *where, addr, addend;
+       Elf_Word rtype, symidx;
+       const Elf_Rel *rel;
+       const Elf_Rela *rela;
+       int error;
+
+       switch (type) {
+       case ELF_RELOC_REL:
+               rel = (const Elf_Rel *)data;
+               where = (Elf_Addr *) (relocbase + rel->r_offset);
+               addend = *where;
+               rtype = ELF_R_TYPE(rel->r_info);
+               symidx = ELF_R_SYM(rel->r_info);
+               break;
+       case ELF_RELOC_RELA:
+               rela = (const Elf_Rela *)data;
+               where = (Elf_Addr *) (relocbase + rela->r_offset);
+               addend = rela->r_addend;
+               rtype = ELF_R_TYPE(rela->r_info);
+               symidx = ELF_R_SYM(rela->r_info);
+               break;
+       default:
+               panic("unknown reloc type %d\n", type);
+       }
+
+       if (local) {
+               if (rtype == R_AARCH64_RELATIVE)
+                       *where = elf_relocaddr(lf, relocbase + addend);
+               return (0);
+       }
+
+       switch (rtype) {
+       case R_AARCH64_NONE:
+       case R_AARCH64_RELATIVE:
+               break;
+       case R_AARCH64_ABS64:
+       case R_AARCH64_GLOB_DAT:
+       case R_AARCH64_JUMP_SLOT:
+               error = lookup(lf, symidx, 1, &addr);
+               if (error != 0)
+                       return (-1);
+               *where = addr + addend;
+               break;
+       default:
+               printf("kldload: unexpected relocation type %d\n", rtype);
+               return (-1);
+       }
+       return (0);
+}
+
 int
 elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
-    int type, elf_lookup_fn lookup __unused)
+    int type, elf_lookup_fn lookup)
 {
 
-       panic("ARM64TODO: elf_reloc_local");
+       return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
 }
 
 /* Process one elf relocation with addend. */
@@ -138,13 +195,15 @@ elf_reloc(linker_file_t lf, Elf_Addr rel
     elf_lookup_fn lookup)
 {
 
-       panic("ARM64TODO: elf_reloc");
+       return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
 }
 
 int
-elf_cpu_load_file(linker_file_t lf __unused)
+elf_cpu_load_file(linker_file_t lf)
 {
 
+       if (lf->id != 1)
+               cpu_icache_sync_range((vm_offset_t)lf->address, lf->size);
        return (0);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to