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.
14 #include <l4/util/elf.h>
15 #include <l4/libloader/adjust_stack>
22 struct Prog_start_info
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;
30 l4_umword_t ldr_flags;
37 l4_addr_t utcbs_start;
38 unsigned char utcbs_log2size;
48 template< typename STACK, typename PROG_INFO = Prog_start_info>
53 typedef PROG_INFO Prog_info;
62 Arg_array() : a0(0) {}
63 int push(Base_app_model *am, bool basename);
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; }
75 void extra_elf_auxv() {}
79 envp.push(this, false);
84 l4_umword_t argc = argv.push(this, false);
89 template< typename STACK, typename PROG_INFO >
91 Base_app_model<STACK, PROG_INFO>::Arg_array::push(Base_app_model *am, bool basename)
93 // push array terminator
94 am->stack()->push(l4_umword_t(0));
100 if (basename && al == a0)
102 // just use the basename for ARGV[0]
105 for (; al >= a0 && *al != '/'; --al)
111 am->stack()->push_local_ptr(al);
114 // scan for previous argument, remember the stack is top down
115 for (; al < a0 && *al; ++al)
125 template< typename App_model_, typename Dbg_ >
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;
134 void launch(App_model *model, Const_dataspace bin, Dbg_ const &dbg);
136 void launch(App_model *model, char const *prog, Dbg_ const &dbg)
138 typename App_model::Const_dataspace bin = model->open_file(prog);
139 launch(model, bin, dbg);
142 template< typename App_task, typename Prog >
143 void launch(App_task task, Prog prog, Const_dataspace bin, Dbg_ const &dbg)
145 typedef App_model Am;
147 launch(&am, bin, dbg);
150 template< typename App_task, typename Prog >
151 void launch(App_task task, Prog prog, char const *bin, Dbg_ const &dbg)
153 typedef App_model Am;
155 launch(&am, bin, dbg);
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;
163 template< typename App_model_, typename Dbg_ >
165 Loader<App_model_, Dbg_>::launch(App_model *am, Const_dataspace bin, Dbg_ const &dbg)
167 typedef App_model Am;
168 typedef typename Am::Dataspace Dataspace;
170 read_infos(am, bin, dbg);
171 Dataspace app_stack = am->alloc_app_stack();
174 // put env strings on stack
177 Stack &stack = *am->stack();
178 stack.align(sizeof(l4_umword_t));
180 void const *l4aux_ptr;
182 // load the program into memory, prepare all the VMAs
183 // and stuff on the application stack
186 am->prog_attach_stack(app_stack);
187 am->prog_reserve_utcb_area();
188 am->prog_attach_kip();
190 l4aux_ptr = am->generate_l4aux(am->argv.a0);
193 L4Re::Env *env = am->add_env();
195 stack.align(sizeof(l4_umword_t));
197 const char *stack_before_auxv = stack.ptr();
200 stack.push(l4_umword_t(0));
201 stack.push(l4_umword_t(0));
204 stack.push_local_ptr(env);
205 stack.push(l4_umword_t(0xF1));
209 stack.push_local_ptr(l4aux_ptr);
210 stack.push(l4_umword_t(0xF0));
213 am->extra_elf_auxv();
215 stack.push(l4_umword_t(L4_PAGESIZE));
216 stack.push(l4_umword_t(AT_PAGESZ));
218 stack.push(l4_umword_t(0));
219 stack.push(l4_umword_t(AT_UID));
221 stack.push(l4_umword_t(0));
222 stack.push(l4_umword_t(AT_EUID));
224 stack.push(l4_umword_t(0));
225 stack.push(l4_umword_t(AT_GID));
227 stack.push(l4_umword_t(0));
228 stack.push(l4_umword_t(AT_EGID));
230 if (am->prog_info()->dyn_phdrs)
232 stack.push(l4_umword_t(am->prog_info()->dyn_phdrs));
233 stack.push(l4_umword_t(AT_PHDR));
235 stack.push(l4_umword_t(am->prog_info()->dyn_num_phdrs));
236 stack.push(l4_umword_t(AT_PHNUM));
239 if (am->prog_info()->dyn_exec_entry)
241 stack.push(l4_umword_t(am->prog_info()->dyn_exec_entry));
242 stack.push(l4_umword_t(AT_ENTRY));
244 stack.push(l4_umword_t(am->prog_info()->dyn_interp_base));
245 stack.push(l4_umword_t(AT_BASE));
251 const char *p = stack.ptr();
253 stack.ptr(adjust_sp((char *)p, &offs));
255 if (p != stack.ptr() + offs)
256 memmove((char *)stack.ptr() + offs, p, stack_before_auxv - p);
258 // the stack is now ready for the app