#include <mach-o/arm64/reloc.h>
#endif
+extern uint32_t kaslr_offsets_index;
+extern uint32_t kaslr_offsets_count;
+extern uint32_t *kaslr_offsets;
+
#define KXLD_TARGET_NONE (u_int) 0x0
#define KXLD_TARGET_VALUE (u_int) 0x1
#define KXLD_TARGET_SECTNUM (u_int) 0x2
reloc->pair_target_type = KXLD_TARGET_NONE;
}
}
- }
+ } // for...
}
-
rval = KERN_SUCCESS;
finish:
* 2) Don't reference N_ABS symbols
*******************************************************************************/
static u_int
-count_relocatable_relocs(const KXLDRelocator *relocator,
+count_relocatable_relocs(const KXLDRelocator *relocator,
const struct relocation_info *relocs, u_int nrelocs)
{
u_int num_nonpair_relocs = 0;
sym = kxld_symtab_get_symbol_by_index(relocator->symtab, reloc->target);
break;
case KXLD_TARGET_SECTNUM:
- if (data) {
- value = kxld_relocator_get_pointer_at_addr(relocator, data,
- reloc->address);
- sym = kxld_symtab_get_cxx_symbol_by_value(relocator->symtab, value);
- }
+ if (data) {
+ value = kxld_relocator_get_pointer_at_addr(relocator, data,
+ reloc->address);
+ sym = kxld_symtab_get_cxx_symbol_by_value(relocator->symtab, value);
+ }
break;
default:
sym = NULL;
/*******************************************************************************
*******************************************************************************/
u_long
-kxld_reloc_get_macho_data_size(const KXLDArray *locrelocs,
+kxld_reloc_get_macho_data_size(
+ const KXLDArray *locrelocs,
const KXLDArray *extrelocs)
{
u_long rval = 0;
data_size = kxld_reloc_get_macho_data_size(locrelocs, extrelocs);
require_action((*data_offset + data_size) <= size, finish, rval=KERN_FAILURE);
-
+
start = dst = (struct relocation_info *) ((void *) (buf + *data_offset));
+ if (kaslr_offsets == NULL) {
+ kaslr_offsets_index = 0;
+ kaslr_offsets_count = locrelocs->nitems + extrelocs->nitems;
+ kaslr_offsets = (uint32_t *)malloc(kaslr_offsets_count * sizeof(*kaslr_offsets));
+ bzero(kaslr_offsets, kaslr_offsets_count * sizeof(*kaslr_offsets));
+ }
+
+ // copies the reloc data into the __LINKEDIT segment
+ // data_offset is the new value for locreloff
rval = export_macho_for_array(relocator, locrelocs, &dst);
require_noerr(rval, finish);
require_noerr(rval, finish);
count = dst - start;
-
+
memset(dysymtabhdr, 0, sizeof(*dysymtabhdr));
dysymtabhdr->cmd = LC_DYSYMTAB;
dysymtabhdr->cmdsize = (uint32_t) sizeof(*dysymtabhdr);
dysymtabhdr->nlocrel = (uint32_t) count;
*data_offset += count * sizeof(struct relocation_info);
-
+
+#if SPLIT_KEXTS_DEBUG
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "%p >>> Start of dysymtabhdr (size %lu) <%s> ",
+ (void *) dysymtabhdr,
+ sizeof(*dysymtabhdr),
+ __func__);
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "%p <<< End of dysymtabhdr <%s> ",
+ (void *) ((u_char *)dysymtabhdr + sizeof(*dysymtabhdr)),
+ __func__);
+
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "dysymtabhdr at %p: cmdsize %u indirectsymoff %u nindirectsyms %u extreloff %u nextrel %u locreloff %u nlocrel %u <%s>",
+ (void *) dysymtabhdr,
+ dysymtabhdr->cmdsize,
+ dysymtabhdr->indirectsymoff,
+ dysymtabhdr->nindirectsyms,
+ dysymtabhdr->extreloff,
+ dysymtabhdr->nextrel,
+ dysymtabhdr->locreloff,
+ dysymtabhdr->nlocrel,
+ __func__);
+#endif
+
rval = KERN_SUCCESS;
finish:
- return rval;
+ return rval;
}
#endif /* KXLD_PIC_KEXTS */
check(relocator);
- addr = *(const uint32_t *) ((void *) (data + offset));
+ addr = *(const uint32_t *) ((const void *) (data + offset));
#if !KERNEL
if (relocator->swap) {
addr = OSSwapInt32(addr);
check(relocator);
- addr = *(const uint64_t *) ((void *) (data + offset));
+ addr = *(const uint64_t *) ((const void *) (data + offset));
+
#if !KERNEL
if (relocator->swap) {
addr = OSSwapInt64(addr);
*******************************************************************************/
kern_return_t
kxld_relocator_process_table_reloc(KXLDRelocator *relocator,
- const KXLDReloc *reloc, const KXLDSeg *seg, kxld_addr_t link_addr)
+ const KXLDReloc *reloc,
+ const KXLDSeg *seg,
+ kxld_addr_t link_addr)
{
kern_return_t rval = KERN_FAILURE;
u_char *instruction = NULL;
check(relocator);
check(reloc);
- /* Find the instruction */
+ /* Find the instruction in original kext file we are trying to link */
offset = (u_long)(seg->fileoff + (reloc->address - seg->base_addr));
instruction = relocator->file + offset;
base_pc = reloc->address;
link_pc = base_pc + link_addr;
+ if (kxld_seg_is_split_seg(seg)) {
+ // link_pc for split segment special case, do not add in the base_pc
+ link_pc = link_addr;
+ }
/* Relocate */
- rval = relocator->process_reloc(relocator, instruction, reloc->length,
+ rval = relocator->process_reloc(relocator, instruction, reloc->length,
reloc->pcrel, base_pc, link_pc, link_addr, reloc->reloc_type, target,
pair_target, relocator->swap);
require_noerr(rval, finish);
struct relocation_info *dst = NULL;
struct scattered_relocation_info *scatdst = NULL;
u_int i = 0;
-
+
dst = *dstp;
for (i = 0; i < relocs->nitems; ++i) {
switch (reloc->target_type) {
case KXLD_TARGET_LOOKUP:
+ if (kaslr_offsets) {
+ if (kaslr_offsets_index >= kaslr_offsets_count) {
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "kaslr_offsets overflow %d > %d <%s> ",
+ kaslr_offsets_index, kaslr_offsets_count,
+ __func__);
+ abort();
+ }
+ // reloc->address is really an offset from the start of the kext
+ *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
+ }
scatdst->r_address = reloc->address;
scatdst->r_pcrel = reloc->pcrel;
scatdst->r_length = reloc->length;
scatdst->r_scattered = 1;
break;
case KXLD_TARGET_SECTNUM:
+ if (kaslr_offsets) {
+ if (kaslr_offsets_index >= kaslr_offsets_count) {
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "kaslr_offsets overflow <%s> ", __func__);
+ abort();
+ }
+ // reloc->address is really an offset from the start of the kext
+ *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
+ }
dst->r_address = reloc->address;
dst->r_pcrel = reloc->pcrel;
dst->r_length = reloc->length;
/* Assume that everything will be slid together; otherwise,
* there is no sensible value for the section number.
*/
+ if (kaslr_offsets) {
+ if (kaslr_offsets_index >= kaslr_offsets_count) {
+ kxld_log(kKxldLogLinking, kKxldLogErr,
+ "kaslr_offsets overflow <%s> ", __func__);
+ abort();
+ }
+ // reloc->address is really an offset from the start of the kext
+ *(kaslr_offsets + kaslr_offsets_index++) = reloc->address;
+ }
dst->r_address = reloc->address;
dst->r_pcrel = reloc->pcrel;
dst->r_length = reloc->length;
#if !KERNEL
if (swap) instr32 = OSSwapInt32(instr32);
#endif
-
+
*instr32p = instr32;
} else {
instr64p = (uint64_t *) ((void *) instruction);
#if !KERNEL
if (swap) instr64 = OSSwapInt64(instr64);
#endif
-
*instr64p = instr64;
}
#if !KERNEL
if (swap) instr32 = OSSwapInt32(instr32);
#endif
-
+
*instr32p = instr32;
} else { /* length == 3 */
uint64_t *instr64p = (uint64_t *) (void *) instruction;
#if !KERNEL
if (swap) instr64 = OSSwapInt64(instr64);
#endif
-
+
*instr64p = instr64;
}
return rval;
}
+
#endif /* KXLD_USER_OR_ARM64 */