⛏️ index : haiku.git

/*
 * Copyright 2015 Simon South, ssouth@simonsouth.com
 * All rights reserved. Distributed under the terms of the MIT License.
 */


#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <image.h>
#include <OS.h>


struct sbrk_test {
	char *name;
	char *sbrk_arg_text;
	intptr_t sbrk_arg;
};


static void
output_area_info(void *base_address)
{
	uint8_t *next_area_address;
	area_id next_area;
	area_info next_area_info;

	next_area = area_for(base_address);
	while (next_area != B_ERROR) {
		if (get_area_info(next_area, &next_area_info) == B_OK) {
			next_area_address = (uint8_t *)(next_area_info.address)
				+ next_area_info.size;

			printf("Area ID 0x%x: Addr: %p - %p  Size: 0x%04zx  %s\n",
				next_area_info.area, next_area_info.address,
				next_area_address - 1, next_area_info.size,
				next_area_info.name);

			next_area = area_for(next_area_address);
		} else {
			fprintf(stderr, "PROBLEM: Couldn't get area info");
		}
	}
}


static void
output_data_segment_info(void *address)
{
	puts("Current data segment layout:");
	output_area_info(address);
	puts("");
}


static void
output_sbrk_result(intptr_t sbrk_arg, char *sbrk_arg_text)
{
	printf("\tsbrk(%s) returns %p\n", sbrk_arg_text, sbrk(sbrk_arg));
	if (errno != 0) {
		printf("\tError: %s\n", strerror(errno));
		errno = 0;
	}
}


int
main(int argc, char **argv)
{
	static const uint NUM_TESTS = 7;
	static struct sbrk_test sbrk_tests[] = {
		{ "Get current program break",                     "0",      0 },

		{ "Expand data segment (less than one page)",  "0x7ff",  0x7ff },
		{ "Expand data segment (more than one page)", "0x57ff", 0x57ff },
		{
			"Expand data segment (unreasonable value)",
			"INTPTR_MAX",
			 INTPTR_MAX
		},

		{ "Shrink data segment (less than one page)",  "-0x7ff",  -0x7ff },
		{ "Shrink data segment (more than one page)", "-0x27ff", -0x27ff },
		{
			"Shrink data segment (unreasonable value)",
			"INTPTR_MIN",
			 INTPTR_MIN
		}
	};

	int result = -1;

	bool app_image_found = false;
	image_info i_info;
	int32 image_cookie = 0;

	void *data_segment_address = NULL;

	uint test_index;
	struct sbrk_test *next_sbrk_test;

	/* Find the address of our data segment */
	while (!app_image_found
		&& get_next_image_info(0, &image_cookie, &i_info) == B_OK) {
		if (i_info.type == B_APP_IMAGE) {
			app_image_found = true;

			data_segment_address = i_info.data;
		}
	}

	if (data_segment_address != NULL) {
		/* Run our tests */
		test_index = 0;
		while (test_index < NUM_TESTS) {
			next_sbrk_test = &sbrk_tests[test_index];

			output_data_segment_info(data_segment_address);
			printf("%s:\n", next_sbrk_test->name);
			output_sbrk_result(next_sbrk_test->sbrk_arg,
				next_sbrk_test->sbrk_arg_text);
			printf("\n");

			test_index += 1;
		}

		output_data_segment_info(data_segment_address);

		result = 0;
	} else {
		fprintf(stderr, "PROBLEM: Couldn't locate data segment\n");
	}

	return result;
}