]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libloader/include/loader
update
[l4.git] / l4 / pkg / libloader / include / loader
1 // vi:ft=cpp
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  *               Alexander Warg <warg@os.inf.tu-dresden.de>
5  *     economic rights: Technische Universität Dresden (Germany)
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU Lesser General Public License 2.1.
8  * Please see the COPYING-LGPL-2.1 file for details.
9  */
10
11 #pragma once
12
13 #include <l4/re/env>
14 #include <l4/util/elf.h>
15 #include <l4/libloader/adjust_stack>
16
17 #include <cstring>
18
19 namespace Ldr {
20
21
22 struct Prog_start_info
23 {
24   l4_umword_t dyn_exec_entry;
25   l4_umword_t dyn_phdrs;
26   l4_umword_t dyn_num_phdrs;
27   l4_umword_t dyn_interp_base;
28
29
30   l4_umword_t ldr_flags;
31   l4_umword_t l4re_dbg;
32
33   l4_addr_t entry;
34   l4_addr_t kip;
35   l4_addr_t stack_addr;
36   l4_size_t stack_size;
37   l4_addr_t utcbs_start;
38   unsigned char utcbs_log2size;
39
40   l4_fpage_t parent;
41   l4_fpage_t mem_alloc;
42   l4_fpage_t scheduler;
43   l4_fpage_t rm;
44   l4_fpage_t log;
45   l4_fpage_t factory;
46 };
47
48 template< typename STACK, typename PROG_INFO = Prog_start_info>
49 class Base_app_model
50 {
51 public:
52   typedef STACK Stack;
53   typedef PROG_INFO Prog_info;
54
55 protected:
56   Stack _stack;
57   Prog_info _info;
58
59   struct Arg_array
60   {
61     char const *a0, *al;
62     Arg_array() : a0(0) {}
63     int push(Base_app_model *am, bool basename);
64   };
65
66 public:
67   Arg_array argv;
68   Arg_array envp;
69
70   Stack *stack() { return &_stack; }
71   Stack const *stack() const { return &_stack; }
72   Prog_info *prog_info() { return &_info; }
73   Prog_info const *prog_info() const { return &_info; }
74
75   void extra_elf_auxv() {}
76
77   void push_envp()
78   {
79     envp.push(this, false);
80   }
81
82   void push_argv()
83   {
84     l4_umword_t argc = argv.push(this, false);
85     _stack.push(argc);
86   }
87 };
88
89 template< typename STACK, typename PROG_INFO >
90 int
91 Base_app_model<STACK, PROG_INFO>::Arg_array::push(Base_app_model *am, bool basename)
92 {
93   // push array terminator
94   am->stack()->push(l4_umword_t(0));
95   l4_umword_t argc = 0;
96   if (a0)
97     {
98       do
99         {
100           if (basename && al == a0)
101             {
102               // just use the basename for ARGV[0]
103               for (; *al; ++al)
104                 ;
105               for (; al >= a0 && *al != '/'; --al)
106                 ;
107
108               if (*al == '/')
109                 ++al;
110             }
111           am->stack()->push_local_ptr(al);
112           ++argc;
113
114           // scan for previous argument, remember the stack is top down
115           for (; al < a0 && *al; ++al)
116             ;
117
118           ++al;
119         }
120       while (al <= a0);
121     }
122   return argc;
123 }
124
125 template< typename App_model_, typename Dbg_ >
126 class Loader
127 {
128 public:
129   typedef Dbg_ Dbg_log;
130   typedef App_model_ App_model;
131   typedef typename App_model::Const_dataspace Const_dataspace;
132   typedef typename App_model::Stack Stack;
133
134   void launch(App_model *model, Const_dataspace bin, Dbg_ const &dbg);
135
136   void launch(App_model *model, char const *prog, Dbg_ const &dbg)
137   {
138     typename App_model::Const_dataspace bin = model->open_file(prog);
139     launch(model, bin, dbg);
140   }
141
142   template< typename App_task, typename Prog >
143   void launch(App_task task, Prog prog, Const_dataspace bin, Dbg_ const &dbg)
144   {
145     typedef App_model Am;
146     Am am(task, prog);
147     launch(&am, bin, dbg);
148   }
149
150   template< typename App_task, typename Prog >
151   void launch(App_task task, Prog prog, char const *bin, Dbg_ const &dbg)
152   {
153     typedef App_model Am;
154     Am am(task, prog);
155     launch(&am, bin, dbg);
156   }
157
158   virtual void read_infos(App_model *, Const_dataspace bin, Dbg_log const &ldr) = 0;
159   virtual void load(App_model *, Const_dataspace bin, Dbg_log const &ldr) = 0;
160   virtual  ~Loader() {}
161 };
162
163 template< typename App_model_, typename Dbg_ >
164 void
165 Loader<App_model_, Dbg_>::launch(App_model *am, Const_dataspace bin, Dbg_ const &dbg)
166 {
167   typedef App_model Am;
168   typedef typename Am::Dataspace Dataspace;
169
170   read_infos(am, bin, dbg);
171   Dataspace app_stack = am->alloc_app_stack();
172
173   // put args on stack
174   // put env strings on stack
175   am->init_prog();
176
177   Stack &stack = *am->stack();
178   stack.align(sizeof(l4_umword_t));
179
180   void const *l4aux_ptr;
181     {
182       // load the program into memory, prepare all the VMAs
183       // and stuff on the application stack
184       load(am, bin, dbg);
185
186       am->prog_attach_stack(app_stack);
187       am->prog_reserve_utcb_area();
188       am->prog_attach_kip();
189
190       l4aux_ptr = am->generate_l4aux(am->argv.a0);
191     }
192
193   L4Re::Env *env = am->add_env();
194
195   stack.align(sizeof(l4_umword_t));
196
197   const char *stack_before_auxv = stack.ptr();
198
199   // AUXV NULL
200   stack.push(l4_umword_t(0));
201   stack.push(l4_umword_t(0));
202
203   // L4Re Env Pointer
204   stack.push_local_ptr(env);
205   stack.push(l4_umword_t(0xF1));
206
207   if (l4aux_ptr)
208     {
209       stack.push_local_ptr(l4aux_ptr);
210       stack.push(l4_umword_t(0xF0));
211     }
212
213   am->extra_elf_auxv();
214
215   stack.push(l4_umword_t(L4_PAGESIZE));
216   stack.push(l4_umword_t(AT_PAGESZ));
217
218   stack.push(l4_umword_t(0));
219   stack.push(l4_umword_t(AT_UID));
220
221   stack.push(l4_umword_t(0));
222   stack.push(l4_umword_t(AT_EUID));
223
224   stack.push(l4_umword_t(0));
225   stack.push(l4_umword_t(AT_GID));
226
227   stack.push(l4_umword_t(0));
228   stack.push(l4_umword_t(AT_EGID));
229
230   if (am->prog_info()->dyn_phdrs)
231     {
232       stack.push(l4_umword_t(am->prog_info()->dyn_phdrs));
233       stack.push(l4_umword_t(AT_PHDR));
234
235       stack.push(l4_umword_t(am->prog_info()->dyn_num_phdrs));
236       stack.push(l4_umword_t(AT_PHNUM));
237     }
238
239   if (am->prog_info()->dyn_exec_entry)
240     {
241       stack.push(l4_umword_t(am->prog_info()->dyn_exec_entry));
242       stack.push(l4_umword_t(AT_ENTRY));
243
244       stack.push(l4_umword_t(am->prog_info()->dyn_interp_base));
245       stack.push(l4_umword_t(AT_BASE));
246     }
247
248   am->push_envp();
249   am->push_argv();
250
251   const char *p = stack.ptr();
252   l4_umword_t offs;
253   stack.ptr(adjust_sp((char *)p, &offs));
254
255   if (p != stack.ptr() + offs)
256     memmove((char *)stack.ptr() + offs, p, stack_before_auxv - p);
257
258   // the stack is now ready for the app
259   am->start_prog(env);
260 }
261
262 }