175 lines
4.1 KiB
C
175 lines
4.1 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <signal.h>
|
||
|
#include <math.h>
|
||
|
#include <unistd.h>
|
||
|
#include <pthread.h>
|
||
|
|
||
|
// Function definitions.
|
||
|
void stack();
|
||
|
void heap();
|
||
|
void address();
|
||
|
void sigHandler(int);
|
||
|
|
||
|
/*
|
||
|
* Learned about these from:
|
||
|
* https://linux.die.net/man/3/etext
|
||
|
*/
|
||
|
extern char etext, edata, end;
|
||
|
|
||
|
// Data variables.
|
||
|
int UNINITIALIZED1;
|
||
|
int INITIALIZED1 = 0;
|
||
|
int INITIALIZED2 = 0;
|
||
|
int INITIALIZED3 = 0;
|
||
|
int UNINITIALIZED2;
|
||
|
int UNINITIALIZED3;
|
||
|
int UNINITIALIZED4;
|
||
|
int INITIALIZED4 = 0;
|
||
|
|
||
|
/**
|
||
|
* Main function for driving program.
|
||
|
*/
|
||
|
int main()
|
||
|
{
|
||
|
// Binding signal handler.
|
||
|
signal(SIGINT, sigHandler);
|
||
|
|
||
|
/*
|
||
|
* Getting addresses relating to static program segments
|
||
|
* (See man page referenced above for sample code)
|
||
|
*/
|
||
|
printf("===\n");
|
||
|
printf("First address past:\n");
|
||
|
printf("Program text (etext) %10p\n", &etext);
|
||
|
printf("Initialized data (edata) %10p\n", &edata);
|
||
|
printf("Uninitialized data (end) %10p\n", &end);
|
||
|
printf("===\n");
|
||
|
|
||
|
// Getting some initialized data addresses.
|
||
|
printf("INITIALIZED\n");
|
||
|
printf("1: %p\n", &INITIALIZED1);
|
||
|
printf("2: %p\n", &INITIALIZED2);
|
||
|
printf("3: %p\n", &INITIALIZED3);
|
||
|
printf("4: %p\n", &INITIALIZED4);
|
||
|
printf("===\n");
|
||
|
|
||
|
// Getting some unitialized data addresses.
|
||
|
printf("UNINITIALIZED\n");
|
||
|
printf("1: %p\n", &UNINITIALIZED1);
|
||
|
printf("2: %p\n", &UNINITIALIZED2);
|
||
|
printf("3: %p\n", &UNINITIALIZED3);
|
||
|
printf("4: %p\n", &UNINITIALIZED4);
|
||
|
printf("===\n");
|
||
|
|
||
|
// Adding some variables on the stack (will be stored in reverse).
|
||
|
int stackvar1 = 12313;
|
||
|
int stackvar2 = 12313;
|
||
|
int stackvar3 = 12313;
|
||
|
|
||
|
// Main stack addresses.
|
||
|
printf("Main Stack\n");
|
||
|
printf("%p\n", &stackvar1);
|
||
|
printf("%p\n", &stackvar2);
|
||
|
printf("%p\n", &stackvar3);
|
||
|
printf("===\n");
|
||
|
|
||
|
// Function stack addresses (should be lower than main).
|
||
|
printf("Function Call Stack\n");
|
||
|
stack();
|
||
|
printf("===\n");
|
||
|
|
||
|
// Printing heap addresses.
|
||
|
heap();
|
||
|
|
||
|
// Getting the address of the pow function.
|
||
|
printf("Address of pow: %p\n", &pow);
|
||
|
|
||
|
// Getting the address of the pthread_create function.
|
||
|
address();
|
||
|
|
||
|
// Pausing so we can examine headers / maps info.
|
||
|
pause();
|
||
|
|
||
|
// Probably never will reach here, but bye if we do.
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Puts some variables in the function's
|
||
|
* stack frame and prints out their addresses.
|
||
|
* Should be lower than main function's addresses,
|
||
|
* although variables seem to increase in address
|
||
|
* as we print them out (vars stored in reverse
|
||
|
* order on the stack)
|
||
|
*/
|
||
|
void stack()
|
||
|
{
|
||
|
int stackvar1 = 12313;
|
||
|
int stackvar2 = 12313;
|
||
|
int stackvar3 = 12313;
|
||
|
printf("%p\n", &stackvar1);
|
||
|
printf("%p\n", &stackvar2);
|
||
|
printf("%p\n", &stackvar3);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Asks for some heap space and prints out the
|
||
|
* locations of the memory we receive.
|
||
|
*/
|
||
|
void heap()
|
||
|
{
|
||
|
printf("Heap\n");
|
||
|
char *heap1 = malloc(16 * sizeof(char));
|
||
|
char *heap2 = malloc(32 * sizeof(char));
|
||
|
char *heap3 = malloc(64 * sizeof(char));
|
||
|
char *heap4 = malloc(128 * sizeof(char));
|
||
|
char *heap5 = malloc(256 * sizeof(char));
|
||
|
char *heap6 = malloc(512 * sizeof(char));
|
||
|
char *heap7 = malloc(1024 * sizeof(char));
|
||
|
char *heap8 = malloc(2048 * sizeof(char));
|
||
|
printf("1: %p\n", heap1);
|
||
|
printf("2: %p\n", heap2);
|
||
|
printf("3: %p\n", heap3);
|
||
|
printf("4: %p\n", heap4);
|
||
|
printf("5: %p\n", heap5);
|
||
|
printf("6: %p\n", heap6);
|
||
|
printf("7: %p\n", heap7);
|
||
|
printf("8: %p\n", heap8);
|
||
|
printf("===\n");
|
||
|
|
||
|
free(heap1);
|
||
|
free(heap2);
|
||
|
free(heap3);
|
||
|
free(heap4);
|
||
|
free(heap5);
|
||
|
free(heap6);
|
||
|
free(heap7);
|
||
|
free(heap8);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Prints a function address from a dynamic library.
|
||
|
*/
|
||
|
void address()
|
||
|
{
|
||
|
printf("Address of pthread_create: %p\n", &pthread_create);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handler for signals. Bound for the one signal handled
|
||
|
* in this application: SIGINT (program interrupt signal ^C).
|
||
|
*
|
||
|
* @param sigNum, the identifying number of the signal
|
||
|
* sent and now being handled. According to the
|
||
|
* man page for signal, SIGINT = 2.
|
||
|
*/
|
||
|
void sigHandler(int sigNum)
|
||
|
{
|
||
|
// Just exit if we ^C.
|
||
|
if (sigNum == SIGINT)
|
||
|
{
|
||
|
// Exiting program.
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|