1 #include "mm_aspace.h"
2 #include <rtthread.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <elf.h>
6 #ifdef ARCH_MM_MMU
7 #include <mmu.h>
8 #include <page.h>
9 #endif
10 
11 typedef struct
12 {
13     Elf64_Word    st_name;
14     Elf64_Addr    st_value;
15     Elf64_Word    st_size;
16     unsigned char st_info;
17     unsigned char st_other;
18     Elf64_Half    st_shndx;
19 } Elf64_sym;
20 
21 #ifdef ARCH_MM_MMU
arch_elf_reloc(rt_aspace_t aspace,void * text_start,void * rel_dyn_start,size_t rel_dyn_size,void * got_start,size_t got_size,Elf64_sym * dynsym)22 void arch_elf_reloc(rt_aspace_t aspace, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
23 {
24     size_t rel_off;
25     void  *addr;
26 
27     if (rel_dyn_size && !dynsym)
28     {
29         return;
30     }
31     for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8)
32     {
33         uint32_t v1, v2;
34 
35         addr = rt_hw_mmu_v2p(aspace, (void *)(((rt_size_t)rel_dyn_start) + rel_off));
36         memcpy(&v1, addr, 4);
37         addr = rt_hw_mmu_v2p(aspace, (void *)(((rt_size_t)rel_dyn_start) + rel_off + 4));
38         memcpy(&v2, addr, 4);
39 
40         addr = rt_hw_mmu_v2p(aspace, (void *)((rt_size_t)text_start + v1));
41         if ((v2 & 0xff) == R_ARM_RELATIVE)
42         {
43             *(rt_size_t *)addr += (rt_size_t)text_start;
44         }
45         else if ((v2 & 0xff) == R_ARM_ABS32)
46         {
47             uint32_t t;
48             t = (v2 >> 8);
49             if (t) /* 0 is UDF */
50             {
51                 *(rt_size_t *)addr = (((rt_size_t)text_start) + dynsym[t].st_value);
52             }
53         }
54     }
55     /* modify got */
56     if (got_size)
57     {
58         uint32_t *got_item = (uint32_t *)got_start;
59 
60         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
61         {
62             addr                = rt_hw_mmu_v2p(aspace, got_item);
63             *(rt_size_t *)addr += (rt_size_t)text_start;
64         }
65     }
66 }
67 #else
68 
arch_elf_reloc(void * text_start,void * rel_dyn_start,size_t rel_dyn_size,void * got_start,size_t got_size,Elf64_sym * dynsym)69 void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym)
70 {
71     size_t rel_off;
72 
73     if (rel_dyn_size && !dynsym)
74     {
75         return;
76     }
77     for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8)
78     {
79         uint32_t v1, v2;
80 
81         memcpy(&v1, ((rt_uint8_t *)rel_dyn_start) + rel_off, 4);
82         memcpy(&v2, ((rt_uint8_t *)rel_dyn_start) + rel_off + 4, 4);
83 
84         if ((v2 & 0xff) == R_ARM_RELATIVE)
85         {
86             *(uint32_t *)(((rt_size_t)text_start) + v1) += (uint32_t)text_start;
87         }
88         else if ((v2 & 0xff) == R_ARM_ABS32)
89         {
90             uint32_t t;
91             t = (v2 >> 8);
92             if (t) /* 0 is UDF */
93             {
94                 *(uint32_t *)(((rt_size_t)text_start) + v1) = (uint32_t)(((rt_size_t)text_start) + dynsym[t].st_value);
95             }
96         }
97     }
98     /* modify got */
99     if (got_size)
100     {
101         uint32_t *got_item = (uint32_t *)got_start;
102 
103         for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++)
104         {
105             *got_item += (uint32_t)text_start;
106         }
107     }
108 }
109 #endif
110