162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci#ifndef _GNU_SOURCE
362306a36Sopenharmony_ci#define _GNU_SOURCE
462306a36Sopenharmony_ci#endif
562306a36Sopenharmony_ci#include <link.h>
662306a36Sopenharmony_ci#include <stdio.h>
762306a36Sopenharmony_ci#include <stdlib.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct Statistics {
1062306a36Sopenharmony_ci	unsigned long long load_address;
1162306a36Sopenharmony_ci	unsigned long long alignment;
1262306a36Sopenharmony_ci};
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciint ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct Statistics *stats = (struct Statistics *) data;
1762306a36Sopenharmony_ci	int i;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') {
2062306a36Sopenharmony_ci		// Ignore headers from other than the executable.
2162306a36Sopenharmony_ci		return 2;
2262306a36Sopenharmony_ci	}
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	stats->load_address = (unsigned long long) info->dlpi_addr;
2562306a36Sopenharmony_ci	stats->alignment = 0;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	for (i = 0; i < info->dlpi_phnum; i++) {
2862306a36Sopenharmony_ci		if (info->dlpi_phdr[i].p_type != PT_LOAD)
2962306a36Sopenharmony_ci			continue;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci		if (info->dlpi_phdr[i].p_align > stats->alignment)
3262306a36Sopenharmony_ci			stats->alignment = info->dlpi_phdr[i].p_align;
3362306a36Sopenharmony_ci	}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	return 1;  // Terminate dl_iterate_phdr.
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ciint main(int argc, char **argv)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct Statistics extracted;
4162306a36Sopenharmony_ci	unsigned long long misalign;
4262306a36Sopenharmony_ci	int ret;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	ret = dl_iterate_phdr(ExtractStatistics, &extracted);
4562306a36Sopenharmony_ci	if (ret != 1) {
4662306a36Sopenharmony_ci		fprintf(stderr, "FAILED\n");
4762306a36Sopenharmony_ci		return 1;
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (extracted.alignment == 0) {
5162306a36Sopenharmony_ci		fprintf(stderr, "No alignment found\n");
5262306a36Sopenharmony_ci		return 1;
5362306a36Sopenharmony_ci	} else if (extracted.alignment & (extracted.alignment - 1)) {
5462306a36Sopenharmony_ci		fprintf(stderr, "Alignment is not a power of 2\n");
5562306a36Sopenharmony_ci		return 1;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	misalign = extracted.load_address & (extracted.alignment - 1);
5962306a36Sopenharmony_ci	if (misalign) {
6062306a36Sopenharmony_ci		printf("alignment = %llu, load_address = %llu\n",
6162306a36Sopenharmony_ci			extracted.alignment, extracted.load_address);
6262306a36Sopenharmony_ci		fprintf(stderr, "FAILED\n");
6362306a36Sopenharmony_ci		return 1;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	fprintf(stderr, "PASS\n");
6762306a36Sopenharmony_ci	return 0;
6862306a36Sopenharmony_ci}
69