1/*
2 * Copyright 2015 Simon South, ssouth@simonsouth.com
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7#include <errno.h>
8#include <stdint.h>
9#include <stdio.h>
10#include <string.h>
11#include <unistd.h>
12
13#include <image.h>
14#include <OS.h>
15
16
17struct sbrk_test {
18	char *name;
19	char *sbrk_arg_text;
20	intptr_t sbrk_arg;
21};
22
23
24static void
25output_area_info(void *base_address)
26{
27	uint8_t *next_area_address;
28	area_id next_area;
29	area_info next_area_info;
30
31	next_area = area_for(base_address);
32	while (next_area != B_ERROR) {
33		if (get_area_info(next_area, &next_area_info) == B_OK) {
34			next_area_address = (uint8_t *)(next_area_info.address)
35				+ next_area_info.size;
36
37			printf("Area ID 0x%x: Addr: %p - %p  Size: 0x%04zx  %s\n",
38				next_area_info.area, next_area_info.address,
39				next_area_address - 1, next_area_info.size,
40				next_area_info.name);
41
42			next_area = area_for(next_area_address);
43		} else {
44			fprintf(stderr, "PROBLEM: Couldn't get area info");
45		}
46	}
47}
48
49
50static void
51output_data_segment_info(void *address)
52{
53	puts("Current data segment layout:");
54	output_area_info(address);
55	puts("");
56}
57
58
59static void
60output_sbrk_result(intptr_t sbrk_arg, char *sbrk_arg_text)
61{
62	printf("\tsbrk(%s) returns %p\n", sbrk_arg_text, sbrk(sbrk_arg));
63	if (errno != 0) {
64		printf("\tError: %s\n", strerror(errno));
65		errno = 0;
66	}
67}
68
69
70int
71main(int argc, char **argv)
72{
73	static const uint NUM_TESTS = 7;
74	static struct sbrk_test sbrk_tests[] = {
75		{ "Get current program break",                     "0",      0 },
76
77		{ "Expand data segment (less than one page)",  "0x7ff",  0x7ff },
78		{ "Expand data segment (more than one page)", "0x57ff", 0x57ff },
79		{
80			"Expand data segment (unreasonable value)",
81			"INTPTR_MAX",
82			 INTPTR_MAX
83		},
84
85		{ "Shrink data segment (less than one page)",  "-0x7ff",  -0x7ff },
86		{ "Shrink data segment (more than one page)", "-0x27ff", -0x27ff },
87		{
88			"Shrink data segment (unreasonable value)",
89			"INTPTR_MIN",
90			 INTPTR_MIN
91		}
92	};
93
94	int result = -1;
95
96	bool app_image_found = false;
97	image_info i_info;
98	int32 image_cookie = 0;
99
100	void *data_segment_address = NULL;
101
102	uint test_index;
103	struct sbrk_test *next_sbrk_test;
104
105	/* Find the address of our data segment */
106	while (!app_image_found
107		&& get_next_image_info(0, &image_cookie, &i_info) == B_OK) {
108		if (i_info.type == B_APP_IMAGE) {
109			app_image_found = true;
110
111			data_segment_address = i_info.data;
112		}
113	}
114
115	if (data_segment_address != NULL) {
116		/* Run our tests */
117		test_index = 0;
118		while (test_index < NUM_TESTS) {
119			next_sbrk_test = &sbrk_tests[test_index];
120
121			output_data_segment_info(data_segment_address);
122			printf("%s:\n", next_sbrk_test->name);
123			output_sbrk_result(next_sbrk_test->sbrk_arg,
124				next_sbrk_test->sbrk_arg_text);
125			printf("\n");
126
127			test_index += 1;
128		}
129
130		output_data_segment_info(data_segment_address);
131
132		result = 0;
133	} else {
134		fprintf(stderr, "PROBLEM: Couldn't locate data segment\n");
135	}
136
137	return result;
138}
139