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.
13 #include <l4/re/elf_aux.h>
14 #include <l4/util/elf.h>
15 #include <l4/sys/types.h>
16 #include <l4/re/error_helper>
17 #include <l4/libloader/loader>
28 Elf_phdr(void const *hdr, bool _64) : _hdr(hdr), _64(_64) {}
29 Elf32_Phdr const *hdr32() const { return (Elf32_Phdr const*)(_hdr); }
30 Elf64_Phdr const *hdr64() const { return (Elf64_Phdr const*)(_hdr); }
32 char const *phdr_type() const;
33 unsigned long type() const { return _64?hdr64()->p_type:hdr32()->p_type; }
34 unsigned long paddr() const { return _64?hdr64()->p_paddr:hdr32()->p_paddr; }
35 unsigned long vaddr() const { return _64?hdr64()->p_vaddr:hdr32()->p_vaddr; }
36 unsigned long memsz() const { return _64?hdr64()->p_memsz:hdr32()->p_memsz; }
37 unsigned long filesz() const
38 { return _64?hdr64()->p_filesz:hdr32()->p_filesz; }
39 unsigned long flags() const { return _64?hdr64()->p_flags:hdr32()->p_flags; }
40 unsigned long offset() const
41 { return _64?hdr64()->p_offset:hdr32()->p_offset; }
49 unsigned short e_type;
50 unsigned short e_machine;
53 template< typename T >
54 T element(unsigned long offset) const
55 { return reinterpret_cast<T>((unsigned long)this + offset); }
57 template< typename F >
58 void iterate_phdr(F const &func) const
60 unsigned n = num_phdrs();
61 for (unsigned i = 0; i < n; ++i)
67 return l4util_elf_check_magic((ElfW(Ehdr) *)this)
68 && l4util_elf_check_arch((ElfW(Ehdr) *)this);
74 return e_machine == EM_AMD64;
77 Elf64_Ehdr const *hdr64() const { return (Elf64_Ehdr*)this; }
78 Elf32_Ehdr const *hdr32() const { return (Elf32_Ehdr*)this; }
82 bool is_dynamic() const
85 return hdr64()->e_type == ET_DYN;
87 return hdr32()->e_type == ET_DYN;
91 Elf_phdr phdr(unsigned idx) const
94 return Elf_phdr(element<Elf_phdr const*>(hdr64()->e_phoff
95 + hdr64()->e_phentsize * idx), is_64());
97 return Elf_phdr(element<Elf_phdr const*>(hdr32()->e_phoff
98 + hdr32()->e_phentsize * idx), is_64());
102 unsigned num_phdrs() const
105 return hdr64()->e_phnum;
107 return hdr32()->e_phnum;
110 unsigned long entry() const
113 return hdr64()->e_entry;
115 return hdr32()->e_entry;
120 struct Phdr_load_min_max
122 mutable l4_addr_t start;
123 mutable l4_addr_t end;
125 Phdr_load_min_max() : start(~0UL), end(0) {}
126 void operator () (Elf_phdr const &h) const
128 if (h.type() != PT_LOAD)
131 l4_addr_t s = l4_trunc_page(h.paddr());
132 l4_addr_t e = l4_round_page(h.paddr() + h.memsz());
133 if (s < start) start = s;
134 if (e > end) end = e;
140 mutable l4_addr_t kip;
142 explicit Phdr_kip(l4_addr_t kip_default)
146 void operator () (Elf_phdr const &h) const
159 template< typename Dbg >
163 Phdr_print(Dbg const &ldr) : ldr(ldr) {}
164 void operator () (Elf_phdr const &ph) const
166 char const *pt = ph.phdr_type();
168 ldr.printf(" [%-12s]", pt);
170 ldr.printf(" [%12lx]", ph.type());
172 ldr.cprintf(" 0x%lx\t0x%lx\t0x%lx\t0x%lx\t0x%lx\t%c%c%c\n",
173 ph.offset(), ph.paddr(), ph.vaddr(), ph.filesz(),
175 (ph.flags() & PF_R) ? 'r' : '-',
176 (ph.flags() & PF_W) ? 'w' : '-',
177 (ph.flags() & PF_X) ? 'x' : '-');
182 template< typename App_model, typename Dbg >
185 typedef typename App_model::Dataspace Dataspace;
186 typedef typename App_model::Const_dataspace Const_dataspace;
194 Phdr_load(l4_addr_t base, Const_dataspace bin, App_model *mm,
195 unsigned r_flags, Dbg const &dbg)
196 : base(base), r_flags(r_flags), bin(bin), mm(mm), dbg(dbg)
199 void operator () (Elf_phdr const &ph) const
203 if (ph.type() != PT_LOAD)
209 char *paddr = (char*)(l4_trunc_page(ph.paddr()) + base);
210 l4_umword_t offs = l4_trunc_page(ph.offset());
211 l4_umword_t page_offs = ph.offset() & (L4_PAGESIZE-1);
212 l4_umword_t fsz = ph.filesz();
213 if (fsz && page_offs != (ph.paddr() & (L4_PAGESIZE-1)))
215 dbg.printf("malformed ELF file, file offset and paddr mismatch\n");
216 chksys(-L4_EINVAL, "malformed elf file");
219 l4_umword_t size = l4_round_page(ph.memsz() + page_offs);
221 if ((ph.flags() & PF_W) || ph.memsz() > fsz || mm->all_segs_cow())
224 Dataspace mem = mm->alloc_ds(size);
225 mm->prog_attach_ds(l4_addr_t(paddr), size, mem, 0, r_flags,
226 "attaching rw ELF segement");
227 mm->copy_ds(mem, 0, bin, offs, fsz + page_offs);
232 mm->prog_attach_ds(l4_addr_t(paddr), size, bin, offs,
233 r_flags | L4Re::Rm::Read_only,
234 "attaching ro ELF segement");
239 template< typename App_model >
240 struct Phdr_l4re_elf_aux_stack
242 mutable l4_size_t stack_size;
243 mutable l4_addr_t stack_addr;
245 typedef typename App_model::Const_dataspace Const_dataspace;
249 explicit Phdr_l4re_elf_aux_stack(App_model const *mm, Const_dataspace bin)
250 : stack_size(0x8000), stack_addr(0x80000000), mm(mm), bin(bin)
253 void operator () (Elf_phdr const &h) const
255 if (h.type() != PT_L4_AUX)
261 l4_addr_t addr = mm->local_attach_ds(bin, h.filesz(), h.offset());
263 l4re_elf_aux_t const *e = (l4re_elf_aux_t const *)addr;
264 l4re_elf_aux_t const *end = (l4re_elf_aux_t const *)(addr + h.filesz());
265 while (e < end && e->type)
269 case L4RE_ELF_AUX_T_STACK_SIZE:
271 l4re_elf_aux_mword_t const *v = (l4re_elf_aux_mword_t const *)e;
272 stack_size = v->value;
275 case L4RE_ELF_AUX_T_STACK_ADDR:
277 l4re_elf_aux_mword_t const *v = (l4re_elf_aux_mword_t const *)e;
278 stack_addr = v->value;
285 e = (l4re_elf_aux_t const *)((char const *)e + e->length);
288 mm->local_detach_ds(addr, h.filesz());
293 template< typename App_model >
296 typedef typename App_model::Const_dataspace Const_dataspace;
301 mutable char interp[100];
302 mutable l4_addr_t phdrs;
303 mutable bool is_dynamic;
305 Phdr_dynamic(App_model const *mm, Const_dataspace bin, l4_addr_t base)
306 : mm(mm), bin(bin), base(base), phdrs(0),
309 static char const *const addr = "rom/libld-l4.so";
311 for (i = 0; i < sizeof(interp)-1 && addr[i]; ++i)
315 void operator () (Elf_phdr const &ph) const
323 char const *addr = (char const *)mm->local_attach_ds(bin, ph.filesz(), ph.offset());
325 for (i = 0; i < sizeof(interp)-1 && addr[i]; ++i)
329 mm->local_detach_ds(l4_addr_t(addr), ph.filesz());
332 //ldr.printf(" found interpreter PHDR: interp='%s'\n", interp);
335 phdrs = base + ph.paddr();
344 template< typename App_model >
345 struct Phdr_l4re_elf_aux
347 typedef typename App_model::Const_dataspace Const_dataspace;
351 explicit Phdr_l4re_elf_aux(App_model *am, Const_dataspace bin)
355 void operator () (Elf_phdr const &h) const
358 if (h.type() != PT_L4_AUX)
363 l4_addr_t addr = am->local_attach_ds(bin, h.filesz(), h.offset());
365 l4re_elf_aux_t const *e = (l4re_elf_aux_t const *)addr;
366 l4re_elf_aux_t const *end = (l4re_elf_aux_t const *)(addr + h.filesz());
368 while (e < end && e->type)
372 case L4RE_ELF_AUX_T_VMA:
374 l4re_elf_aux_vma_t const *v = (l4re_elf_aux_vma_t const *)e;
375 l4_addr_t start = v->start;
376 chksys(am->prog_reserve_area(&start, v->end - v->start + 1, 0, 0));
383 e = (l4re_elf_aux_t const *)((char const *)e + e->length);
386 am->local_detach_ds(addr, h.filesz());
387 // L4::cap_reinterpret_cast<L4Re::Debug_obj>(r)->debug(0);
393 template< typename App_model, typename Dbg_ >
394 class Elf_loader : public Loader<App_model, Dbg_>
397 typedef Loader<App_model, Dbg_> Base;
399 typedef typename Base::Const_dataspace Const_dataspace;
400 typedef typename Base::Dbg_log Dbg_log;
402 void read_infos(App_model *mm, Const_dataspace bin,
407 Elf_ehdr const *eh = reinterpret_cast<Elf_ehdr const*>(mm->local_attach_ds(bin, L4_PAGESIZE, 0));
411 ldr.printf("file is not an ELF binary\n");
412 chksys(-L4_EINVAL, "not an ELF binary");
416 Phdr_kip stack_kip(mm->prog_info()->kip);
418 Phdr_kip stack_kip(info->stack.target_addr(), info->stack.stack_size(),
422 eh->iterate_phdr(stack_kip);
424 mm->prog_info()->kip = stack_kip.kip;
426 Phdr_l4re_elf_aux_stack<App_model> stack_info(mm, bin);
428 eh->iterate_phdr(stack_info);
429 mm->stack()->set_target_stack(stack_info.stack_addr, stack_info.stack_size);
431 ldr.printf(" PHDRs: type offset\tpaddr\tvaddr\tfilesz\tmemsz\trights\n");
432 eh->iterate_phdr(Phdr_print<Dbg_log>(ldr));
433 mm->local_detach_ds((l4_addr_t)eh, L4_PAGESIZE);
436 void load(App_model *mm, Const_dataspace bin, l4_addr_t *base,
441 Elf_ehdr const *eh = reinterpret_cast<Elf_ehdr const*>(mm->local_attach_ds(bin, L4_PAGESIZE, 0));
445 ldr.printf("file is not an ELF binary\n");
446 chksys(-L4_EINVAL, "not an ELF binary");
449 unsigned r_flags = 0;
453 Phdr_load_min_max b_func;
454 ldr.printf(" relocate PIC/PIE binary\n");
455 /* figure out size of the binary, if PIC */
456 eh->iterate_phdr(b_func);
458 ldr.printf(" all PHDRs: [0x%lx-0x%lx]\n", b_func.start, b_func.end);
461 l4_addr_t lib = _base + b_func.start;
462 chksys(mm->prog_reserve_area(&lib, b_func.end - b_func.start,
463 L4Re::Rm::Search_addr, L4_SUPERPAGESHIFT));
465 ldr.printf(" relocate to %p\n", (void*)lib);
467 _base = l4_addr_t(lib) - b_func.start;
469 ldr.printf(" PHDRs: type offset\tpaddr\tvaddr\tfilesz\tmemsz\trights\n");
470 eh->iterate_phdr(Phdr_print<Dbg_log>(ldr));
472 r_flags |= L4Re::Rm::In_area;
475 eh->iterate_phdr(Phdr_load<App_model, Dbg_log>(_base, bin, mm, r_flags, ldr));
476 eh->iterate_phdr(Phdr_l4re_elf_aux<App_model>(mm, bin));
478 mm->prog_info()->entry = eh->entry() + _base;
480 Phdr_dynamic<App_model> dyn_info(mm, bin, _base);
481 eh->iterate_phdr(dyn_info);
483 // Load the interpreter
484 if (dyn_info.is_dynamic)
486 ldr.printf(" dynamically linked executable, load interpreter '%s'\n", dyn_info.interp);
488 Const_dataspace file = mm->open_file(dyn_info.interp);
489 l4_addr_t base = 0x400000;
491 load(mm, file, &base, ldr);
493 Prog_start_info *i = mm->prog_info();
495 i->dyn_exec_entry = eh->entry() + _base;
496 i->dyn_phdrs = dyn_info.phdrs;
497 i->dyn_num_phdrs = eh->num_phdrs();
498 i->dyn_interp_base = base;
501 mm->local_detach_ds((l4_addr_t)eh, L4_PAGESIZE);
503 ldr.printf(" done...\n");
506 void load(App_model *mm, Const_dataspace bin,
509 load(mm, bin, 0, ldr);