mozglue/linker/Utils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
    19  */
    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
    27  */
    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.
    35  */
    36 template <typename T>
    37 class le_to_cpu
    38 {
    39 public:
    40   typedef typename UInt<16 * sizeof(T)>::Type Type;
    42   operator Type() const
    43   {
    44     return (b << (sizeof(T) * 8)) | a;
    45   }
    47   const le_to_cpu& operator =(const Type &v)
    48   {
    49     a = v & ((1 << (sizeof(T) * 8)) - 1);
    50     b = v >> (sizeof(T) * 8);
    51     return *this;
    52   }
    54   le_to_cpu() { }
    55   le_to_cpu(const Type &v)
    56   {
    57     operator =(v);
    58   }
    60   const le_to_cpu& operator +=(const Type &v)
    61   {
    62     return operator =(operator Type() + v);
    63   }
    65   const le_to_cpu& operator ++(int)
    66   {
    67     return operator =(operator Type() + 1);
    68   }
    70 private:
    71   T a, b;
    72 };
    74 /**
    75  * Type definitions
    76  */
    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
    84  */
    85 struct AutoCloseFDTraits
    86 {
    87   typedef int type;
    88   static int empty() { return -1; }
    89   static void release(int fd) { if (fd != -1) close(fd); }
    90 };
    91 typedef mozilla::Scoped<AutoCloseFDTraits> AutoCloseFD;
    93 /**
    94  * AutoCloseFILE is a RAII wrapper for POSIX streams
    95  */
    96 struct AutoCloseFILETraits
    97 {
    98   typedef FILE *type;
    99   static FILE *empty() { return nullptr; }
   100   static void release(FILE *f) { if (f) fclose(f); }
   101 };
   102 typedef mozilla::Scoped<AutoCloseFILETraits> AutoCloseFILE;
   104 /**
   105  * Page alignment helpers
   106  */
   107 static inline size_t PageSize()
   108 {
   109   return 4096;
   110 }
   112 static inline uintptr_t AlignedPtr(uintptr_t ptr, size_t alignment)
   113 {
   114   return ptr & ~(alignment - 1);
   115 }
   117 template <typename T>
   118 static inline T *AlignedPtr(T *ptr, size_t alignment)
   119 {
   120   return reinterpret_cast<T *>(
   121          AlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
   122 }
   124 template <typename T>
   125 static inline T PageAlignedPtr(T ptr)
   126 {
   127   return AlignedPtr(ptr, PageSize());
   128 }
   130 static inline uintptr_t AlignedEndPtr(uintptr_t ptr, size_t alignment)
   131 {
   132   return AlignedPtr(ptr + alignment - 1, alignment);
   133 }
   135 template <typename T>
   136 static inline T *AlignedEndPtr(T *ptr, size_t alignment)
   137 {
   138   return reinterpret_cast<T *>(
   139          AlignedEndPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
   140 }
   142 template <typename T>
   143 static inline T PageAlignedEndPtr(T ptr)
   144 {
   145   return AlignedEndPtr(ptr,  PageSize());
   146 }
   148 static inline size_t AlignedSize(size_t size, size_t alignment)
   149 {
   150   return (size + alignment - 1) & ~(alignment - 1);
   151 }
   153 static inline size_t PageAlignedSize(size_t size)
   154 {
   155   return AlignedSize(size, PageSize());
   156 }
   158 static inline bool IsAlignedPtr(uintptr_t ptr, size_t alignment)
   159 {
   160   return ptr % alignment == 0;
   161 }
   163 template <typename T>
   164 static inline bool IsAlignedPtr(T *ptr, size_t alignment)
   165 {
   166   return IsAlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment);
   167 }
   169 template <typename T>
   170 static inline bool IsPageAlignedPtr(T ptr)
   171 {
   172   return IsAlignedPtr(ptr, PageSize());
   173 }
   175 static inline bool IsAlignedSize(size_t size, size_t alignment)
   176 {
   177   return size % alignment == 0;
   178 }
   180 static inline bool IsPageAlignedSize(size_t size)
   181 {
   182   return IsAlignedSize(size, PageSize());
   183 }
   185 static inline size_t PageNumber(size_t size)
   186 {
   187   return (size + PageSize() - 1) / PageSize();
   188 }
   190 /**
   191  * MemoryRange stores a pointer, size pair.
   192  */
   193 class MemoryRange
   194 {
   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;
   201   }
   203   void Assign(const MemoryRange& other) {
   204     buf = other.buf;
   205     length = other.length;
   206   }
   208   void *get() const
   209   {
   210     return buf;
   211   }
   213   operator void *() const
   214   {
   215     return buf;
   216   }
   218   operator unsigned char *() const
   219   {
   220     return reinterpret_cast<unsigned char *>(buf);
   221   }
   223   bool operator ==(void *ptr) const {
   224     return buf == ptr;
   225   }
   227   bool operator ==(unsigned char *ptr) const {
   228     return buf == ptr;
   229   }
   231   void *operator +(off_t offset) const
   232   {
   233     return reinterpret_cast<char *>(buf) + offset;
   234   }
   236   /**
   237    * Returns whether the given address is within the mapped range
   238    */
   239   bool Contains(void *ptr) const
   240   {
   241     return (ptr >= buf) && (ptr < reinterpret_cast<char *>(buf) + length);
   242   }
   244   /**
   245    * Returns the length of the mapped range
   246    */
   247   size_t GetLength() const
   248   {
   249     return length;
   250   }
   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);
   255   }
   257 private:
   258   void *buf;
   259   size_t length;
   260 };
   262 /**
   263  * MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
   264  * a simple void * or unsigned char *.
   265  *
   266  * It is defined as a derivative of a template that allows to use a
   267  * different unmapping strategy.
   268  */
   269 template <typename T>
   270 class GenericMappedPtr: public MemoryRange
   271 {
   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);
   281   }
   283   void Assign(const MemoryRange& other) {
   284     Assign(other.get(), other.GetLength());
   285   }
   287   ~GenericMappedPtr()
   288   {
   289     if (get() != MAP_FAILED)
   290       static_cast<T *>(this)->munmap(get(), GetLength());
   291   }
   293 };
   295 struct MappedPtr: public GenericMappedPtr<MappedPtr>
   296 {
   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)
   306   {
   307     ::munmap(buf, length);
   308   }
   309 };
   311 /**
   312  * UnsizedArray is a way to access raw arrays of data in memory.
   313  *
   314  *   struct S { ... };
   315  *   UnsizedArray<S> a(buf);
   316  *   UnsizedArray<S> b; b.Init(buf);
   317  *
   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);
   321  *
   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.
   324  */
   325 template <typename T>
   326 class UnsizedArray
   327 {
   328 public:
   329   typedef size_t idx_t;
   331   /**
   332    * Constructors and Initializers
   333    */
   334   UnsizedArray(): contents(nullptr) { }
   335   UnsizedArray(const void *buf): contents(reinterpret_cast<const T *>(buf)) { }
   337   void Init(const void *buf)
   338   {
   339     MOZ_ASSERT(contents == nullptr);
   340     contents = reinterpret_cast<const T *>(buf);
   341   }
   343   /**
   344    * Returns the nth element of the array
   345    */
   346   const T &operator[](const idx_t index) const
   347   {
   348     MOZ_ASSERT(contents);
   349     return contents[index];
   350   }
   352   operator const T *() const
   353   {
   354     return contents;
   355   }
   356   /**
   357    * Returns whether the array points somewhere
   358    */
   359   operator bool() const
   360   {
   361     return contents != nullptr;
   362   }
   363 private:
   364   const T *contents;
   365 };
   367 /**
   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.
   371  *
   372  *   struct S { ... };
   373  *   Array<S> a(buf, len);
   374  *   UnsizedArray<S> b; b.Init(buf, len);
   375  *
   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:
   378  *
   379  *   Array<S> c; c.InitSize(buf, size);
   380  *
   381  * It is also possible to initialize an Array in two steps, only providing
   382  * one data at a time:
   383  *
   384  *   Array<S> d;
   385  *   d.Init(buf);
   386  *   d.Init(len); // or d.InitSize(size);
   387  *
   388  */
   389 template <typename T>
   390 class Array: public UnsizedArray<T>
   391 {
   392 public:
   393   typedef typename UnsizedArray<T>::idx_t idx_t;
   395   /**
   396    * Constructors and Initializers
   397    */
   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)
   403   {
   404     UnsizedArray<T>::Init(buf);
   405   }
   407   void Init(const idx_t len)
   408   {
   409     MOZ_ASSERT(length == 0);
   410     length = len;
   411   }
   413   void InitSize(const idx_t size)
   414   {
   415     Init(size / sizeof(T));
   416   }
   418   void Init(const void *buf, const idx_t len)
   419   {
   420     UnsizedArray<T>::Init(buf);
   421     Init(len);
   422   }
   424   void InitSize(const void *buf, const idx_t size)
   425   {
   426     UnsizedArray<T>::Init(buf);
   427     InitSize(size);
   428   }
   430   /**
   431    * Returns the nth element of the array
   432    */
   433   const T &operator[](const idx_t index) const
   434   {
   435     MOZ_ASSERT(index < length);
   436     MOZ_ASSERT(operator bool());
   437     return UnsizedArray<T>::operator[](index);
   438   }
   440   /**
   441    * Returns the number of elements in the array
   442    */
   443   idx_t numElements() const
   444   {
   445     return length;
   446   }
   448   /**
   449    * Returns whether the array points somewhere and has at least one element.
   450    */
   451   operator bool() const
   452   {
   453     return (length > 0) && UnsizedArray<T>::operator bool();
   454   }
   456   /**
   457    * Iterator for an Array. Use is similar to that of STL const_iterators:
   458    *
   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.
   463    *   }
   464    */
   465   class iterator
   466   {
   467   public:
   468     iterator(): item(nullptr) { }
   470     const T &operator *() const
   471     {
   472       return *item;
   473     }
   475     const T *operator ->() const
   476     {
   477       return item;
   478     }
   480     iterator &operator ++()
   481     {
   482       ++item;
   483       return *this;
   484     }
   486     bool operator<(const iterator &other) const
   487     {
   488       return item < other.item;
   489     }
   490   protected:
   491     friend class Array<T>;
   492     iterator(const T &item): item(&item) { }
   494   private:
   495     const T *item;
   496   };
   498   /**
   499    * Returns an iterator pointing at the beginning of the Array
   500    */
   501   iterator begin() const {
   502     if (length)
   503       return iterator(UnsizedArray<T>::operator[](0));
   504     return iterator();
   505   }
   507   /**
   508    * Returns an iterator pointing past the end of the Array
   509    */
   510   iterator end() const {
   511     if (length)
   512       return iterator(UnsizedArray<T>::operator[](length));
   513     return iterator();
   514   }
   516   /**
   517    * Reverse iterator for an Array. Use is similar to that of STL
   518    * const_reverse_iterators:
   519    *
   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.
   524    *   }
   525    */
   526   class reverse_iterator
   527   {
   528   public:
   529     reverse_iterator(): item(nullptr) { }
   531     const T &operator *() const
   532     {
   533       const T *tmp = item;
   534       return *--tmp;
   535     }
   537     const T *operator ->() const
   538     {
   539       return &operator*();
   540     }
   542     reverse_iterator &operator ++()
   543     {
   544       --item;
   545       return *this;
   546     }
   548     bool operator<(const reverse_iterator &other) const
   549     {
   550       return item > other.item;
   551     }
   552   protected:
   553     friend class Array<T>;
   554     reverse_iterator(const T &item): item(&item) { }
   556   private:
   557     const T *item;
   558   };
   560   /**
   561    * Returns a reverse iterator pointing at the end of the Array
   562    */
   563   reverse_iterator rbegin() const {
   564     if (length)
   565       return reverse_iterator(UnsizedArray<T>::operator[](length));
   566     return reverse_iterator();
   567   }
   569   /**
   570    * Returns a reverse iterator pointing past the beginning of the Array
   571    */
   572   reverse_iterator rend() const {
   573     if (length)
   574       return reverse_iterator(UnsizedArray<T>::operator[](0));
   575     return reverse_iterator();
   576   }
   577 private:
   578   idx_t length;
   579 };
   581 /**
   582  * Transforms a pointer-to-function to a pointer-to-object pointing at the
   583  * same address.
   584  */
   585 template <typename T>
   586 void *FunctionPtr(T func)
   587 {
   588   union {
   589     void *ptr;
   590     T func;
   591   } f;
   592   f.func = func;
   593   return f.ptr;
   594 }
   596 #endif /* Utils_h */

mercurial