18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#ifndef _GNU_SOURCE
38c2ecf20Sopenharmony_ci#define _GNU_SOURCE
48c2ecf20Sopenharmony_ci#endif
58c2ecf20Sopenharmony_ci#include <link.h>
68c2ecf20Sopenharmony_ci#include <stdio.h>
78c2ecf20Sopenharmony_ci#include <stdlib.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistruct Statistics {
108c2ecf20Sopenharmony_ci	unsigned long long load_address;
118c2ecf20Sopenharmony_ci	unsigned long long alignment;
128c2ecf20Sopenharmony_ci};
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciint ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	struct Statistics *stats = (struct Statistics *) data;
178c2ecf20Sopenharmony_ci	int i;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') {
208c2ecf20Sopenharmony_ci		// Ignore headers from other than the executable.
218c2ecf20Sopenharmony_ci		return 2;
228c2ecf20Sopenharmony_ci	}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	stats->load_address = (unsigned long long) info->dlpi_addr;
258c2ecf20Sopenharmony_ci	stats->alignment = 0;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	for (i = 0; i < info->dlpi_phnum; i++) {
288c2ecf20Sopenharmony_ci		if (info->dlpi_phdr[i].p_type != PT_LOAD)
298c2ecf20Sopenharmony_ci			continue;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci		if (info->dlpi_phdr[i].p_align > stats->alignment)
328c2ecf20Sopenharmony_ci			stats->alignment = info->dlpi_phdr[i].p_align;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	return 1;  // Terminate dl_iterate_phdr.
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ciint main(int argc, char **argv)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	struct Statistics extracted;
418c2ecf20Sopenharmony_ci	unsigned long long misalign;
428c2ecf20Sopenharmony_ci	int ret;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	ret = dl_iterate_phdr(ExtractStatistics, &extracted);
458c2ecf20Sopenharmony_ci	if (ret != 1) {
468c2ecf20Sopenharmony_ci		fprintf(stderr, "FAILED\n");
478c2ecf20Sopenharmony_ci		return 1;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (extracted.alignment == 0) {
518c2ecf20Sopenharmony_ci		fprintf(stderr, "No alignment found\n");
528c2ecf20Sopenharmony_ci		return 1;
538c2ecf20Sopenharmony_ci	} else if (extracted.alignment & (extracted.alignment - 1)) {
548c2ecf20Sopenharmony_ci		fprintf(stderr, "Alignment is not a power of 2\n");
558c2ecf20Sopenharmony_ci		return 1;
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	misalign = extracted.load_address & (extracted.alignment - 1);
598c2ecf20Sopenharmony_ci	if (misalign) {
608c2ecf20Sopenharmony_ci		printf("alignment = %llu, load_address = %llu\n",
618c2ecf20Sopenharmony_ci			extracted.alignment, extracted.load_address);
628c2ecf20Sopenharmony_ci		fprintf(stderr, "FAILED\n");
638c2ecf20Sopenharmony_ci		return 1;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	fprintf(stderr, "PASS\n");
678c2ecf20Sopenharmony_ci	return 0;
688c2ecf20Sopenharmony_ci}
69