You can read the file /proc/self/maps
and parse the first three fields of each line:
<begin-addr>-<end-addr> rwxp ...
Then you search the line that contains the address you are looking for and check the permissions:
r-x
: it is code;rw-
: it is writable data;r--
: it is read-only data;- any other combination: something weird (
rwxp
: generated code, ...).
For example the following program:
#include <stdio.h>
void foo() {}
int x;
int main()
{
int y;
printf("%p\n%p\n%p\n", foo, &x, &y);
scanf("%*s");
return 0;
}
...in my system gives this output:
0x400570
0x6009e4
0x7fff4c9b4e2c
...and these are the relevant lines from /proc/<pid>/maps
:
00400000-00401000 r-xp 00000000 00:1d 641656 /tmp/a.out
00600000-00601000 rw-p 00000000 00:1d 641656 /tmp/a.out
....
7fff4c996000-7fff4c9b7000 rw-p 00000000 00:00 0 [stack]
....
So the addresses are: code, data and data.