2.9 Memory.
(((char)&v)+3));
};
After running it we get:
root@debian-mips:~# ./a.out
00 00 00 7B
That is it. 0x7B is 123 in decimal. In little-endian architectures, 7B is the first byte (you can check on x86
or x86-64), but here it is the last one, because the highest byte goes first.
That’swhythereareseparateLinuxdistributionsforMIPS(“mips”(big-endian)and“mipsel”(little-endian)).
It is impossible for a binary compiled for one endianness to work on anOSwith different endianness.
There is another example of MIPS big-endiannes in this book:1.24.4 on page 365.
2.8.4 Bi-endian.
CPUs that may switch between endianness are ARM, PowerPC, SPARC, MIPS,IA64^24 , etc.
2.8.5 Converting data
TheBSWAPinstruction can be used for conversion.
TCP/IP network data packets use the big-endian conventions, so that is why a program working on a little-
endian architecture has to convert the values. Thehtonl()andhtons()functions are usually used.
In TCP/IP, big-endian is also called “network byte order”, while byte order on the computer “host byte
order”. “host byte order” is little-endian on Intel x86 and other little-endian architectures, but it is big-
endian on IBM POWER, sohtonl()andhtons()don’t shuffle any bytes on the latter.
2.9 Memory
There are 3 main types of memory:
- Global memoryAKA“static memory allocation”. No need to allocate explicitly, the allocation is
performed just by declaring variables/arrays globally. These are global variables, residing in the
data or constant segments. They are available globally (hence, considered as ananti-pattern). Not
convenient for buffers/arrays, because they must have a fixed size. Buffer overflows that occur here
usually overwrite variables or buffers residing next to them in memory. There’s an example in this
book:1.9.3 on page 76. - StackAKA“allocate on stack”. The allocation is performed just by declaring variables/arrays locally
in the function. These are usually local variables for the function. Sometimes these local variable
are also available to descending functions (tocalleefunctions, if caller passes a pointer to a variable
to thecalleeto be executed). Allocation and deallocation are very fast, it justSPneeds to be shifted.
But they’re also not convenient for buffers/arrays, because the buffer size has to be fixed, unless
alloca()(1.7.2 on page 35) (or a variable-length array) is used. Buffer overflows usually overwrite
important stack structures:1.20.2 on page 275.
- HeapAKA“dynamic memory allocation”. Allocation/deallocation is performed by calling
malloc()/free()ornew/deletein C++. This is the most convenient method: the block size may
be set at runtime.
Resizing is possible (usingrealloc()), but can be slow. This is the slowest way to allocate memory:
thememoryallocatormustsupportandupdateallcontrolstructureswhileallocatinganddeallocating.
Buffer overflows usually overwrite these structures. Heap allocations are also source of memory leak
problems: each memory block has to be deallocated explicitly, but one may forget about it, or do it
incorrectly.
(^24) Intel Architecture 64 (Itanium)