Bumping manifests a=b2g-bump
[gecko.git] / mozglue / linker / Utils.h
blobb652d16f68b4bbd954fd3e619c5d5edafda4014f
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef Utils_h
6 #define Utils_h
8 #include <stdint.h>
9 #include <stddef.h>
10 #include <sys/mman.h>
11 #include <unistd.h>
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Scoped.h"
15 /**
16 * On architectures that are little endian and that support unaligned reads,
17 * we can use direct type, but on others, we want to have a special class
18 * to handle conversion and alignment issues.
20 #if !defined(DEBUG) && (defined(__i386__) || defined(__x86_64__))
21 typedef uint16_t le_uint16;
22 typedef uint32_t le_uint32;
23 #else
25 /**
26 * Template that allows to find an unsigned int type from a (computed) bit size
28 template <int s> struct UInt { };
29 template <> struct UInt<16> { typedef uint16_t Type; };
30 template <> struct UInt<32> { typedef uint32_t Type; };
32 /**
33 * Template to access 2 n-bit sized words as a 2*n-bit sized word, doing
34 * conversion from little endian and avoiding alignment issues.
36 template <typename T>
37 class le_to_cpu
39 public:
40 typedef typename UInt<16 * sizeof(T)>::Type Type;
42 operator Type() const
44 return (b << (sizeof(T) * 8)) | a;
47 const le_to_cpu& operator =(const Type &v)
49 a = v & ((1 << (sizeof(T) * 8)) - 1);
50 b = v >> (sizeof(T) * 8);
51 return *this;
54 le_to_cpu() { }
55 le_to_cpu(const Type &v)
57 operator =(v);
60 const le_to_cpu& operator +=(const Type &v)
62 return operator =(operator Type() + v);
65 const le_to_cpu& operator ++(int)
67 return operator =(operator Type() + 1);
70 private:
71 T a, b;
74 /**
75 * Type definitions
77 typedef le_to_cpu<unsigned char> le_uint16;
78 typedef le_to_cpu<le_uint16> le_uint32;
79 #endif
82 /**
83 * AutoCloseFD is a RAII wrapper for POSIX file descriptors
85 struct AutoCloseFDTraits
87 typedef int type;
88 static int empty() { return -1; }
89 static void release(int fd) { if (fd != -1) close(fd); }
91 typedef mozilla::Scoped<AutoCloseFDTraits> AutoCloseFD;
93 /**
94 * AutoCloseFILE is a RAII wrapper for POSIX streams
96 struct AutoCloseFILETraits
98 typedef FILE *type;
99 static FILE *empty() { return nullptr; }
100 static void release(FILE *f) { if (f) fclose(f); }
102 typedef mozilla::Scoped<AutoCloseFILETraits> AutoCloseFILE;
105 * Page alignment helpers
107 static inline size_t PageSize()
109 return 4096;
112 static inline uintptr_t AlignedPtr(uintptr_t ptr, size_t alignment)
114 return ptr & ~(alignment - 1);
117 template <typename T>
118 static inline T *AlignedPtr(T *ptr, size_t alignment)
120 return reinterpret_cast<T *>(
121 AlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
124 template <typename T>
125 static inline T PageAlignedPtr(T ptr)
127 return AlignedPtr(ptr, PageSize());
130 static inline uintptr_t AlignedEndPtr(uintptr_t ptr, size_t alignment)
132 return AlignedPtr(ptr + alignment - 1, alignment);
135 template <typename T>
136 static inline T *AlignedEndPtr(T *ptr, size_t alignment)
138 return reinterpret_cast<T *>(
139 AlignedEndPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
142 template <typename T>
143 static inline T PageAlignedEndPtr(T ptr)
145 return AlignedEndPtr(ptr, PageSize());
148 static inline size_t AlignedSize(size_t size, size_t alignment)
150 return (size + alignment - 1) & ~(alignment - 1);
153 static inline size_t PageAlignedSize(size_t size)
155 return AlignedSize(size, PageSize());
158 static inline bool IsAlignedPtr(uintptr_t ptr, size_t alignment)
160 return ptr % alignment == 0;
163 template <typename T>
164 static inline bool IsAlignedPtr(T *ptr, size_t alignment)
166 return IsAlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment);
169 template <typename T>
170 static inline bool IsPageAlignedPtr(T ptr)
172 return IsAlignedPtr(ptr, PageSize());
175 static inline bool IsAlignedSize(size_t size, size_t alignment)
177 return size % alignment == 0;
180 static inline bool IsPageAlignedSize(size_t size)
182 return IsAlignedSize(size, PageSize());
185 static inline size_t PageNumber(size_t size)
187 return (size + PageSize() - 1) / PageSize();
191 * MemoryRange stores a pointer, size pair.
193 class MemoryRange
195 public:
196 MemoryRange(void *buf, size_t length): buf(buf), length(length) { }
198 void Assign(void *b, size_t len) {
199 buf = b;
200 length = len;
203 void Assign(const MemoryRange& other) {
204 buf = other.buf;
205 length = other.length;
208 void *get() const
210 return buf;
213 operator void *() const
215 return buf;
218 operator unsigned char *() const
220 return reinterpret_cast<unsigned char *>(buf);
223 bool operator ==(void *ptr) const {
224 return buf == ptr;
227 bool operator ==(unsigned char *ptr) const {
228 return buf == ptr;
231 void *operator +(off_t offset) const
233 return reinterpret_cast<char *>(buf) + offset;
237 * Returns whether the given address is within the mapped range
239 bool Contains(void *ptr) const
241 return (ptr >= buf) && (ptr < reinterpret_cast<char *>(buf) + length);
245 * Returns the length of the mapped range
247 size_t GetLength() const
249 return length;
252 static MemoryRange mmap(void *addr, size_t length, int prot, int flags,
253 int fd, off_t offset) {
254 return MemoryRange(::mmap(addr, length, prot, flags, fd, offset), length);
257 private:
258 void *buf;
259 size_t length;
263 * MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
264 * a simple void * or unsigned char *.
266 * It is defined as a derivative of a template that allows to use a
267 * different unmapping strategy.
269 template <typename T>
270 class GenericMappedPtr: public MemoryRange
272 public:
273 GenericMappedPtr(void *buf, size_t length): MemoryRange(buf, length) { }
274 GenericMappedPtr(const MemoryRange& other): MemoryRange(other) { }
275 GenericMappedPtr(): MemoryRange(MAP_FAILED, 0) { }
277 void Assign(void *b, size_t len) {
278 if (get() != MAP_FAILED)
279 static_cast<T *>(this)->munmap(get(), GetLength());
280 MemoryRange::Assign(b, len);
283 void Assign(const MemoryRange& other) {
284 Assign(other.get(), other.GetLength());
287 ~GenericMappedPtr()
289 if (get() != MAP_FAILED)
290 static_cast<T *>(this)->munmap(get(), GetLength());
295 struct MappedPtr: public GenericMappedPtr<MappedPtr>
297 MappedPtr(void *buf, size_t length)
298 : GenericMappedPtr<MappedPtr>(buf, length) { }
299 MappedPtr(const MemoryRange& other)
300 : GenericMappedPtr<MappedPtr>(other) { }
301 MappedPtr(): GenericMappedPtr<MappedPtr>() { }
303 private:
304 friend class GenericMappedPtr<MappedPtr>;
305 void munmap(void *buf, size_t length)
307 ::munmap(buf, length);
312 * UnsizedArray is a way to access raw arrays of data in memory.
314 * struct S { ... };
315 * UnsizedArray<S> a(buf);
316 * UnsizedArray<S> b; b.Init(buf);
318 * This is roughly equivalent to
319 * const S *a = reinterpret_cast<const S *>(buf);
320 * const S *b = nullptr; b = reinterpret_cast<const S *>(buf);
322 * An UnsizedArray has no known length, and it's up to the caller to make
323 * sure the accessed memory is mapped and makes sense.
325 template <typename T>
326 class UnsizedArray
328 public:
329 typedef size_t idx_t;
332 * Constructors and Initializers
334 UnsizedArray(): contents(nullptr) { }
335 UnsizedArray(const void *buf): contents(reinterpret_cast<const T *>(buf)) { }
337 void Init(const void *buf)
339 MOZ_ASSERT(contents == nullptr);
340 contents = reinterpret_cast<const T *>(buf);
344 * Returns the nth element of the array
346 const T &operator[](const idx_t index) const
348 MOZ_ASSERT(contents);
349 return contents[index];
352 operator const T *() const
354 return contents;
357 * Returns whether the array points somewhere
359 operator bool() const
361 return contents != nullptr;
363 private:
364 const T *contents;
368 * Array, like UnsizedArray, is a way to access raw arrays of data in memory.
369 * Unlike UnsizedArray, it has a known length, and is enumerable with an
370 * iterator.
372 * struct S { ... };
373 * Array<S> a(buf, len);
374 * UnsizedArray<S> b; b.Init(buf, len);
376 * In the above examples, len is the number of elements in the array. It is
377 * also possible to initialize an Array with the buffer size:
379 * Array<S> c; c.InitSize(buf, size);
381 * It is also possible to initialize an Array in two steps, only providing
382 * one data at a time:
384 * Array<S> d;
385 * d.Init(buf);
386 * d.Init(len); // or d.InitSize(size);
389 template <typename T>
390 class Array: public UnsizedArray<T>
392 public:
393 typedef typename UnsizedArray<T>::idx_t idx_t;
396 * Constructors and Initializers
398 Array(): UnsizedArray<T>(), length(0) { }
399 Array(const void *buf, const idx_t length)
400 : UnsizedArray<T>(buf), length(length) { }
402 void Init(const void *buf)
404 UnsizedArray<T>::Init(buf);
407 void Init(const idx_t len)
409 MOZ_ASSERT(length == 0);
410 length = len;
413 void InitSize(const idx_t size)
415 Init(size / sizeof(T));
418 void Init(const void *buf, const idx_t len)
420 UnsizedArray<T>::Init(buf);
421 Init(len);
424 void InitSize(const void *buf, const idx_t size)
426 UnsizedArray<T>::Init(buf);
427 InitSize(size);
431 * Returns the nth element of the array
433 const T &operator[](const idx_t index) const
435 MOZ_ASSERT(index < length);
436 MOZ_ASSERT(operator bool());
437 return UnsizedArray<T>::operator[](index);
441 * Returns the number of elements in the array
443 idx_t numElements() const
445 return length;
449 * Returns whether the array points somewhere and has at least one element.
451 operator bool() const
453 return (length > 0) && UnsizedArray<T>::operator bool();
457 * Iterator for an Array. Use is similar to that of STL const_iterators:
459 * struct S { ... };
460 * Array<S> a(buf, len);
461 * for (Array<S>::iterator it = a.begin(); it < a.end(); ++it) {
462 * // Do something with *it.
465 class iterator
467 public:
468 iterator(): item(nullptr) { }
470 const T &operator *() const
472 return *item;
475 const T *operator ->() const
477 return item;
480 iterator &operator ++()
482 ++item;
483 return *this;
486 bool operator<(const iterator &other) const
488 return item < other.item;
490 protected:
491 friend class Array<T>;
492 iterator(const T &item): item(&item) { }
494 private:
495 const T *item;
499 * Returns an iterator pointing at the beginning of the Array
501 iterator begin() const {
502 if (length)
503 return iterator(UnsizedArray<T>::operator[](0));
504 return iterator();
508 * Returns an iterator pointing past the end of the Array
510 iterator end() const {
511 if (length)
512 return iterator(UnsizedArray<T>::operator[](length));
513 return iterator();
517 * Reverse iterator for an Array. Use is similar to that of STL
518 * const_reverse_iterators:
520 * struct S { ... };
521 * Array<S> a(buf, len);
522 * for (Array<S>::reverse_iterator it = a.rbegin(); it < a.rend(); ++it) {
523 * // Do something with *it.
526 class reverse_iterator
528 public:
529 reverse_iterator(): item(nullptr) { }
531 const T &operator *() const
533 const T *tmp = item;
534 return *--tmp;
537 const T *operator ->() const
539 return &operator*();
542 reverse_iterator &operator ++()
544 --item;
545 return *this;
548 bool operator<(const reverse_iterator &other) const
550 return item > other.item;
552 protected:
553 friend class Array<T>;
554 reverse_iterator(const T &item): item(&item) { }
556 private:
557 const T *item;
561 * Returns a reverse iterator pointing at the end of the Array
563 reverse_iterator rbegin() const {
564 if (length)
565 return reverse_iterator(UnsizedArray<T>::operator[](length));
566 return reverse_iterator();
570 * Returns a reverse iterator pointing past the beginning of the Array
572 reverse_iterator rend() const {
573 if (length)
574 return reverse_iterator(UnsizedArray<T>::operator[](0));
575 return reverse_iterator();
577 private:
578 idx_t length;
582 * Transforms a pointer-to-function to a pointer-to-object pointing at the
583 * same address.
585 template <typename T>
586 void *FunctionPtr(T func)
588 union {
589 void *ptr;
590 T func;
591 } f;
592 f.func = func;
593 return f.ptr;
596 #endif /* Utils_h */