OSDN Git Service

67f9ff6a351cb2ecbaeab4eae3be0cd80b0daef4
[uclinux-h8/uClibc.git] / ldso / ldso / bfin / dl-inlines.h
1 /* Copyright (C) 2003, 2004 Red Hat, Inc.
2  * Contributed by Alexandre Oliva <aoliva@redhat.com>
3  * Copyright (C) 2006-2011 Analog Devices, Inc.
4  *
5  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
6  */
7
8 #include <bfin_sram.h>
9
10 #define __dl_loadaddr_unmap __dl_loadaddr_unmap
11
12 #include "../fdpic/dl-inlines.h"
13
14 void
15 __dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr,
16                      struct funcdesc_ht *funcdesc_ht)
17 {
18   int i;
19
20   for (i = 0; i < loadaddr.map->nsegs; i++)
21     {
22       struct elf32_fdpic_loadseg *segdata;
23       ssize_t offs;
24       segdata = loadaddr.map->segs + i;
25
26       /* FIXME:
27         A more cleaner way is to add type for struct elf32_fdpic_loadseg,
28         and release the memory according to the type.
29         Currently, we hardcode the memory address of L1 SRAM.  */
30       if ((segdata->addr & 0xff800000) == 0xff800000)
31        {
32          _dl_sram_free ((void *)segdata->addr);
33          continue;
34        }
35
36       offs = (segdata->p_vaddr & ADDR_ALIGN);
37       _dl_munmap ((void*)segdata->addr - offs,
38                   segdata->p_memsz + offs);
39     }
40   /* _dl_unmap is only called for dlopen()ed libraries, for which
41      calling free() is safe, or before we've completed the initial
42      relocation, in which case calling free() is probably pointless,
43      but still safe.  */
44   _dl_free (loadaddr.map);
45   if (funcdesc_ht)
46     htab_delete (funcdesc_ht);
47 }
48
49 static __always_inline int
50 __dl_is_special_segment (Elf32_Ehdr *epnt,
51                          Elf32_Phdr *ppnt)
52 {
53   if (ppnt->p_type != PT_LOAD)
54     return 0;
55
56   if ((epnt->e_flags & EF_BFIN_CODE_IN_L1)
57       && !(ppnt->p_flags & PF_W)
58       && (ppnt->p_flags & PF_X))
59     return 1;
60
61   if ((epnt->e_flags & EF_BFIN_DATA_IN_L1)
62       && (ppnt->p_flags & PF_W)
63       && !(ppnt->p_flags & PF_X))
64     return 1;
65
66   /* 0xfeb00000, 0xfec00000, 0xff700000, 0xff800000, 0xff900000,
67      and 0xffa00000 are also used in GNU ld and linux kernel.
68      They need to be kept synchronized.  */
69   if (ppnt->p_vaddr == 0xff700000
70       || ppnt->p_vaddr == 0xff800000
71       || ppnt->p_vaddr == 0xff900000
72       || ppnt->p_vaddr == 0xffa00000
73       || ppnt->p_vaddr == 0xfeb00000
74       || ppnt->p_vaddr == 0xfec00000)
75     return 1;
76
77   return 0;
78 }
79
80 static __always_inline char *
81 __dl_map_segment (Elf32_Ehdr *epnt,
82                   Elf32_Phdr *ppnt,
83                   int infile,
84                   int flags)
85 {
86   char *status, *tryaddr, *addr;
87   size_t size;
88
89   if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000)
90       && !(ppnt->p_flags & PF_W)
91       && (ppnt->p_flags & PF_X)) {
92     status = (char *) _dl_mmap
93       (tryaddr = 0,
94        size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz,
95        LXFLAGS(ppnt->p_flags),
96        flags | MAP_EXECUTABLE | MAP_DENYWRITE,
97        infile, ppnt->p_offset & OFFS_ALIGN);
98     if (_dl_mmap_check_error(status)
99         || (tryaddr && tryaddr != status))
100       return NULL;
101     addr = (char *) _dl_sram_alloc (ppnt->p_filesz, L1_INST_SRAM);
102     if (addr != NULL)
103       _dl_dma_memcpy (addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz);
104     _dl_munmap (status, size);
105     if (addr == NULL)
106       _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__);
107     return addr;
108   }
109
110   if (((epnt->e_flags & EF_BFIN_DATA_IN_L1)
111        || ppnt->p_vaddr == 0xff700000
112        || ppnt->p_vaddr == 0xff800000
113        || ppnt->p_vaddr == 0xff900000)
114       && (ppnt->p_flags & PF_W)
115       && !(ppnt->p_flags & PF_X)) {
116     if (ppnt->p_vaddr == 0xff800000)
117       addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_A_SRAM);
118     else if (ppnt->p_vaddr == 0xff900000)
119       addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_B_SRAM);
120     else
121       addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_SRAM);
122     if (addr == NULL) {
123       _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__);
124     } else {
125       if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
126         _dl_sram_free (addr);
127         return NULL;
128       }
129       if (ppnt->p_filesz < ppnt->p_memsz)
130        _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
131     }
132     return addr;
133   }
134
135   if (ppnt->p_vaddr == 0xfeb00000
136       || ppnt->p_vaddr == 0xfec00000) {
137     addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L2_SRAM);
138     if (addr == NULL) {
139       _dl_dprintf(2, "%s:%i: L2 allocation failed\n", _dl_progname, __LINE__);
140     } else {
141       if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
142         _dl_sram_free (addr);
143         return NULL;
144       }
145       if (ppnt->p_filesz < ppnt->p_memsz)
146        _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
147     }
148     return addr;
149   }
150
151   return 0;
152 }