This is a Linux brainteaser for the C comfortable and leisurely bored. I'm not looking for the answer..
Note the compile lines are commented at the bottom of the program - Ubuntu and derivatives please use the second compile line or it will not work.
So what does this program do? This program, when compiled and run, will display the addresses and values of the array myint[] plus the addresses and values of my calculated addresses...So why does this work? Why does two different memory regions appear to have the same data?
Disclaimer – I can't guarantee this will work on every Linux distro out there but it should work on most Intel/AMDs.
#include <stdio.h>
#include <stdlib.h>
unsigned long myint[] = {
111111,
222222,
333333,
444444,
555555,
666666,
777777,
888888,
999999
};
int main(int argc, char**argv)
{
int i = 0;
/*calculate our address from main and myint*/
void *textaddr = (void*)((unsigned long)&main & ((0UL - 1UL) ^ 0xfff));
void *dataoff = (void*)((unsigned long)&myint & 0xfff);
/*our new address which has the values of myint*/
unsigned long *ans = (unsigned long*)((unsigned long)dataoff + (unsigned long)textaddr);
for (i = 0; i < 9; ++i)
{
fprintf(stdout, "ans->%lu addr->%p\n", *(ans + i) ,(void*)(ans + i));
}
fprintf(stdout, "The values/address of the array myint!\n");
for (i = 0; i < 9; ++i)
{
fprintf(stdout, "ans->%lu addr->%p\n",myint[i] , (void*)&myint[i]);
}
exit(EXIT_SUCCESS);
}
compile lines
Most linux distros Mandriva, Arch, Slackware etc can use this compile line
gcc linuxmem.c -Wall -ansi -pedantic -o linuxmem
Ubuntu and derivatives
gcc linuxmem.c -Wall -ansi -pedantic -z norelro -o linuxmem
My output
ans->111111 addr->0x400ac0
ans->222222 addr->0x400ac8
ans->333333 addr->0x400ad0
ans->444444 addr->0x400ad8
ans->555555 addr->0x400ae0
ans->666666 addr->0x400ae8
ans->777777 addr->0x400af0
ans->888888 addr->0x400af8
ans->999999 addr->0x400b00
The values/address of the array myint!
ans->111111 addr->0x600ac0
ans->222222 addr->0x600ac8
ans->333333 addr->0x600ad0
ans->444444 addr->0x600ad8
ans->555555 addr->0x600ae0
ans->666666 addr->0x600ae8
ans->777777 addr->0x600af0
ans->888888 addr->0x600af8
ans->999999 addr->0x600b00