1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
4 *     economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU Lesser General Public License 2.1.
7 * Please see the COPYING-LGPL-2.1 file for details.
8 */
9#pragma once
10
11#include <l4/sys/types.h>
12#include <l4/re/l4aux.h>
13#include <cstddef>
14#include <l4/libloader/stack>
15
16namespace Ldr {
17
18struct Mem_check_ok
19{ void check_access(char *, size_t) {} };
20
21template< typename Mem_check = Mem_check_ok>
22class Remote_stack : public Ldr::Stack, public Mem_check
23{
24public:
25
26  void access_ok(char *p, size_t sz)
27  {
28    // for downward growing stack first subtract the size
29    Mem_check::check_access(p - sz, sz);
30  }
31
32  explicit Remote_stack(char *p = 0) : _target_top(0), _top(p), _p(p) {}
33  char *ptr() const { return _p; }
34  void ptr(char *p) { _p = p; }
35  void set_target_stack(l4_addr_t addr, l4_size_t size)
36  { _target_top = addr + size; _size = size; }
37
38  template < typename T >
39  T relocate(T src) const
40  { return (T)(l4_addr_t(src) + (_target_top - l4_addr_t(_top))); }
41
42  char const *push_str(char const *s, size_t len);
43  char *push_object(void const *o, unsigned long size);
44
45  template< typename T >
46  T *push(T const &v)
47  {
48    access_ok(_p, sizeof(T));
49    T *p = reinterpret_cast<T*>(_p);
50    *(--p) = v;
51    _p = reinterpret_cast<char*>(p);
52    return p;
53  }
54
55  void align(unsigned long size)
56  {
57    l4_addr_t p = l4_addr_t(_p);
58    unsigned bits;
59    for (bits = 0; (1UL << bits) <= size; ++bits)
60      ;
61
62    p &= ~0UL << bits;
63    _p = (char *)p;
64  }
65
66  void const **push_local_ptr(void const *p)
67  {
68    void const *x = relocate(p);
69    return push(x);
70  }
71
72  l4_addr_t target_ptr() const { return relocate(l4_addr_t(_p)); }
73  l4_addr_t target_top() const { return _target_top; }
74  l4_addr_t target_addr() const { return _target_top - _size; }
75  l4_size_t stack_size() const { return _size; }
76  void set_local_top(char *top)
77  { _top = top; _p = top; }
78
79private:
80  l4_addr_t _target_top;
81  l4_size_t _size;
82  char *_top;
83  char *_p;
84};
85
86
87template<typename Mem_check>
88char const *
89Remote_stack<Mem_check>::push_str(char const *s, size_t len)
90{
91  access_ok(_p, len + 1);
92  _p -= len + 1;
93  __builtin_memcpy(_p, s, len);
94  _p[len] = 0;
95
96  return _p;
97}
98
99template<typename Mem_check>
100char *
101Remote_stack<Mem_check>::push_object(void const *o, unsigned long size)
102{
103  access_ok(_p, size);
104  _p -= size;
105  __builtin_memcpy(_p, o, size);
106  return _p;
107}
108
109};
110